From 5e346e7c0a9735b1a8cdef9b3801306921cd9f8d Mon Sep 17 00:00:00 2001 From: Michael Teeuw Date: Mon, 1 Jan 2024 15:43:38 +0100 Subject: [PATCH 001/418] Start of 2.27.0 develop branch. --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e4625d28b..940b775c9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ This project adheres to [Semantic Versioning](https://semver.org/). ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror². +## [2.27.0] - Develop Branch (unreleased) + +_This release is scheduled to be released on 2024-04-01._ + +### Added + +### Updated + +### Fixed + +### Deleted + ## [2.26.0] - 01-01-2024 Thanks to: @bnitkin, @bugsounet, @dependabot, @jkriegshauser, @kaennchenstruggle, @KristjanESPERANTO and @Ybbet. diff --git a/package-lock.json b/package-lock.json index 4d56f2d023..adba08219d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.26.0", + "version": "2.27.0-develop", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.26.0", + "version": "2.27.0-develop", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 6d5206975f..20c8333c06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.26.0", + "version": "2.27.0-develop", "description": "The open source modular smart mirror platform.", "main": "js/electron.js", "scripts": { From 367d02f1b67ab08a50318563fa0f36f4d410653b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 1 Jan 2024 21:56:13 +0100 Subject: [PATCH 002/418] Update URLs to MagicMirrorOrg (#3321) --- CHANGELOG.md | 134 +++++++++--------- Collaboration.md | 2 +- README.md | 10 +- fonts/package.json | 4 +- js/app.js | 4 +- js/defaults.js | 2 +- modules/default/clock/clock.js | 4 +- .../default/updatenotification/git_helper.js | 2 +- .../updatenotification/updatenotification.js | 2 +- package.json | 6 +- .../unit/functions/updatenotification_spec.js | 16 +-- vendor/package.json | 4 +- 12 files changed, 95 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 940b775c9f..5be3f84373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -664,12 +664,12 @@ Special thanks to the following contributors: @bryanzzhu, @bugsounet, @chamakura ### Fixed - Fix backward compatibility issues for Safari < 11. -- Fix the use of "maxNumberOfDays" in the module "weatherforecast depending on the endpoint (forecast/daily or forecast)". [#2018](https://github.com/MichMich/MagicMirror/issues/2018) -- Fix calendar display. Account for current timezone. [#2068](https://github.com/MichMich/MagicMirror/issues/2068) +- Fix the use of "maxNumberOfDays" in the module "weatherforecast depending on the endpoint (forecast/daily or forecast)". [#2018](https://github.com/MagicMirrorOrg/MagicMirror/issues/2018) +- Fix calendar display. Account for current timezone. [#2068](https://github.com/MagicMirrorOrg/MagicMirror/issues/2068) - Fix logLevel being set before loading config. -- Fix incorrect namespace links in svg clockfaces. [#2072](https://github.com/MichMich/MagicMirror/issues/2072) -- Fix weather/providers/weathergov for API guidelines. [#2045](https://github.com/MichMich/MagicMirror/issues/2045) -- Fix "undefined" in weather modules header. [#1985](https://github.com/MichMich/MagicMirror/issues/1985) +- Fix incorrect namespace links in svg clockfaces. [#2072](https://github.com/MagicMirrorOrg/MagicMirror/issues/2072) +- Fix weather/providers/weathergov for API guidelines. [#2045](https://github.com/MagicMirrorOrg/MagicMirror/issues/2045) +- Fix "undefined" in weather modules header. [#1985](https://github.com/MagicMirrorOrg/MagicMirror/issues/1985) - Fix #2110, #2111, #2118: Recurring full day events should not use timezone adjustment. Just compare month/day. ## [2.12.0] - 2020-07-01 @@ -703,14 +703,14 @@ Special thanks to the following contributors: @AndreKoepke, @andrezibaia, @bryan ### Fixed -- The broken modules due to Socket.io change from last release. [#1973](https://github.com/MichMich/MagicMirror/issues/1973) -- Add backward compatibility for old module code in socketclient.js. [#1973](https://github.com/MichMich/MagicMirror/issues/1973) -- Support multiple instances of calendar module with different config. [#1109](https://github.com/MichMich/MagicMirror/issues/1109) -- Fix the use of "maxNumberOfDays" in the module "weatherforecast". [#2018](https://github.com/MichMich/MagicMirror/issues/2018) -- Throw error when check_config fails. [#1928](https://github.com/MichMich/MagicMirror/issues/1928) -- Bug fix related to 'maxEntries' not displaying Calendar events. [#2050](https://github.com/MichMich/MagicMirror/issues/2050) -- Updated ical library to the latest version. [#1926](https://github.com/MichMich/MagicMirror/issues/1926) -- Fix config check after merge of prettier [#2109](https://github.com/MichMich/MagicMirror/issues/2109) +- The broken modules due to Socket.io change from last release. [#1973](https://github.com/MagicMirrorOrg/MagicMirror/issues/1973) +- Add backward compatibility for old module code in socketclient.js. [#1973](https://github.com/MagicMirrorOrg/MagicMirror/issues/1973) +- Support multiple instances of calendar module with different config. [#1109](https://github.com/MagicMirrorOrg/MagicMirror/issues/1109) +- Fix the use of "maxNumberOfDays" in the module "weatherforecast". [#2018](https://github.com/MagicMirrorOrg/MagicMirror/issues/2018) +- Throw error when check_config fails. [#1928](https://github.com/MagicMirrorOrg/MagicMirror/issues/1928) +- Bug fix related to 'maxEntries' not displaying Calendar events. [#2050](https://github.com/MagicMirrorOrg/MagicMirror/issues/2050) +- Updated ical library to the latest version. [#1926](https://github.com/MagicMirrorOrg/MagicMirror/issues/1926) +- Fix config check after merge of prettier [#2109](https://github.com/MagicMirrorOrg/MagicMirror/issues/2109) ## [2.11.0] - 2020-04-01 @@ -718,7 +718,7 @@ Special thanks to the following contributors: @AndreKoepke, @andrezibaia, @bryan In the past years the project has grown a lot. This came with a huge downside: poor maintainability. If I let the project continue the way it was, it would eventually crash and burn. More important: I would completely lose the drive and interest to continue the project. Because of this the decision was made to simplify the core by removing all side features like automatic installers and support for exotic platforms. This release (2.11.0) is the first real release that will reflect (parts) of these changes. As a result of this, some things might break. So before you continue make sure to backup your installation. Your config, your modules or better yet: your full MagicMirror² folder. In other words: update at your own risk. -For more information regarding this major change, please check issue [#1860](https://github.com/MichMich/MagicMirror/issues/1860). +For more information regarding this major change, please check issue [#1860](https://github.com/MagicMirrorOrg/MagicMirror/issues/1860). ### Deleted @@ -748,8 +748,8 @@ For more information regarding this major change, please check issue [#1860](htt - Fix calendar time offset for recurring events crossing Daylight Savings Time (ISSUE #1798) - Fix regression in currentweather module causing 'undefined' to show up when config.hideTemp is false - Fix FEELS translation for Croatian -- Fixed weather tests [#1840](https://github.com/MichMich/MagicMirror/issues/1840) -- Fixed Socket.io can't be used with Reverse Proxy in serveronly mode [#1934](https://github.com/MichMich/MagicMirror/issues/1934) +- Fixed weather tests [#1840](https://github.com/MagicMirrorOrg/MagicMirror/issues/1840) +- Fixed Socket.io can't be used with Reverse Proxy in serveronly mode [#1934](https://github.com/MagicMirrorOrg/MagicMirror/issues/1934) - Fix update checking skipping 3rd party modules the first time ### Changed @@ -817,14 +817,14 @@ Special thanks to @sdetweil for all his great contributions! - Updatenotification module: Display update notification for a limited (configurable) time. - Enabled e2e/vendor_spec.js tests. -- The css/custom.css will be renamed after the next release. We've added into `run-start.sh` an instruction by GIT to ignore with `--skip-worktree` and `rm --cached`. [#1540](https://github.com/MichMich/MagicMirror/issues/1540) +- The css/custom.css will be renamed after the next release. We've added into `run-start.sh` an instruction by GIT to ignore with `--skip-worktree` and `rm --cached`. [#1540](https://github.com/MagicMirrorOrg/MagicMirror/issues/1540) - Disable sending of notification CLOCK_SECOND when displaySeconds is false. ### Fixed - Updatenotification module: Properly handle race conditions, prevent crash. - Send `NEWS_FEED` notification also for the first news messages which are shown. -- Fixed issue where weather module would not refresh data after a network or API outage. [#1722](https://github.com/MichMich/MagicMirror/issues/1722) +- Fixed issue where weather module would not refresh data after a network or API outage. [#1722](https://github.com/MagicMirrorOrg/MagicMirror/issues/1722) - Fixed weatherforecast module not displaying rain amount on fallback endpoint. - Notifications CLOCK_SECOND & CLOCK_MINUTE being from startup instead of matched against the clock and avoid drifting. @@ -839,7 +839,7 @@ Special thanks to @sdetweil for all his great contributions! - Russian translation for “Feels” - Calendar module: added `nextDaysRelative` config option - Add `broadcastPastEvents` config option for calendars to include events from the past `maximumNumberOfDays` in event broadcasts -- Added feature to broadcast news feed items `NEWS_FEED` and updated news items `NEWS_FEED_UPDATED` in default [newsfeed](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/newsfeed) module (when news is updated) with documented default and `config.js` options in [README.md](https://github.com/MichMich/MagicMirror/blob/develop/modules/default/newsfeed/README.md) +- Added feature to broadcast news feed items `NEWS_FEED` and updated news items `NEWS_FEED_UPDATED` in default [newsfeed](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules/default/newsfeed) module (when news is updated) with documented default and `config.js` options in [README.md](https://github.com/MagicMirrorOrg/MagicMirror/blob/develop/modules/default/newsfeed/README.md) - Added notifications to default `clock` module broadcasting `CLOCK_SECOND` and `CLOCK_MINUTE` for the respective time elapsed. - Added UK Met Office Datapoint feed as a provider in the default weather module. - Added new provider class @@ -848,7 +848,7 @@ Special thanks to @sdetweil for all his great contributions! - Use Feels Like temp from feed if present - Optionally display probability of precipitation (PoP) in current weather (UK Met Office data) - Automatically try to fix eslint errors by passing `--fix` option to it -- Added sunrise and sunset times to weathergov weather-provider [#1705](https://github.com/MichMich/MagicMirror/issues/1705) +- Added sunrise and sunset times to weathergov weather-provider [#1705](https://github.com/MagicMirrorOrg/MagicMirror/issues/1705) - Added "useLocationAsHeader" to display "location" in `config.js` as header when location name is not returned - Added to `newsfeed.js`: in order to design the news article better with css, three more class-names were introduced: newsfeed-desc, newsfeed-desc, newsfeed-desc @@ -857,18 +857,18 @@ Special thanks to @sdetweil for all his great contributions! - English translation for "Feels" to "Feels like" - Fixed the example calendar url in `config.js.sample` - Updated `ical.js` to solve various calendar issues. -- Updated weather city list url [#1676](https://github.com/MichMich/MagicMirror/issues/1676) +- Updated weather city list url [#1676](https://github.com/MagicMirrorOrg/MagicMirror/issues/1676) - Only update clock once per minute when seconds aren't shown - Updated weather-provider documentation. ### Fixed - Fixed uncaught exception, race condition on module update -- Fixed issue [#1696](https://github.com/MichMich/MagicMirror/issues/1696), some ical files start date to not parse to date type +- Fixed issue [#1696](https://github.com/MagicMirrorOrg/MagicMirror/issues/1696), some ical files start date to not parse to date type - Allowance HTML5 autoplay-policy (policy is changed from Chrome 66 updates) - Handle SIGTERM messages - Fixes sliceMultiDayEvents so it respects maximumNumberOfDays -- Minor types in default NewsFeed [README.md](https://github.com/MichMich/MagicMirror/blob/develop/modules/default/newsfeed/README.md) +- Minor types in default NewsFeed [README.md](https://github.com/MagicMirrorOrg/MagicMirror/blob/develop/modules/default/newsfeed/README.md) - Fix typos and small syntax errors, cleanup dependencies, remove multiple-empty-lines, add semi-rule - Fixed issues with calendar not displaying one-time changes to repeating events - Updated the fetchedLocationName variable in currentweather.js so that city shows up in the header @@ -906,41 +906,41 @@ Fixed `package.json` version number. ### Updated -- Bumped the Electron dependency to v3.0.13 to support the most recent Raspbian. [#1500](https://github.com/MichMich/MagicMirror/issues/1500) +- Bumped the Electron dependency to v3.0.13 to support the most recent Raspbian. [#1500](https://github.com/MagicMirrorOrg/MagicMirror/issues/1500) - Updated modernizr code in alert module, fixed a small typo there too - More verbose error message on console if the config is malformed - Updated installer script to install Node.js version 10.x ### Fixed -- Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MichMich/MagicMirror/issues/1503), [#1511](https://github.com/MichMich/MagicMirror/issues/1511). -- Fixed unhandled error on bad git data in updatenotification module [#1285](https://github.com/MichMich/MagicMirror/issues/1285). -- Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MichMich/MagicMirror/issues/1504). +- Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MagicMirrorOrg/MagicMirror/issues/1503), [#1511](https://github.com/MagicMirrorOrg/MagicMirror/issues/1511). +- Fixed unhandled error on bad git data in updatenotification module [#1285](https://github.com/MagicMirrorOrg/MagicMirror/issues/1285). +- Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MagicMirrorOrg/MagicMirror/issues/1504). - Fixed analogue clock border display issue where non-black backgrounds used (previous fix for issue 611) -- Fixed compatibility issues caused when modules request different versions of Font Awesome, see issue [#1522](https://github.com/MichMich/MagicMirror/issues/1522). MagicMirror² now uses [Font Awesome 5 with v4 shims included for backwards compatibility](https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4#shims). +- Fixed compatibility issues caused when modules request different versions of Font Awesome, see issue [#1522](https://github.com/MagicMirrorOrg/MagicMirror/issues/1522). MagicMirror² now uses [Font Awesome 5 with v4 shims included for backwards compatibility](https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4#shims). - Installation script problems with raspbian -- Calendar: only show repeating count if the event is actually repeating [#1534](https://github.com/MichMich/MagicMirror/pull/1534) +- Calendar: only show repeating count if the event is actually repeating [#1534](https://github.com/MagicMirrorOrg/MagicMirror/pull/1534) - Calendar: Fix exdate handling when multiple values are specified (comma separated) -- Calendar: Fix relative date handling for fulldate events, calculate difference always from start of day [#1572](https://github.com/MichMich/MagicMirror/issues/1572) +- Calendar: Fix relative date handling for fulldate events, calculate difference always from start of day [#1572](https://github.com/MagicMirrorOrg/MagicMirror/issues/1572) - Fix null dereference in moduleNeedsUpdate when the module isn't visible - Calendar: Fixed event end times by setting default calendarEndTime to "LT" (Local time format). [#1479] -- Calendar: Fixed missing calendar fetchers after server process restarts [#1589](https://github.com/MichMich/MagicMirror/issues/1589) +- Calendar: Fixed missing calendar fetchers after server process restarts [#1589](https://github.com/MagicMirrorOrg/MagicMirror/issues/1589) - Notification: fixed background color (was white text on white background) - Use getHeader instead of data.header when creating the DOM so overwriting the function also propagates into it - Fix documentation of `useKMPHwind` option in currentweather ### New weather module -- Fixed weather forecast table display [#1499](https://github.com/MichMich/MagicMirror/issues/1499). +- Fixed weather forecast table display [#1499](https://github.com/MagicMirrorOrg/MagicMirror/issues/1499). - Dimmed loading indicator for weather forecast. -- Implemented config option `decimalSymbol` [#1499](https://github.com/MichMich/MagicMirror/issues/1499). -- Aligned indoor values in current weather vertical [#1499](https://github.com/MichMich/MagicMirror/issues/1499). +- Implemented config option `decimalSymbol` [#1499](https://github.com/MagicMirrorOrg/MagicMirror/issues/1499). +- Aligned indoor values in current weather vertical [#1499](https://github.com/MagicMirrorOrg/MagicMirror/issues/1499). - Added humidity support to nunjuck unit filter. -- Do not display degree symbol for temperature in Kelvin [#1503](https://github.com/MichMich/MagicMirror/issues/1503). -- Weather forecast now works with openweathermap for both, `/forecast` and `/forecast/daily`, in new weather module. If you use the `/forecast`-weatherEndpoint, the hourly data are converted to daily data, see issues [#1504](https://github.com/MichMich/MagicMirror/issues/1504), [#1513](https://github.com/MichMich/MagicMirror/issues/1513). -- Added fade, fadePoint and maxNumberOfDays properties to the forecast mode [#1516](https://github.com/MichMich/MagicMirror/issues/1516) -- Fixed Loading string and decimalSymbol string replace [#1538](https://github.com/MichMich/MagicMirror/issues/1538) -- Show Snow amounts in new weather module [#1545](https://github.com/MichMich/MagicMirror/issues/1545) +- Do not display degree symbol for temperature in Kelvin [#1503](https://github.com/MagicMirrorOrg/MagicMirror/issues/1503). +- Weather forecast now works with openweathermap for both, `/forecast` and `/forecast/daily`, in new weather module. If you use the `/forecast`-weatherEndpoint, the hourly data are converted to daily data, see issues [#1504](https://github.com/MagicMirrorOrg/MagicMirror/issues/1504), [#1513](https://github.com/MagicMirrorOrg/MagicMirror/issues/1513). +- Added fade, fadePoint and maxNumberOfDays properties to the forecast mode [#1516](https://github.com/MagicMirrorOrg/MagicMirror/issues/1516) +- Fixed Loading string and decimalSymbol string replace [#1538](https://github.com/MagicMirrorOrg/MagicMirror/issues/1538) +- Show Snow amounts in new weather module [#1545](https://github.com/MagicMirrorOrg/MagicMirror/issues/1545) - Added weather.gov as a new weather-provider for US locations ## [2.6.0] - 2019-01-01 @@ -965,7 +965,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Screenshot for the weather forecast module - Portuguese translation for "Feels" - Croatian translation -- Fading for dateheaders timeFormat in Calendar [#1464](https://github.com/MichMich/MagicMirror/issues/1464) +- Fading for dateheaders timeFormat in Calendar [#1464](https://github.com/MagicMirrorOrg/MagicMirror/issues/1464) - Documentation for the existing `scale` option in the Weather Forecast module. ### Fixed @@ -974,7 +974,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Fixed Polish translation for Single Update Info - Ignore entries with unparseable details in the calendar module - Bug showing FullDayEvents one day too long in calendar fixed -- Bug in newsfeed when `removeStartTags` is used on the description [#1478](https://github.com/MichMich/MagicMirror/issues/1478) +- Bug in newsfeed when `removeStartTags` is used on the description [#1478](https://github.com/MagicMirrorOrg/MagicMirror/issues/1478) ### Updated @@ -1007,7 +1007,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Fixed mixup between german and spanish translation for newsfeed. - Fixed close dates to be absolute, if no configured in the config.js - module Calendar - Fixed the updatenotification module message about new commits in the repository, so they can be correctly localized in singular and plural form. -- Fix for weatherforecast rainfall rounding [#1374](https://github.com/MichMich/MagicMirror/issues/1374) +- Fix for weatherforecast rainfall rounding [#1374](https://github.com/MagicMirrorOrg/MagicMirror/issues/1374) - Fix calendar parsing issue for Midori on RasperryPi Zero w, related to issue #694. - Fix weather city ID link in sample config - Fixed issue with clientonly not updating with IP address and port provided on command line. @@ -1029,7 +1029,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ## [2.4.0] - 2018-07-01 -⚠️ **Warning:** This release includes an updated version of Electron. This requires a Raspberry Pi configuration change to allow the best performance and prevent the CPU from overheating. Please read the information on the [MagicMirror² Wiki](https://github.com/michmich/magicmirror/wiki/configuring-the-raspberry-pi#enable-the-open-gl-driver-to-decrease-electrons-cpu-usage). +⚠️ **Warning:** This release includes an updated version of Electron. This requires a Raspberry Pi configuration change to allow the best performance and prevent the CPU from overheating. Please read the information on the [MagicMirror² Wiki](https://github.com/MagicMirrorOrg/MagicMirror/wiki/configuring-the-raspberry-pi#enable-the-open-gl-driver-to-decrease-electrons-cpu-usage). ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install` @@ -1051,20 +1051,20 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Upgrade to Electron 2.0.0. - Remove yarn-or-npm which breaks production builds. -- Invoke module suspend even if no dom content. [#1308](https://github.com/MichMich/MagicMirror/issues/1308) +- Invoke module suspend even if no dom content. [#1308](https://github.com/MagicMirrorOrg/MagicMirror/issues/1308) ### Fixed -- Fixed issue where wind chill could not be displayed in Fahrenheit. [#1247](https://github.com/MichMich/MagicMirror/issues/1247) -- Fixed issues where a module crashes when it tries to dismiss a non existing alert. [#1240](https://github.com/MichMich/MagicMirror/issues/1240) +- Fixed issue where wind chill could not be displayed in Fahrenheit. [#1247](https://github.com/MagicMirrorOrg/MagicMirror/issues/1247) +- Fixed issues where a module crashes when it tries to dismiss a non existing alert. [#1240](https://github.com/MagicMirrorOrg/MagicMirror/issues/1240) - In default module currentWeather/currentWeather.js line 296, 300, self.config.animationSpeed can not be found because the notificationReceived function does not have "self" variable. - Fixed browser-side code to work on the Midori browser. -- Fixed issue where heat index was reporting incorrect values in Celsius and Fahrenheit. [#1263](https://github.com/MichMich/MagicMirror/issues/1263) +- Fixed issue where heat index was reporting incorrect values in Celsius and Fahrenheit. [#1263](https://github.com/MagicMirrorOrg/MagicMirror/issues/1263) - Fixed weatherforecast to use dt_txt field instead of dt to handle timezones better -- Newsfeed now remembers to show the description when `"ARTICLE_LESS_DETAILS"` is called if the user wants to always show the description. [#1282](https://github.com/MichMich/MagicMirror/issues/1282) +- Newsfeed now remembers to show the description when `"ARTICLE_LESS_DETAILS"` is called if the user wants to always show the description. [#1282](https://github.com/MagicMirrorOrg/MagicMirror/issues/1282) - `clientonly/*.js` is now linted, and one linting error is fixed - Fix issue #1196 by changing underscore to hyphen in locale id, in align with momentjs. -- Fixed issue where heat index and wind chill were reporting incorrect values in Kelvin. [#1263](https://github.com/MichMich/MagicMirror/issues/1263) +- Fixed issue where heat index and wind chill were reporting incorrect values in Kelvin. [#1263](https://github.com/MagicMirrorOrg/MagicMirror/issues/1263) ### Updated @@ -1076,7 +1076,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Fixed -- Downgrade electron to 1.4.15 to solve the black screen issue.[#1243](https://github.com/MichMich/MagicMirror/issues/1243) +- Downgrade electron to 1.4.15 to solve the black screen issue.[#1243](https://github.com/MagicMirrorOrg/MagicMirror/issues/1243) ## [2.3.0] - 2018-04-01 @@ -1202,8 +1202,8 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Changed -- Revert Docker related changes in favor of [docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror). All Docker images are outsourced. ([#856](https://github.com/MichMich/MagicMirror/pull/856)) -- Change Docker base image (Debian + Node) to an arm based distro (AlpineARM + Node) ([#846](https://github.com/MichMich/MagicMirror/pull/846)) +- Revert Docker related changes in favor of [docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror). All Docker images are outsourced. ([#856](https://github.com/MagicMirrorOrg/MagicMirror/pull/856)) +- Change Docker base image (Debian + Node) to an arm based distro (AlpineARM + Node) ([#846](https://github.com/MagicMirrorOrg/MagicMirror/pull/846)) - Fix the dockerfile to have it running from the first time. ### Added @@ -1250,7 +1250,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Add `anytime` group for Compliments module. - Compliments module can use remoteFile without default daytime arrays defined. - Installer: Use init config.js from config.js.sample. -- Switched out `rrule` package for `rrule-alt` and fixes in `ical.js` in order to fix calendar issues. ([#565](https://github.com/MichMich/MagicMirror/issues/565)) +- Switched out `rrule` package for `rrule-alt` and fixes in `ical.js` in order to fix calendar issues. ([#565](https://github.com/MagicMirrorOrg/MagicMirror/issues/565)) - Make mouse events pass through the region fullscreen_above to modules below. - Scaled the splash screen down to make it a bit more subtle. - Replace HTML tables with markdown tables in README files. @@ -1263,7 +1263,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Added -- Added Docker support (Pull Request [#673](https://github.com/MichMich/MagicMirror/pull/673)). +- Added Docker support (Pull Request [#673](https://github.com/MagicMirrorOrg/MagicMirror/pull/673)). - Calendar-specific support for `maximumEntries`, and `maximumNumberOfDays`. - Add loaded function to modules, providing an async callback. - Made default newsfeed module aware of gesture events from [MMM-Gestures](https://github.com/thobach/MMM-Gestures) @@ -1309,7 +1309,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Updated .gitignore to not ignore default modules folder. - Remove white flash on boot up. - Added `update` in Raspberry Pi installation script. -- Fix an issue where the analog clock looked scrambled. ([#611](https://github.com/MichMich/MagicMirror/issues/611)) +- Fix an issue where the analog clock looked scrambled. ([#611](https://github.com/MagicMirrorOrg/MagicMirror/issues/611)) - If units are set to imperial, the showRainAmount option of weatherforecast will show the correct unit. - Module currentWeather: check if temperature received from api is defined. - Fix an issue with module hidden status changing to `true` although lock string prevented showing it. @@ -1326,18 +1326,18 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Finnish translation. - Danish translation. - Turkish translation. -- Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MichMich/MagicMirror/issues/456)). +- Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MagicMirrorOrg/MagicMirror/issues/456)). - Added ability to change the point of time when calendar events get relative. - Add Splash screen on boot. - Add option to show humidity in currentWeather module. - Add VSCode IntelliSense support. -- Module API: Add Visibility locking to module system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information. -- Module API: Method to overwrite the module's header. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) for more information. -- Module API: Option to define the minimum MagicMirror² version to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresversion) for more information. -- Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/calendar) for more information. -- Possibility to use the calendar feed as the source for the weather (currentweather & weatherforecast) location data. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/weatherforecast) for more information. +- Module API: Add Visibility locking to module system. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules#visibility-locking) for more information. +- Module API: Method to overwrite the module's header. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules#getheader) for more information. +- Module API: Option to define the minimum MagicMirror² version to run a module. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules#requiresversion) for more information. +- Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules/default/calendar) for more information. +- Possibility to use the calendar feed as the source for the weather (currentweather & weatherforecast) location data. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules/default/weatherforecast) for more information. - Added option to show rain amount in the weatherforecast default module -- Add module `updatenotification` to get an update whenever a new version is available. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/updatenotification) for more information. +- Add module `updatenotification` to get an update whenever a new version is available. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules/default/updatenotification) for more information. - Add the ability to set timezone on the date display in the Clock Module - Ability to set date format in calendar module - Possibility to use currentweather for the compliments @@ -1407,11 +1407,11 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Fixed - Prevent `getModules()` selectors from returning duplicate entries. -- Append endpoints of weather modules with `/` to retrieve the correct data. (Issue [#337](https://github.com/MichMich/MagicMirror/issues/337)) +- Append endpoints of weather modules with `/` to retrieve the correct data. (Issue [#337](https://github.com/MagicMirrorOrg/MagicMirror/issues/337)) - Corrected grammar in `module.js` from 'suspend' to 'suspended'. - Fixed openweathermap.org URL in config sample. - Prevent currentweather module from crashing when received data object is incorrect. -- Fix issue where translation loading prevented the UI start-up when the language was set to 'en'. (Issue [#388](https://github.com/MichMich/MagicMirror/issues/388)) +- Fix issue where translation loading prevented the UI start-up when the language was set to 'en'. (Issue [#388](https://github.com/MagicMirrorOrg/MagicMirror/issues/388)) ### Updated @@ -1431,8 +1431,8 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Fixed -- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MichMich/MagicMirror/issues/300)) -- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MichMich/MagicMirror/issues/319)) +- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MagicMirrorOrg/MagicMirror/issues/300)) +- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MagicMirrorOrg/MagicMirror/issues/319)) ### Changed @@ -1449,7 +1449,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Fixed - Added reference to Italian Translation. -- Added the missing NE translation to all languages. [#344](https://github.com/MichMich/MagicMirror/issues/344) +- Added the missing NE translation to all languages. [#344](https://github.com/MagicMirrorOrg/MagicMirror/issues/344) - Added proper User-Agent string to calendar call. ### Changed diff --git a/Collaboration.md b/Collaboration.md index 079a355419..100bbf95cb 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -15,4 +15,4 @@ This document describes how collaborators of this repository should work togethe ## Releases -- are done by @MichMich only +Are done by @rejas or @khassel. diff --git a/README.md b/README.md index 2437c6b66e..0221b79f40 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ License - GitHub Actions - Build Status - - + GitHub Actions + Build Status + +

-**MagicMirror²** is an open source modular smart mirror platform. With a growing list of installable modules, the **MagicMirror²** allows you to convert your hallway or bathroom mirror into your personal assistant. **MagicMirror²** is built by the creator of [the original MagicMirror](https://michaelteeuw.nl/tagged/magicmirror) with the incredible help of a [growing community of contributors](https://github.com/MichMich/MagicMirror/graphs/contributors). +**MagicMirror²** is an open source modular smart mirror platform. With a growing list of installable modules, the **MagicMirror²** allows you to convert your hallway or bathroom mirror into your personal assistant. **MagicMirror²** is built by the creator of [the original MagicMirror](https://michaelteeuw.nl/tagged/magicmirror) with the incredible help of a [growing community of contributors](https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors). MagicMirror² focuses on a modular plugin system and uses [Electron](https://www.electronjs.org/) as an application wrapper. So no more web server or browser installs necessary! diff --git a/fonts/package.json b/fonts/package.json index 5761f94f40..7dd6fd2516 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -3,11 +3,11 @@ "description": "Package for fonts use by MagicMirror² Core.", "repository": { "type": "git", - "url": "git+https://github.com/MichMich/MagicMirror.git" + "url": "git+https://github.com/MagicMirrorOrg/MagicMirror.git" }, "license": "MIT", "bugs": { - "url": "https://github.com/MichMich/MagicMirror/issues" + "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" }, "dependencies": { "@fontsource/roboto": "^5.0.8", diff --git a/js/app.js b/js/app.js index 3957ef933d..eabdf73112 100644 --- a/js/app.js +++ b/js/app.js @@ -29,7 +29,7 @@ if (process.env.MM_CONFIG_FILE) { } // FIXME: Hotfix Pull Request -// https://github.com/MichMich/MagicMirror/pull/673 +// https://github.com/MagicMirrorOrg/MagicMirror/pull/673 if (process.env.MM_PORT) { global.mmPort = process.env.MM_PORT; } @@ -40,7 +40,7 @@ process.on("uncaughtException", function (err) { Log.error("Whoops! There was an uncaught exception..."); Log.error(err); Log.error("MagicMirror² will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?"); - Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MichMich/MagicMirror/issues"); + Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MagicMirrorOrg/MagicMirror/issues"); }); /** diff --git a/js/defaults.js b/js/defaults.js index c8f849587b..ce49bf5bee 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -26,7 +26,7 @@ const defaults = { zoom: 1, customCss: "css/custom.css", // httpHeaders used by helmet, see https://helmetjs.github.io/. You can add other/more object values by overriding this in config.js, - // e.g. you need to add `frameguard: false` for embedding MagicMirror in another website, see https://github.com/MichMich/MagicMirror/issues/2847 + // e.g. you need to add `frameguard: false` for embedding MagicMirror in another website, see https://github.com/MagicMirrorOrg/MagicMirror/issues/2847 httpHeaders: { contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false }, // properties for checking if server is alive and has same startup-timestamp, the check is per default enabled diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 6b4ae32412..549026eaef 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -129,7 +129,7 @@ Module.register("clock", { // Set content of wrappers. // The moment().format("h") method has a bug on the Raspberry Pi. // So we need to generate the timestring manually. - // See issue: https://github.com/MichMich/MagicMirror/issues/181 + // See issue: https://github.com/MagicMirrorOrg/MagicMirror/issues/181 let timeString; const now = moment(); if (this.config.timezone) { @@ -247,7 +247,7 @@ Module.register("clock", { analogWrapper.style.background = `url(${this.data.path}faces/${this.config.analogFace}.svg)`; analogWrapper.style.backgroundSize = "100%"; - // The following line solves issue: https://github.com/MichMich/MagicMirror/issues/611 + // The following line solves issue: https://github.com/MagicMirrorOrg/MagicMirror/issues/611 // analogWrapper.style.border = "1px solid black"; analogWrapper.style.border = "rgba(0, 0, 0, 0.1)"; //Updated fix for Issue 611 where non-black backgrounds are used } else if (this.config.analogFace !== "none") { diff --git a/modules/default/updatenotification/git_helper.js b/modules/default/updatenotification/git_helper.js index 8efe478d13..8243c43a7b 100644 --- a/modules/default/updatenotification/git_helper.js +++ b/modules/default/updatenotification/git_helper.js @@ -128,7 +128,7 @@ class GitHelper { const { stderr } = await this.execShell(`cd ${repo.folder} && git fetch -n --dry-run`); // example output: - // From https://github.com/MichMich/MagicMirror + // From https://github.com/MagicMirrorOrg/MagicMirror // e40ddd4..06389e3 develop -> origin/develop // here the result is in stderr (this is a git default, don't ask why ...) const matches = stderr.match(this.getRefRegex(gitInfo.current)); diff --git a/modules/default/updatenotification/updatenotification.js b/modules/default/updatenotification/updatenotification.js index 7c5f595a79..eb5528e114 100644 --- a/modules/default/updatenotification/updatenotification.js +++ b/modules/default/updatenotification/updatenotification.js @@ -102,7 +102,7 @@ Module.register("updatenotification", { const localRef = status.hash; const remoteRef = status.tracking.replace(/.*\//, ""); - return `${text}`; + return `${text}`; }); }, diff --git a/package.json b/package.json index 20c8333c06..f9c44ae7c3 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/MichMich/MagicMirror.git" + "url": "git+https://github.com/MagicMirrorOrg/MagicMirror.git" }, "keywords": [ "magic mirror", @@ -41,11 +41,11 @@ ], "author": "Michael Teeuw", "contributors": [ - "https://github.com/MichMich/MagicMirror/graphs/contributors" + "https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors" ], "license": "MIT", "bugs": { - "url": "https://github.com/MichMich/MagicMirror/issues" + "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" }, "homepage": "https://magicmirror.builders", "devDependencies": { diff --git a/tests/unit/functions/updatenotification_spec.js b/tests/unit/functions/updatenotification_spec.js index b36592c4ba..102c533744 100644 --- a/tests/unit/functions/updatenotification_spec.js +++ b/tests/unit/functions/updatenotification_spec.js @@ -75,10 +75,10 @@ describe("Updatenotification", () => { const moduleName = "MagicMirror"; beforeEach(async () => { - gitRemoteOut = "origin\tgit@github.com:MichMich/MagicMirror.git (fetch)\norigin\tgit@github.com:MichMich/MagicMirror.git (push)\n"; + gitRemoteOut = "origin\tgit@github.com:MagicMirrorOrg/MagicMirror.git (fetch)\norigin\tgit@github.com:MagicMirrorOrg/MagicMirror.git (push)\n"; gitRevParseOut = "332e429a41f1a2339afd4f0ae96dd125da6beada"; gitStatusOut = "## develop...origin/develop\n M tests/unit/functions/updatenotification_spec.js\n"; - gitFetchErr = "From github.com:MichMich/MagicMirror\n60e0377..332e429 develop -> origin/develop\n"; + gitFetchErr = "From github.com:MagicMirrorOrg/MagicMirror\n60e0377..332e429 develop -> origin/develop\n"; gitRevListCountOut = "5"; await gitHelper.add(moduleName); @@ -114,10 +114,10 @@ describe("Updatenotification", () => { const moduleName = "MagicMirror"; beforeEach(async () => { - gitRemoteOut = "origin\tgit@github.com:MichMich/MagicMirror.git (fetch)\norigin\tgit@github.com:MichMich/MagicMirror.git (push)\n"; + gitRemoteOut = "origin\tgit@github.com:MagicMirrorOrg/MagicMirror.git (fetch)\norigin\tgit@github.com:MagicMirrorOrg/MagicMirror.git (push)\n"; gitRevParseOut = "332e429a41f1a2339afd4f0ae96dd125da6beada"; gitStatusOut = "## master...origin/master\n M tests/unit/functions/updatenotification_spec.js\n"; - gitFetchErr = "From github.com:MichMich/MagicMirror\n60e0377..332e429 master -> origin/master\n"; + gitFetchErr = "From github.com:MagicMirrorOrg/MagicMirror\n60e0377..332e429 master -> origin/master\n"; gitRevListCountOut = "5"; await gitHelper.add(moduleName); @@ -153,10 +153,10 @@ describe("Updatenotification", () => { const moduleName = "MagicMirror"; beforeEach(async () => { - gitRemoteOut = "origin\tgit@github.com:MichMich/MagicMirror.git (fetch)\norigin\tgit@github.com:MichMich/MagicMirror.git (push)\n"; + gitRemoteOut = "origin\tgit@github.com:MagicMirrorOrg/MagicMirror.git (fetch)\norigin\tgit@github.com:MagicMirrorOrg/MagicMirror.git (push)\n"; gitRevParseOut = "332e429a41f1a2339afd4f0ae96dd125da6beada"; gitStatusOut = "## master...origin/master\n M tests/unit/functions/updatenotification_spec.js\n"; - gitFetchErr = "From github.com:MichMich/MagicMirror\n60e0377..332e429 master -> origin/master\n"; + gitFetchErr = "From github.com:MagicMirrorOrg/MagicMirror\n60e0377..332e429 master -> origin/master\n"; gitRevListCountOut = "5"; gitTagListOut = "332e429a41f1a2339afd4f0ae96dd125da6beada...tag...\n"; gitRevListOut = "332e429a41f1a2339afd4f0ae96dd125da6beada\n"; @@ -194,10 +194,10 @@ describe("Updatenotification", () => { const moduleName = "MagicMirror"; beforeEach(async () => { - gitRemoteOut = "origin\tgit@github.com:MichMich/MagicMirror.git (fetch)\norigin\tgit@github.com:MichMich/MagicMirror.git (push)\n"; + gitRemoteOut = "origin\tgit@github.com:MagicMirrorOrg/MagicMirror.git (fetch)\norigin\tgit@github.com:MagicMirrorOrg/MagicMirror.git (push)\n"; gitRevParseOut = "332e429a41f1a2339afd4f0ae96dd125da6beada"; gitStatusOut = "## master...origin/master\n M tests/unit/functions/updatenotification_spec.js\n"; - gitFetchErr = "From github.com:MichMich/MagicMirror\n60e0377..332e429 master -> origin/master\n"; + gitFetchErr = "From github.com:MagicMirrorOrg/MagicMirror\n60e0377..332e429 master -> origin/master\n"; gitRevListCountOut = "5"; gitTagListOut = "xxxe429a41f1a2339afd4f0ae96dd125da6beada...tag...\n"; gitRevListOut = "332e429a41f1a2339afd4f0ae96dd125da6beada\n"; diff --git a/vendor/package.json b/vendor/package.json index f42eca66ff..d3182f20b4 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -3,11 +3,11 @@ "description": "Package for vendors use by MagicMirror² Core.", "repository": { "type": "git", - "url": "git+https://github.com/MichMich/MagicMirror.git" + "url": "git+https://github.com/MagicMirrorOrg/MagicMirror.git" }, "license": "MIT", "bugs": { - "url": "https://github.com/MichMich/MagicMirror/issues" + "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" }, "dependencies": { "@fortawesome/fontawesome-free": "^6.5.1", From ae1f9d04688bbdc3e4fd1bae32b78e021e201d6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 22:03:25 +0100 Subject: [PATCH 003/418] Bump moment-timezone from 0.5.43 to 0.5.44 in /vendor (#3317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [moment-timezone](https://github.com/moment/moment-timezone) from 0.5.43 to 0.5.44.
Release notes

Sourced from moment-timezone's releases.

Release 0.5.44

  • Updated data to IANA TZDB 2023d.
  • Fixed .valueOf() to return NaN for invalid zoned objects (matching default moment) #1082.
  • Performance improvements:
    • Use binary search when looking up zone information #720.
    • Avoid redundant checks in tz.guess().
    • Avoid redundant getZone() calls in .tz().
Changelog

Sourced from moment-timezone's changelog.

0.5.44 2023-12-29

  • Updated data to IANA TZDB 2023d.
  • Fixed .valueOf() to return NaN for invalid zoned objects (matching default moment) #1082.
  • Performance improvements:
    • Use binary search when looking up zone information #720.
    • Avoid redundant checks in tz.guess().
    • Avoid redundant getZone() calls in .tz().
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=moment-timezone&package-manager=npm_and_yarn&previous-version=0.5.43&new-version=0.5.44)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- vendor/package-lock.json | 8 ++++---- vendor/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 4b8ad7add0..c20e2d49bd 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -10,7 +10,7 @@ "@fortawesome/fontawesome-free": "^6.5.1", "animate.css": "^4.1.1", "moment": "^2.30.1", - "moment-timezone": "^0.5.43", + "moment-timezone": "^0.5.44", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" @@ -57,9 +57,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.43", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", - "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", + "version": "0.5.44", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz", + "integrity": "sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==", "dependencies": { "moment": "^2.29.4" }, diff --git a/vendor/package.json b/vendor/package.json index d3182f20b4..3d1ef83ec0 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -13,7 +13,7 @@ "@fortawesome/fontawesome-free": "^6.5.1", "animate.css": "^4.1.1", "moment": "^2.30.1", - "moment-timezone": "^0.5.43", + "moment-timezone": "^0.5.44", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" From bcab8ebd261cffee8e42097f8ada39b909e721cf Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 1 Jan 2024 22:14:05 +0100 Subject: [PATCH 004/418] skip changelog requirement when running tests for dependency updates (#3326) solution for #3320 --- .github/dependabot.yaml | 15 +++++++++++++++ CHANGELOG.md | 2 ++ LICENSE.md | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 9e699b7e65..4f7b4405cb 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -5,21 +5,36 @@ updates: schedule: interval: "weekly" target-branch: "develop" + labels: + - "Skip Changelog" + - "dependencies" - package-ecosystem: "npm" directory: "/" schedule: interval: "monthly" target-branch: "develop" + labels: + - "Skip Changelog" + - "dependencies" + - "javascript" - package-ecosystem: "npm" directory: "/vendor" schedule: interval: "monthly" target-branch: "develop" + labels: + - "Skip Changelog" + - "dependencies" + - "javascript" - package-ecosystem: "npm" directory: "/fonts" schedule: interval: "monthly" target-branch: "develop" + labels: + - "Skip Changelog" + - "dependencies" + - "javascript" diff --git a/CHANGELOG.md b/CHANGELOG.md index 5be3f84373..5f552cc368 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Fixed +- Skip changelog requirement when running tests for dependency updates (#3320) + ### Deleted ## [2.26.0] - 01-01-2024 diff --git a/LICENSE.md b/LICENSE.md index e3fe88029f..506207e0c4 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ # The MIT License (MIT) -Copyright © 2016-2022 Michael Teeuw +Copyright © 2016-2024 Michael Teeuw Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation From 5f7b56e64549601dad5b103f5957eeec4ab201ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 22:36:34 +0100 Subject: [PATCH 005/418] Bump eslint-plugin-jsdoc from 46.9.1 to 47.0.2 (#3315) Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 46.9.1 to 47.0.2.
Release notes

Sourced from eslint-plugin-jsdoc's releases.

v47.0.2

47.0.2 (2024-01-01)

Bug Fixes

v47.0.1

47.0.1 (2023-12-31)

Bug Fixes

  • TS: make configs explicit (47f3161)

v47.0.0

47.0.0 (2023-12-31)

Features

BREAKING CHANGES

  • Adds types

v46.10.1

46.10.1 (2023-12-30)

Bug Fixes

  • revert change to engines for now (5e6280f)

v46.10.0

46.10.0 (2023-12-30)

Features

Commits
  • 3677e43 fix(TS): use flat config; fixes #1130
  • 5f61575 chore(lint): handle disable directives in config
  • 47f3161 fix(TS): make configs explicit
  • dd9e71d feat: expose TS types for index file; fixes #1130
  • eb3f4b4 chore(linting): add ignores properly and disable directives for now
  • 5e6280f fix: revert change to engines for now
  • eec9d95 feat: support ESLint 9
  • 5c4ccb9 chore: update devDeps.
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=eslint-plugin-jsdoc&package-manager=npm_and_yarn&previous-version=46.9.1&new-version=47.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 13 +++++-------- package.json | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index adba08219d..b20fbb0054 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,7 @@ "@stylistic/eslint-plugin": "^1.5.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.0", - "eslint-plugin-jsdoc": "^46.9.1", + "eslint-plugin-jsdoc": "^47.0.2", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", "jest": "^29.7.0", @@ -3995,9 +3995,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "46.9.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.9.1.tgz", - "integrity": "sha512-11Ox5LCl2wY7gGkp9UOyew70o9qvii1daAH+h/MFobRVRNcy7sVlH+jm0HQdgcvcru6285GvpjpUyoa051j03Q==", + "version": "47.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-47.0.2.tgz", + "integrity": "sha512-sIq81Pv+yrhhwY0m1JH79rdZRgDNunehv3S0Yv0UfewpoeJyPkODFn2o4o20nofVoI2tjku9/QBcCYUmmeWFXA==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.41.0", @@ -4013,11 +4013,8 @@ "engines": { "node": ">=16" }, - "funding": { - "url": "https://opencollective.com/prettier" - }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-scope": { diff --git a/package.json b/package.json index f9c44ae7c3..4bd3139981 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@stylistic/eslint-plugin": "^1.5.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.0", - "eslint-plugin-jsdoc": "^46.9.1", + "eslint-plugin-jsdoc": "^47.0.2", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", "jest": "^29.7.0", From 6097547c103be1bc89c572e5bd2be50b342967fa Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:38:53 +0100 Subject: [PATCH 006/418] Add systeminfo (#3331) This is a first attempt to bring additional system information into the console (see #3328). It's certainly not yet perfect, but with the PR we have a better basis for discussion. I tried to keep the output small so that we get as much information as possible in screenshots. This is how it looks on my development system. ```bash [03.01.2024 00:50.19.226] [INFO] System information: ### SYSTEM: manufacturer: Notebook; model: N650DU; raspberry: undefined; virtual: false ### OS: platform: linux; distro: Debian GNU/Linux; release: 12 ### VERSIONS: MagicMirror: 2.27.0-develop; electron: 27.2.0; kernel: 5.10.0-20-amd64; node: 21.1.0; npm: 10.2.4; pm2: 5.3.0; docker: 20.10.24+dfsg1 ``` Why is it still a draft: - [x] I have doubts that utils.js is the right place for the function. What do you think? => Update: As long as there is no better idea, it stays there. - [x] Instead of working through all wishes you expressed in the issue #3328, I only implemented what was easy to achieve. And wanted to hear what you think about this approach. => Update: Some added. Of course, more information could be added later, as soon as experience has been gained in productive use. - [x] I don't quite like the introductory line ("The following lines provide information..."). Should I perhaps simply replace it with "System information:"? => Update: Changed to "System information:" [Here](https://github.com/sebhildebrandt/systeminformation#function-reference-and-os-support) you can see what information we could easily add with the systeminformation package. It would be interesting how the raspberry field is filled on a raspi system and with docker there should be another line, but I can't easily test that now. --- CHANGELOG.md | 4 +++- js/app.js | 3 +++ js/utils.js | 16 ++++++++++++++++ package-lock.json | 28 +++++++++++++++++++++++++++- package.json | 3 ++- 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f552cc368..3014d88910 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). -❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror². +❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². ## [2.27.0] - Develop Branch (unreleased) @@ -11,6 +11,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Added +- Output of system information to the console for troubleshooting (#3328). + ### Updated ### Fixed diff --git a/js/app.js b/js/app.js index eabdf73112..7f4335efaf 100644 --- a/js/app.js +++ b/js/app.js @@ -21,6 +21,9 @@ const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`) global.version = require(`${__dirname}/../package.json`).version; Log.log(`Starting MagicMirror: v${global.version}`); +// Log system information. +Utils.logSystemInformation(); + // global absolute root path global.root_path = path.resolve(`${__dirname}/../`); diff --git a/js/utils.js b/js/utils.js index d111afca23..38f6ca8ba1 100644 --- a/js/utils.js +++ b/js/utils.js @@ -5,6 +5,8 @@ * MIT Licensed. */ const colors = require("colors/safe"); +const Log = require("logger"); +const si = require("systeminformation"); module.exports = { colors: { @@ -12,5 +14,19 @@ module.exports = { error: colors.red, info: colors.blue, pass: colors.green + }, + + async logSystemInformation () { + try { + const staticData = await si.getStaticData(); + let systemDataString = "System information:"; + systemDataString += `\n ### SYSTEM: manufacturer: ${staticData["system"]["manufacturer"]}; model: ${staticData["system"]["model"]}; raspberry: ${staticData["system"]["raspberry"]}; virtual: ${staticData["system"]["virtual"]}`; + systemDataString += `\n ### OS: platform: ${staticData["os"]["platform"]}; distro: ${staticData["os"]["distro"]}; release: ${staticData["os"]["release"]}; arch: ${staticData["os"]["arch"]}; kernel: ${staticData["versions"]["kernel"]}`; + systemDataString += `\n ### VERSIONS: electron: ${process.versions.electron}; node: ${staticData["versions"]["node"]}; npm: ${staticData["versions"]["npm"]}; pm2: ${staticData["versions"]["pm2"]}; docker: ${staticData["versions"]["docker"]}`; + systemDataString += `\n ### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}`; + Log.info(systemDataString); + } catch (e) { + Log.error(e); + } } }; diff --git a/package-lock.json b/package-lock.json index b20fbb0054..3e1330b197 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,8 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.17.1", - "socket.io": "^4.7.2" + "socket.io": "^4.7.2", + "systeminformation": "^5.21.22" }, "devDependencies": { "@stylistic/eslint-plugin": "^1.5.1", @@ -9297,6 +9298,31 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/systeminformation": { + "version": "5.21.22", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.21.22.tgz", + "integrity": "sha512-gNHloAJSyS+sKWkwvmvozZ1eHrdVTEsynWMTY6lvLGBB70gflkBQFw8drXXr1oEXY84+Vr9tOOrN8xHZLJSycA==", + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, "node_modules/table": { "version": "6.8.1", "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", diff --git a/package.json b/package.json index 4bd3139981..17151bba14 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,8 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.17.1", - "socket.io": "^4.7.2" + "socket.io": "^4.7.2", + "systeminformation": "^5.21.22" }, "lint-staged": { "*": "prettier --write", From 407072d12d6597fa197f4b3603fc63a9f8acd67e Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 7 Jan 2024 17:28:17 +0100 Subject: [PATCH 007/418] Update system information (#3337) - Add ELECTRON_ENABLE_GPU - Remove docker version - Differentiation between installed and used node version - Highlight "Ready to go!" for server mode (Since we display system information in the console, it is easy to overlook this important line.) ## Electron mode ### Before ```bash [07.01.2024 16:37.30.591] [INFO] System information: ### SYSTEM: manufacturer: Notebook; model: N650DU; raspberry: undefined; virtual: false ### OS: platform: linux; distro: Debian GNU/Linux; release: 12; arch: x64; kernel: 5.10.0-20-amd64 ### VERSIONS: electron: 27.2.0; node: 18.17.1; npm: 10.2.4; pm2: 5.3.0; docker: 20.10.24+dfsg1 ### OTHER: timeZone: Europe/Berlin ``` ### After ```bash [07.01.2024 16:39.04.736] [INFO] System information: ### SYSTEM: manufacturer: Notebook; model: N650DU; raspberry: undefined; virtual: false ### OS: platform: linux; distro: Debian GNU/Linux; release: 12; arch: x64; kernel: 5.10.0-20-amd64 ### VERSIONS: electron: 27.2.0; used node: 18.17.1; installed node: 21.1.0; npm: 10.2.4; pm2: 5.3.0 ### OTHER: timeZone: Europe/Berlin; ELECTRON_ENABLE_GPU: undefined ``` ## server mode ### Before ```bash [07.01.2024 16:36.49.106] [LOG] Ready to go! Please point your browser to: http://localhost:8080 [07.01.2024 16:36.49.287] [INFO] System information: ### SYSTEM: manufacturer: Notebook; model: N650DU; raspberry: undefined; virtual: false ### OS: platform: linux; distro: Debian GNU/Linux; release: 12; arch: x64; kernel: 5.10.0-20-amd64 ### VERSIONS: electron: undefined; node: 21.1.0; npm: 10.2.4; pm2: 5.3.0; docker: 20.10.24+dfsg1 ### OTHER: timeZone: Europe/Berlin ``` ### After ```bash [2024-01-07 16:33:53.804] [INFO] >>> Ready to go! Please point your browser to: http://localhost:8080 <<< [2024-01-07 16:33:53.997] [INFO] System information: ### SYSTEM: manufacturer: Notebook; model: N650DU; raspberry: undefined; virtual: false ### OS: platform: linux; distro: Debian GNU/Linux; release: 12; arch: x64; kernel: 5.10.0-20-amd64 ### VERSIONS: electron: undefined; used node: 21.1.0; installed node: 21.1.0; npm: 10.2.4; pm2: 5.3.0 ### OTHER: timeZone: Europe/Berlin; ELECTRON_ENABLE_GPU: undefined ``` --- CHANGELOG.md | 2 +- js/utils.js | 10 ++++++---- serveronly/index.js | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3014d88910..3bd7e72d7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ _This release is scheduled to be released on 2024-04-01._ ### Added -- Output of system information to the console for troubleshooting (#3328). +- Output of system information to the console for troubleshooting (#3328 and #3337) ### Updated diff --git a/js/utils.js b/js/utils.js index 38f6ca8ba1..095cc2e88e 100644 --- a/js/utils.js +++ b/js/utils.js @@ -4,6 +4,7 @@ * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com * MIT Licensed. */ +const execSync = require("child_process").execSync; const colors = require("colors/safe"); const Log = require("logger"); const si = require("systeminformation"); @@ -18,12 +19,13 @@ module.exports = { async logSystemInformation () { try { + let installedNodeVersion = execSync("node -v", { encoding: "utf-8" }).replace("v", "").replace(/(?:\r\n|\r|\n)/g, ""); const staticData = await si.getStaticData(); let systemDataString = "System information:"; - systemDataString += `\n ### SYSTEM: manufacturer: ${staticData["system"]["manufacturer"]}; model: ${staticData["system"]["model"]}; raspberry: ${staticData["system"]["raspberry"]}; virtual: ${staticData["system"]["virtual"]}`; - systemDataString += `\n ### OS: platform: ${staticData["os"]["platform"]}; distro: ${staticData["os"]["distro"]}; release: ${staticData["os"]["release"]}; arch: ${staticData["os"]["arch"]}; kernel: ${staticData["versions"]["kernel"]}`; - systemDataString += `\n ### VERSIONS: electron: ${process.versions.electron}; node: ${staticData["versions"]["node"]}; npm: ${staticData["versions"]["npm"]}; pm2: ${staticData["versions"]["pm2"]}; docker: ${staticData["versions"]["docker"]}`; - systemDataString += `\n ### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}`; + systemDataString += `\n### SYSTEM: manufacturer: ${staticData["system"]["manufacturer"]}; model: ${staticData["system"]["model"]}; raspberry: ${staticData["system"]["raspberry"]}; virtual: ${staticData["system"]["virtual"]}`; + systemDataString += `\n### OS: platform: ${staticData["os"]["platform"]}; distro: ${staticData["os"]["distro"]}; release: ${staticData["os"]["release"]}; arch: ${staticData["os"]["arch"]}; kernel: ${staticData["versions"]["kernel"]}`; + systemDataString += `\n### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData["versions"]["node"]}; installed node: ${installedNodeVersion}; npm: ${staticData["versions"]["npm"]}; pm2: ${staticData["versions"]["pm2"]}`; + systemDataString += `\n### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}`; Log.info(systemDataString); } catch (e) { Log.error(e); diff --git a/serveronly/index.js b/serveronly/index.js index 3cfa7969d2..66632ac105 100644 --- a/serveronly/index.js +++ b/serveronly/index.js @@ -4,5 +4,5 @@ const Log = require("../js/logger"); app.start().then((config) => { const bindAddress = config.address ? config.address : "localhost"; const httpType = config.useHttps ? "https" : "http"; - Log.log(`\nReady to go! Please point your browser to: ${httpType}://${bindAddress}:${config.port}`); + Log.info(`\n>>> Ready to go! Please point your browser to: ${httpType}://${bindAddress}:${config.port} <<<`); }); From 4bbd35fa6a57cea6490cb3a53fec86e8bc87720f Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:45:54 +0100 Subject: [PATCH 008/418] Use node prefix for build-in modules (#3340) It is basically a cosmetic thing, but has the following advantages: 1. Consistency with the official node documentation. The prefix is used there. 2. It is easier to recognize the build-in modules. --- .eslintrc.json | 9 +- CHANGELOG.md | 2 + clientonly/index.js | 4 +- js/app.js | 4 +- js/check_config.js | 4 +- js/server.js | 8 +- js/server_functions.js | 4 +- js/utils.js | 2 +- modules/default/calendar/calendarfetcher.js | 2 +- .../default/calendar/calendarfetcherutils.js | 2 +- modules/default/newsfeed/newsfeedfetcher.js | 2 +- .../default/updatenotification/git_helper.js | 8 +- .../updatenotification/update_helper.js | 4 +- package-lock.json | 517 +++++++++++++++--- package.json | 7 +- tests/e2e/fonts_spec.js | 2 +- tests/e2e/helpers/basic-auth.js | 2 +- tests/e2e/serveronly_spec.js | 2 +- tests/e2e/template_spec.js | 2 +- tests/e2e/translations_spec.js | 4 +- tests/electron/env_spec.js | 2 +- tests/unit/classes/class_spec.js | 2 +- tests/unit/classes/translator_spec.js | 2 +- tests/unit/functions/cmp_versions_spec.js | 2 +- .../unit/functions/updatenotification_spec.js | 6 +- .../unit/global_vars/defaults_modules_spec.js | 4 +- tests/unit/global_vars/root_path_spec.js | 4 +- tests/utils/weather_mocker.js | 8 +- 28 files changed, 489 insertions(+), 132 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 72cdf37c21..1eaa9b43df 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,9 +1,9 @@ { "extends": ["eslint:recommended", "plugin:@stylistic/all-extends", "plugin:import/recommended", "plugin:jest/recommended", "plugin:jsdoc/recommended"], - "plugins": [], + "plugins": ["unicorn"], "env": { "browser": true, - "es2023": true, + "es2024": true, "jest/globals": true, "node": true }, @@ -16,7 +16,7 @@ }, "parserOptions": { "sourceType": "module", - "ecmaVersion": 2023, + "ecmaVersion": "latest", "ecmaFeatures": { "globalReturn": true } @@ -62,7 +62,8 @@ "@stylistic/indent": ["error", "tab"], "@stylistic/semi": ["error", "always"], "@stylistic/space-before-function-paren": ["error", "always"], - "@stylistic/spaced-comment": "off" + "@stylistic/spaced-comment": "off", + "unicorn/prefer-node-protocol": "error" }, "overrides": [ { diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bd7e72d7b..1325372660 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Updated +- Use node prefix for build-in modules + ### Fixed - Skip changelog requirement when running tests for dependency updates (#3320) diff --git a/clientonly/index.js b/clientonly/index.js index cee8ba22c6..b9a354832b 100644 --- a/clientonly/index.js +++ b/clientonly/index.js @@ -40,7 +40,7 @@ // Return new pending promise return new Promise((resolve, reject) => { // Select http or https module, depending on requested url - const lib = url.startsWith("https") ? require("https") : require("http"); + const lib = url.startsWith("https") ? require("node:https") : require("node:http"); const request = lib.get(url, (response) => { let configData = ""; @@ -94,7 +94,7 @@ // Spawn electron application const electron = require("electron"); - const child = require("child_process").spawn(electron, ["js/electron.js"], options); + const child = require("node:child_process").spawn(electron, ["js/electron.js"], options); // Pipe all child process output to current stdout child.stdout.on("data", function (buf) { diff --git a/js/app.js b/js/app.js index 7f4335efaf..06960c0b39 100644 --- a/js/app.js +++ b/js/app.js @@ -8,8 +8,8 @@ // Alias modules mentioned in package.js under _moduleAliases. require("module-alias/register"); -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); const envsub = require("envsub"); const Log = require("logger"); diff --git a/js/check_config.js b/js/check_config.js index 3d868bd502..b3a0fe9429 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -5,8 +5,8 @@ * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com * MIT Licensed. */ -const path = require("path"); -const fs = require("fs"); +const path = require("node:path"); +const fs = require("node:fs"); const { Linter } = require("eslint"); const linter = new Linter(); diff --git a/js/server.js b/js/server.js index 726a18e32a..a183fe4df8 100644 --- a/js/server.js +++ b/js/server.js @@ -4,10 +4,10 @@ * By Michael Teeuw https://michaelteeuw.nl * MIT Licensed. */ -const fs = require("fs"); -const http = require("http"); -const https = require("https"); -const path = require("path"); +const fs = require("node:fs"); +const http = require("node:http"); +const https = require("node:https"); +const path = require("node:path"); const express = require("express"); const ipfilter = require("express-ipfilter").IpFilter; const helmet = require("helmet"); diff --git a/js/server_functions.js b/js/server_functions.js index c975df7c5e..7d4358b2e5 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -1,5 +1,5 @@ -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); const Log = require("logger"); const startUp = new Date(); diff --git a/js/utils.js b/js/utils.js index 095cc2e88e..ce37a0291b 100644 --- a/js/utils.js +++ b/js/utils.js @@ -4,7 +4,7 @@ * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com * MIT Licensed. */ -const execSync = require("child_process").execSync; +const execSync = require("node:child_process").execSync; const colors = require("colors/safe"); const Log = require("logger"); const si = require("systeminformation"); diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 51db30d7c7..2ba4e12ea6 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -5,7 +5,7 @@ * MIT Licensed. */ -const https = require("https"); +const https = require("node:https"); const ical = require("node-ical"); const Log = require("logger"); const NodeHelper = require("node_helper"); diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index af48b7e795..7a0b8b4053 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -8,7 +8,7 @@ /** * @external Moment */ -const path = require("path"); +const path = require("node:path"); const moment = require("moment"); const zoneTable = require(path.join(__dirname, "windowsZones.json")); diff --git a/modules/default/newsfeed/newsfeedfetcher.js b/modules/default/newsfeed/newsfeedfetcher.js index 0c52e347ce..47af15ce63 100644 --- a/modules/default/newsfeed/newsfeedfetcher.js +++ b/modules/default/newsfeed/newsfeedfetcher.js @@ -5,7 +5,7 @@ * MIT Licensed. */ -const stream = require("stream"); +const stream = require("node:stream"); const FeedMe = require("feedme"); const iconv = require("iconv-lite"); const { htmlToText } = require("html-to-text"); diff --git a/modules/default/updatenotification/git_helper.js b/modules/default/updatenotification/git_helper.js index 8243c43a7b..4fb8c18928 100644 --- a/modules/default/updatenotification/git_helper.js +++ b/modules/default/updatenotification/git_helper.js @@ -1,7 +1,7 @@ -const util = require("util"); -const exec = util.promisify(require("child_process").exec); -const fs = require("fs"); -const path = require("path"); +const util = require("node:util"); +const exec = util.promisify(require("node:child_process").exec); +const fs = require("node:fs"); +const path = require("node:path"); const Log = require("logger"); const BASE_DIR = path.normalize(`${__dirname}/../../../`); diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index 25fd0aaa18..00afb65836 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -1,5 +1,5 @@ -const Exec = require("child_process").exec; -const Spawn = require("child_process").spawn; +const Exec = require("node:child_process").exec; +const Spawn = require("node:child_process").spawn; const commandExists = require("command-exists"); const Log = require("logger"); diff --git a/package-lock.json b/package-lock.json index 3e1330b197..11fabf91f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,10 +28,11 @@ "systeminformation": "^5.21.22" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.5.1", + "@stylistic/eslint-plugin": "^1.5.3", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.0", - "eslint-plugin-jsdoc": "^47.0.2", + "eslint-plugin-jest": "^27.6.1", + "eslint-plugin-jsdoc": "^48.0.2", + "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", "jest": "^29.7.0", @@ -74,6 +75,17 @@ "node": ">=6.0.0" } }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-2.0.1.tgz", + "integrity": "sha512-QJAJffmCiymkv6YyQ7voyQb5caCth6jzZsQncYCpHXrJ7RqdYG5y43+is8mnFcYubdOkr7cn1+na9BdFMxqw7w==", + "dev": true, + "dependencies": { + "bidi-js": "^1.0.3", + "css-tree": "^2.3.1", + "is-potential-custom-element-name": "^1.0.1" + } + }, "node_modules/@babel/code-frame": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", @@ -1633,15 +1645,15 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.5.1.tgz", - "integrity": "sha512-y7ynUMh5Hq1MhYApAccl1iuQem5Sf2JSEIjV/qsBfmW1WfRDs74V+0kLkcOn1Y600W3t8orIFrrEuWmJSetAgw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.5.3.tgz", + "integrity": "sha512-Vee+hHKaCd8DPRoRJTCV+mOFz+zFIaA9QiNJaAvgBzmPkcDnSC7Ewh518fN6SSNe9psS8TDIpcxd1g5v4MSY5A==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.5.1", - "@stylistic/eslint-plugin-jsx": "1.5.1", - "@stylistic/eslint-plugin-plus": "1.5.1", - "@stylistic/eslint-plugin-ts": "1.5.1" + "@stylistic/eslint-plugin-js": "1.5.3", + "@stylistic/eslint-plugin-jsx": "1.5.3", + "@stylistic/eslint-plugin-plus": "1.5.3", + "@stylistic/eslint-plugin-ts": "1.5.3" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1651,12 +1663,12 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.1.tgz", - "integrity": "sha512-iZF0rF+uOhAmOJYOJx1Yvmm3CZ1uz9n0SRd9dpBYHA3QAvfABUORh9LADWwZCigjHJkp2QbCZelGFJGwGz7Siw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.3.tgz", + "integrity": "sha512-XlKnm82fD7Sw9kQ6FFigE0tobvptNBXZWsdfoKmUyK7bNxHsAHOFT8zJGY3j3MjZ0Fe7rLTu86hX/vOl0bRRdQ==", "dev": true, "dependencies": { - "acorn": "^8.11.2", + "acorn": "^8.11.3", "escape-string-regexp": "^4.0.0", "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1" @@ -1669,12 +1681,12 @@ } }, "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.5.1.tgz", - "integrity": "sha512-JuX+jsbVdpZ6EZXkbxYr9ERcGc0ndSMFgOuwEPHhOWPZ+7F8JP/nzpBjrRf7dUPMX7ezTYLZ2a3KRGRNme6rWQ==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.5.3.tgz", + "integrity": "sha512-gKXWFmvg3B4e6G+bVz2p37icjj3gS5lzazZD6oLjmQ2b0Lw527VpnxGjWxQ16keKXtrVzUfebakjskOoALg3CQ==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "^1.5.1", + "@stylistic/eslint-plugin-js": "^1.5.3", "estraverse": "^5.3.0" }, "engines": { @@ -1685,25 +1697,25 @@ } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.5.1.tgz", - "integrity": "sha512-yxkFHsUgoqEf/j1Og0FGkpEmeQoqx0CMmtgoyZGr34hka0ElCy9fRpsFkLcwx60SfiHXspbvs2YUMXiWIffnjg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.5.3.tgz", + "integrity": "sha512-fuOBySbH4dbfY4Dwvu+zg5y+e0lALHTyQske5+a2zNC8Ejnx4rFlVjYOmaVFtxFhTD4V0vM7o21Ozci0igcxKg==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^6.13.2" + "@typescript-eslint/utils": "^6.17.0" }, "peerDependencies": { "eslint": "*" } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.1.tgz", - "integrity": "sha512-oXM1V7Jp8G9+udxQTy+Igo79LR2e5HXiWqlA/3v+/PAqWxniR9nJqJSBjtQKJTPsGplDqn/ASpHUOETP4EI/4A==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.3.tgz", + "integrity": "sha512-/gUEqGo0gpFeu220YmC0788VliKnmTaAz4pI82KA5cUuCp6OzEhGlrNkb1eevMwH0RRgyND20HJxOYvEGlwu+w==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.5.1", - "@typescript-eslint/utils": "^6.13.2" + "@stylistic/eslint-plugin-js": "1.5.3", + "@typescript-eslint/utils": "^6.17.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1858,6 +1870,12 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, "node_modules/@types/responselike": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", @@ -1904,13 +1922,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz", - "integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", + "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0" + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1921,9 +1939,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz", - "integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", + "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1934,13 +1952,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz", - "integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", + "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/visitor-keys": "6.16.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/visitor-keys": "6.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1962,17 +1980,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.16.0.tgz", - "integrity": "sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", + "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.16.0", - "@typescript-eslint/types": "6.16.0", - "@typescript-eslint/typescript-estree": "6.16.0", + "@typescript-eslint/scope-manager": "6.18.0", + "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/typescript-estree": "6.18.0", "semver": "^7.5.4" }, "engines": { @@ -1987,12 +2005,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz", - "integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==", + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", + "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.16.0", + "@typescript-eslint/types": "6.18.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2021,9 +2039,9 @@ } }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "bin": { "acorn": "bin/acorn" }, @@ -2444,6 +2462,15 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -2731,6 +2758,27 @@ "node": ">=0.3.6" } }, + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clean-regexp/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", @@ -2974,6 +3022,19 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/core-js-compat": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", + "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "dev": true, + "dependencies": { + "browserslist": "^4.22.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -3081,15 +3142,15 @@ } }, "node_modules/cssstyle": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", - "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", "dev": true, "dependencies": { "rrweb-cssom": "^0.6.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/data-urls": { @@ -3370,9 +3431,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "27.2.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-27.2.0.tgz", - "integrity": "sha512-no/iMICVLI/5G0IqgKFbB89HDN88DWwKeRO+dPfJPkpJISdEX8Cx/sMEOFuuRa4VNInNe5CKCqRWExK5z3AdcQ==", + "version": "27.2.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-27.2.1.tgz", + "integrity": "sha512-bYUzyptYrUIFtPnyF2x6DnhF1E9FCthctjbNSKMqg7dG4NqSwyuZzEku3Wts55u8R+ddNFbLoLwRHHLvYTCQlA==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -3849,9 +3910,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.0.tgz", - "integrity": "sha512-MTlusnnDMChbElsszJvrwD1dN3x6nZl//s4JD23BxB6MgR66TZlL064su24xEIS3VACfAoHV1vgyMgPw8nkdng==", + "version": "27.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", + "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -3996,9 +4057,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "47.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-47.0.2.tgz", - "integrity": "sha512-sIq81Pv+yrhhwY0m1JH79rdZRgDNunehv3S0Yv0UfewpoeJyPkODFn2o4o20nofVoI2tjku9/QBcCYUmmeWFXA==", + "version": "48.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.0.2.tgz", + "integrity": "sha512-CBFl5Jc7+jlV36RwDm+PQ8Uw5r28pn2/uW/OaB+Gw5bFwn4Py/1eYMZ3hGf9S4meUFZ/sRvS+hVif2mRAp6WqQ==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.41.0", @@ -4012,12 +4073,72 @@ "spdx-expression-parse": "^4.0.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-unicorn": { + "version": "50.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-50.0.1.tgz", + "integrity": "sha512-KxenCZxqSYW0GWHH18okDlOQcpezcitm5aOSz6EnobyJ6BIByiPDviQRjJIUAjG/tMN11958MxaQ+qCoU6lfDA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "@eslint-community/eslint-utils": "^4.4.0", + "@eslint/eslintrc": "^2.1.4", + "ci-info": "^4.0.0", + "clean-regexp": "^1.0.0", + "core-js-compat": "^3.34.0", + "esquery": "^1.5.0", + "indent-string": "^4.0.0", + "is-builtin-module": "^3.2.1", + "jsesc": "^3.0.2", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.10.0", + "semver": "^7.5.4", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=8.56.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/ci-info": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -5025,6 +5146,12 @@ "node": ">=16.0.0" } }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -5233,6 +5360,15 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -6281,12 +6417,13 @@ } }, "node_modules/jsdom": { - "version": "23.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.0.1.tgz", - "integrity": "sha512-2i27vgvlUsGEBO9+/kJQRbtqtm+191b5zAZrU/UezVmnC2dlDAFLgDYJvAEi94T4kjsRKkezEtLQTgsNEsW2lQ==", + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.2.0.tgz", + "integrity": "sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA==", "dev": true, "dependencies": { - "cssstyle": "^3.0.0", + "@asamuzakjp/dom-selector": "^2.0.1", + "cssstyle": "^4.0.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", @@ -6294,7 +6431,6 @@ "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.7", "parse5": "^7.1.2", "rrweb-cssom": "^0.6.0", "saxes": "^6.0.0", @@ -6305,7 +6441,7 @@ "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.14.2", + "ws": "^8.16.0", "xml-name-validator": "^5.0.0" }, "engines": { @@ -7025,6 +7161,15 @@ "node": ">=4" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -7182,6 +7327,27 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -7215,12 +7381,6 @@ "node": ">=8" } }, - "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", - "dev": true - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7695,6 +7855,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss": { "version": "8.4.32", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", @@ -8016,6 +8185,117 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", @@ -8032,6 +8312,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regjsparser": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", + "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, "node_modules/replace-last": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/replace-last/-/replace-last-1.2.6.tgz", @@ -8588,9 +8889,9 @@ } }, "node_modules/socket.io": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", - "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.3.tgz", + "integrity": "sha512-SE+UIQXBQE+GPG2oszWMlsEmWtHVqw/h1VrYJGK5/MC7CH5p58N448HwIrtREcvR4jfdOJAY4ieQfxMr55qbbw==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -8671,6 +8972,26 @@ "source-map": "^0.6.0" } }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "node_modules/spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", @@ -8948,6 +9269,18 @@ "node": ">=6" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -9844,6 +10177,26 @@ "node": ">=10.12.0" } }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 17151bba14..578e4a740a 100644 --- a/package.json +++ b/package.json @@ -49,10 +49,11 @@ }, "homepage": "https://magicmirror.builders", "devDependencies": { - "@stylistic/eslint-plugin": "^1.5.1", + "@stylistic/eslint-plugin": "^1.5.3", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.0", - "eslint-plugin-jsdoc": "^47.0.2", + "eslint-plugin-jest": "^27.6.1", + "eslint-plugin-jsdoc": "^48.0.2", + "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", "jest": "^29.7.0", diff --git a/tests/e2e/fonts_spec.js b/tests/e2e/fonts_spec.js index 458ff2baaf..80e3e34081 100644 --- a/tests/e2e/fonts_spec.js +++ b/tests/e2e/fonts_spec.js @@ -3,7 +3,7 @@ const helpers = require("./helpers/global-setup"); describe("All font files from roboto.css should be downloadable", () => { const fontFiles = []; // Statements below filters out all 'url' lines in the CSS file - const fileContent = require("fs").readFileSync(`${__dirname}/../../fonts/roboto.css`, "utf8"); + const fileContent = require("node:fs").readFileSync(`${__dirname}/../../fonts/roboto.css`, "utf8"); const regex = /\burl\(['"]([^'"]+)['"]\)/g; let match = regex.exec(fileContent); while (match !== null) { diff --git a/tests/e2e/helpers/basic-auth.js b/tests/e2e/helpers/basic-auth.js index c793085ba9..c10e0f3ce9 100644 --- a/tests/e2e/helpers/basic-auth.js +++ b/tests/e2e/helpers/basic-auth.js @@ -1,4 +1,4 @@ -const path = require("path"); +const path = require("node:path"); const auth = require("express-basic-auth"); const express = require("express"); diff --git a/tests/e2e/serveronly_spec.js b/tests/e2e/serveronly_spec.js index 9a6f29ba75..c33a78d292 100644 --- a/tests/e2e/serveronly_spec.js +++ b/tests/e2e/serveronly_spec.js @@ -6,7 +6,7 @@ describe("App environment", () => { let serverProcess; beforeAll(async () => { process.env.MM_CONFIG_FILE = "tests/configs/default.js"; - serverProcess = await require("child_process").spawn("npm", ["run", "server"], { env: process.env, detached: true }); + serverProcess = await require("node:child_process").spawn("npm", ["run", "server"], { env: process.env, detached: true }); // we have to wait until the server is startet await delay(2000); }); diff --git a/tests/e2e/template_spec.js b/tests/e2e/template_spec.js index 46417aea79..23005564ed 100644 --- a/tests/e2e/template_spec.js +++ b/tests/e2e/template_spec.js @@ -1,4 +1,4 @@ -const fs = require("fs"); +const fs = require("node:fs"); const helpers = require("./helpers/global-setup"); describe("templated config with port variable", () => { diff --git a/tests/e2e/translations_spec.js b/tests/e2e/translations_spec.js index a0124fc9af..07a99e218c 100644 --- a/tests/e2e/translations_spec.js +++ b/tests/e2e/translations_spec.js @@ -1,5 +1,5 @@ -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); const helmet = require("helmet"); const { JSDOM } = require("jsdom"); const express = require("express"); diff --git a/tests/electron/env_spec.js b/tests/electron/env_spec.js index 12c2ee0766..b0e28789a6 100644 --- a/tests/electron/env_spec.js +++ b/tests/electron/env_spec.js @@ -1,4 +1,4 @@ -const events = require("events"); +const events = require("node:events"); const helpers = require("./helpers/global-setup"); describe("Electron app environment", () => { diff --git a/tests/unit/classes/class_spec.js b/tests/unit/classes/class_spec.js index c455621d59..0fc8843935 100644 --- a/tests/unit/classes/class_spec.js +++ b/tests/unit/classes/class_spec.js @@ -1,4 +1,4 @@ -const path = require("path"); +const path = require("node:path"); const { JSDOM } = require("jsdom"); describe("File js/class", () => { diff --git a/tests/unit/classes/translator_spec.js b/tests/unit/classes/translator_spec.js index c0957e680b..8ba9d3c8d9 100644 --- a/tests/unit/classes/translator_spec.js +++ b/tests/unit/classes/translator_spec.js @@ -1,4 +1,4 @@ -const path = require("path"); +const path = require("node:path"); const helmet = require("helmet"); const { JSDOM } = require("jsdom"); const express = require("express"); diff --git a/tests/unit/functions/cmp_versions_spec.js b/tests/unit/functions/cmp_versions_spec.js index 6fe6a13e35..9d4e976b3a 100644 --- a/tests/unit/functions/cmp_versions_spec.js +++ b/tests/unit/functions/cmp_versions_spec.js @@ -1,4 +1,4 @@ -const path = require("path"); +const path = require("node:path"); const { JSDOM } = require("jsdom"); describe("Test function cmpVersions in js/module.js", () => { diff --git a/tests/unit/functions/updatenotification_spec.js b/tests/unit/functions/updatenotification_spec.js index 102c533744..b49dd04d22 100644 --- a/tests/unit/functions/updatenotification_spec.js +++ b/tests/unit/functions/updatenotification_spec.js @@ -1,9 +1,9 @@ -jest.mock("util", () => ({ +jest.mock("node:util", () => ({ ...jest.requireActual("util"), promisify: jest.fn() })); -jest.mock("fs", () => ({ +jest.mock("node:fs", () => ({ ...jest.requireActual("fs"), statSync: jest.fn() })); @@ -29,7 +29,7 @@ describe("Updatenotification", () => { let gitTagListOut; beforeAll(async () => { - const { promisify } = require("util"); + const { promisify } = require("node:util"); promisify.mockReturnValue(execMock); const GitHelper = require("../../../modules/default/updatenotification/git_helper"); diff --git a/tests/unit/global_vars/defaults_modules_spec.js b/tests/unit/global_vars/defaults_modules_spec.js index 6a943bd004..7fcdf2533a 100644 --- a/tests/unit/global_vars/defaults_modules_spec.js +++ b/tests/unit/global_vars/defaults_modules_spec.js @@ -1,5 +1,5 @@ -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); const root_path = path.join(__dirname, "../../.."); diff --git a/tests/unit/global_vars/root_path_spec.js b/tests/unit/global_vars/root_path_spec.js index 6806f5c3c2..32bcc74b8a 100644 --- a/tests/unit/global_vars/root_path_spec.js +++ b/tests/unit/global_vars/root_path_spec.js @@ -1,5 +1,5 @@ -const fs = require("fs"); -const path = require("path"); +const fs = require("node:fs"); +const path = require("node:path"); const root_path = path.join(__dirname, "../../.."); const version = require(`${__dirname}/../../../package.json`).version; diff --git a/tests/utils/weather_mocker.js b/tests/utils/weather_mocker.js index 83279001fa..4354df1d10 100644 --- a/tests/utils/weather_mocker.js +++ b/tests/utils/weather_mocker.js @@ -1,7 +1,7 @@ -const fs = require("fs"); -const path = require("path"); -const util = require("util"); -const exec = util.promisify(require("child_process").exec); +const fs = require("node:fs"); +const path = require("node:path"); +const util = require("node:util"); +const exec = util.promisify(require("node:child_process").exec); const _ = require("lodash"); /** From b47600e0d828b30d44acdf1d23d19ecf1dd7b93e Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:16:26 +0100 Subject: [PATCH 009/418] Remove lodash (#3339) Removing lodash dependency by replacing merge by spread operator. I have also split the return into two variables to make it easier to understand what is happening. --- CHANGELOG.md | 3 ++- package-lock.json | 1 - package.json | 1 - tests/utils/weather_mocker.js | 5 +++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1325372660..ca3df69f3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Updated -- Use node prefix for build-in modules +- Removing lodash dependency by replacing merge by spread operator (#3339) +- Use node prefix for build-in modules (#3340) ### Fixed diff --git a/package-lock.json b/package-lock.json index 11fabf91f0..986e535a5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,6 @@ "jest": "^29.7.0", "jsdom": "^23.0.1", "lint-staged": "^15.2.0", - "lodash": "^4.17.21", "playwright": "^1.40.1", "prettier": "^3.1.1", "sinon": "^17.0.1", diff --git a/package.json b/package.json index 578e4a740a..6ecce674bc 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "jest": "^29.7.0", "jsdom": "^23.0.1", "lint-staged": "^15.2.0", - "lodash": "^4.17.21", "playwright": "^1.40.1", "prettier": "^3.1.1", "sinon": "^17.0.1", diff --git a/tests/utils/weather_mocker.js b/tests/utils/weather_mocker.js index 4354df1d10..70d56e6812 100644 --- a/tests/utils/weather_mocker.js +++ b/tests/utils/weather_mocker.js @@ -2,7 +2,6 @@ const fs = require("node:fs"); const path = require("node:path"); const util = require("node:util"); const exec = util.promisify(require("node:child_process").exec); -const _ = require("lodash"); /** * @param {string} type what data to read, can be "current" "forecast" or "hourly @@ -25,7 +24,9 @@ const readMockData = (type, extendedData = {}) => { break; } - return JSON.stringify(_.merge({}, JSON.parse(fs.readFileSync(path.resolve(`${__dirname}/../mocks/${fileName}`)).toString()), extendedData)); + const fileData = JSON.parse(fs.readFileSync(path.resolve(`${__dirname}/../mocks/${fileName}`)).toString()); + const mergedData = JSON.stringify({ ...{}, ...fileData, ...extendedData }); + return mergedData; }; const injectMockData = (configFileName, extendedData = {}) => { From dadc7ba0a26e81adfe6e115a021d922d50b19d41 Mon Sep 17 00:00:00 2001 From: Ross Younger Date: Sun, 14 Jan 2024 21:12:32 +1300 Subject: [PATCH 010/418] [newsfeed] Suppress unsightly animation edge cases when there are 0 or 1 active news items (#3336) When the newsfeed module has an items list of size 1, every `updateInterval` the animation runs to transition from the active story to itself. This is unsightly. This PR suppresses that. To reproduce: configure newsfeed with a single news source, `ignoreOldItems` true, a short `updateInterval` (e.g. 3000), and a carefully-chosen small `ignoreOlderThan` lining up with the current contents of your news source. --- CHANGELOG.md | 2 ++ modules/default/newsfeed/newsfeed.js | 37 +++++++++++++++++---- modules/default/newsfeed/newsfeedfetcher.js | 4 ++- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca3df69f3d..9904dc1d31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Fixed - Skip changelog requirement when running tests for dependency updates (#3320) +- [newsfeed] Suppress unsightly animation cases when there are 0 or 1 active news items +- [newsfeed] Always compute the feed item URL using the same helper function ### Deleted diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 27114d8e31..2ecd2ad645 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -118,27 +118,33 @@ Module.register("newsfeed", { //Override template data and return whats used for the current template getTemplateData () { + if (this.activeItem >= this.newsItems.length) { + this.activeItem = 0; + } + this.activeItemCount = this.newsItems.length; // this.config.showFullArticle is a run-time configuration, triggered by optional notifications if (this.config.showFullArticle) { + this.activeItemHash = this.newsItems[this.activeItem]?.hash; return { url: this.getActiveItemURL() }; } if (this.error) { + this.activeItemHash = undefined; return { error: this.error }; } if (this.newsItems.length === 0) { + this.activeItemHash = undefined; return { empty: true }; } - if (this.activeItem >= this.newsItems.length) { - this.activeItem = 0; - } const item = this.newsItems[this.activeItem]; + this.activeItemHash = item.hash; + const items = this.newsItems.map(function (item) { item.publishDate = moment(new Date(item.pubdate)).fromNow(); return item; @@ -150,7 +156,7 @@ Module.register("newsfeed", { sourceTitle: item.sourceTitle, publishDate: moment(new Date(item.pubdate)).fromNow(), title: item.title, - url: this.getUrlPrefix(item) + item.url, + url: this.getActiveItemURL(), description: item.description, items: items }; @@ -312,8 +318,27 @@ Module.register("newsfeed", { if (this.timer) clearInterval(this.timer); this.timer = setInterval(() => { - this.activeItem++; - this.updateDom(this.config.animationSpeed); + + /* + * When animations are enabled, don't update the DOM unless we are actually changing what we are displaying. + * (Animating from a headline to itself is unsightly.) + * Cases: + * + * Number of items | Number of items | Display + * at last update | right now | Behaviour + * ---------------------------------------------------- + * 0 | 0 | do not update + * 0 | >0 | update + * 1 | 0 or >1 | update + * 1 | 1 | update only if item details (hash value) changed + * >1 | any | update + * + * (N.B. We set activeItemCount and activeItemHash in getTemplateData().) + */ + if (this.newsItems.length !== this.activeItemCount || this.activeItemHash !== this.newsItems[0]?.hash) { + this.activeItem++; // this is OK if newsItems.Length==1; getTemplateData will wrap it around + this.updateDom(this.config.animationSpeed); + } // Broadcast NewsFeed if needed if (this.config.broadcastNewsFeeds) { diff --git a/modules/default/newsfeed/newsfeedfetcher.js b/modules/default/newsfeed/newsfeedfetcher.js index 47af15ce63..ea1c7712fd 100644 --- a/modules/default/newsfeed/newsfeedfetcher.js +++ b/modules/default/newsfeed/newsfeedfetcher.js @@ -5,6 +5,7 @@ * MIT Licensed. */ +const crypto = require("node:crypto"); const stream = require("node:stream"); const FeedMe = require("feedme"); const iconv = require("iconv-lite"); @@ -67,7 +68,8 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings description: description, pubdate: pubdate, url: url, - useCorsProxy: useCorsProxy + useCorsProxy: useCorsProxy, + hash: crypto.createHash("sha256").update(`${pubdate} :: ${title} :: ${url}`).digest("hex") }); } else if (logFeedWarnings) { Log.warn("Can't parse feed item:"); From f890f14df7cd2f0fe3d60163b34b84d41d88ca5a Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 14 Jan 2024 09:13:01 +0100 Subject: [PATCH 011/418] ignore strange errors from systeminformation under aarch64 (#3349) by excluding them from global error handling, see discussions in https://github.com/MagicMirrorOrg/MagicMirror/pull/3337 --- CHANGELOG.md | 2 +- js/app.js | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9904dc1d31..468cc9ba48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ _This release is scheduled to be released on 2024-04-01._ ### Added -- Output of system information to the console for troubleshooting (#3328 and #3337) +- Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 ### Updated diff --git a/js/app.js b/js/app.js index 06960c0b39..33db688233 100644 --- a/js/app.js +++ b/js/app.js @@ -40,10 +40,13 @@ if (process.env.MM_PORT) { // The next part is here to prevent a major exception when there // is no internet connection. This could probable be solved better. process.on("uncaughtException", function (err) { - Log.error("Whoops! There was an uncaught exception..."); - Log.error(err); - Log.error("MagicMirror² will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?"); - Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MagicMirrorOrg/MagicMirror/issues"); + // ignore strange exceptions under aarch64 coming from systeminformation: + if (!err.stack.includes("node_modules/systeminformation")) { + Log.error("Whoops! There was an uncaught exception..."); + Log.error(err); + Log.error("MagicMirror² will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?"); + Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MagicMirrorOrg/MagicMirror/issues"); + } }); /** From 58bc14e8c05e2ef8e75ccc5f6a9cf05e01ad11d4 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 14 Jan 2024 09:15:30 +0100 Subject: [PATCH 012/418] Request only required information instead of all (#3338) Hopefully this solves the problem with arm64 (reported in PR #3337). --- js/utils.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/js/utils.js b/js/utils.js index ce37a0291b..b3b2992a69 100644 --- a/js/utils.js +++ b/js/utils.js @@ -20,10 +20,15 @@ module.exports = { async logSystemInformation () { try { let installedNodeVersion = execSync("node -v", { encoding: "utf-8" }).replace("v", "").replace(/(?:\r\n|\r|\n)/g, ""); - const staticData = await si.getStaticData(); + + const staticData = await si.get({ + system: "manufacturer, model, raspberry, virtual", + osInfo: "platform, distro, release, arch", + versions: "kernel, node, npm, pm2" + }); let systemDataString = "System information:"; systemDataString += `\n### SYSTEM: manufacturer: ${staticData["system"]["manufacturer"]}; model: ${staticData["system"]["model"]}; raspberry: ${staticData["system"]["raspberry"]}; virtual: ${staticData["system"]["virtual"]}`; - systemDataString += `\n### OS: platform: ${staticData["os"]["platform"]}; distro: ${staticData["os"]["distro"]}; release: ${staticData["os"]["release"]}; arch: ${staticData["os"]["arch"]}; kernel: ${staticData["versions"]["kernel"]}`; + systemDataString += `\n### OS: platform: ${staticData["osInfo"]["platform"]}; distro: ${staticData["osInfo"]["distro"]}; release: ${staticData["osInfo"]["release"]}; arch: ${staticData["osInfo"]["arch"]}; kernel: ${staticData["versions"]["kernel"]}`; systemDataString += `\n### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData["versions"]["node"]}; installed node: ${installedNodeVersion}; npm: ${staticData["versions"]["npm"]}; pm2: ${staticData["versions"]["pm2"]}`; systemDataString += `\n### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}`; Log.info(systemDataString); From 098757f24820ff676d8af8ec9acbecec1b40c6a8 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 16 Jan 2024 21:45:04 +0100 Subject: [PATCH 013/418] update dependencies including electron to v28 (#3357) --- CHANGELOG.md | 1 + package-lock.json | 593 +++++++++++++++++++--------------------------- package.json | 12 +- 3 files changed, 256 insertions(+), 350 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 468cc9ba48..1fe6df62e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ _This release is scheduled to be released on 2024-04-01._ - Removing lodash dependency by replacing merge by spread operator (#3339) - Use node prefix for build-in modules (#3340) +- Update electron to v28 and update other dependencies ### Fixed diff --git a/package-lock.json b/package-lock.json index 986e535a5a..22e97abbe9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,22 +24,22 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.17.1", - "socket.io": "^4.7.2", + "socket.io": "^4.7.4", "systeminformation": "^5.21.22" }, "devDependencies": { "@stylistic/eslint-plugin": "^1.5.3", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.1", + "eslint-plugin-jest": "^27.6.3", "eslint-plugin-jsdoc": "^48.0.2", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", "jest": "^29.7.0", - "jsdom": "^23.0.1", + "jsdom": "^23.2.0", "lint-staged": "^15.2.0", - "playwright": "^1.40.1", - "prettier": "^3.1.1", + "playwright": "^1.41.0", + "prettier": "^3.2.2", "sinon": "^17.0.1", "stylelint": "^16.1.0", "stylelint-config-standard": "^36.0.0", @@ -50,7 +50,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^27.2.0" + "electron": "^28.1.3" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -75,9 +75,9 @@ } }, "node_modules/@asamuzakjp/dom-selector": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-2.0.1.tgz", - "integrity": "sha512-QJAJffmCiymkv6YyQ7voyQb5caCth6jzZsQncYCpHXrJ7RqdYG5y43+is8mnFcYubdOkr7cn1+na9BdFMxqw7w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-2.0.2.tgz", + "integrity": "sha512-x1KXOatwofR6ZAYzXRBL5wrdV0vwNxlTCK9NCuLqAzQYARqGcvFwiJA6A1ERuh+dgeA4Dxm3JBYictIes+SqUQ==", "dev": true, "dependencies": { "bidi-js": "^1.0.3", @@ -179,9 +179,9 @@ } }, "node_modules/@babel/core": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", - "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -189,10 +189,10 @@ "@babel/generator": "^7.23.6", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.6", + "@babel/helpers": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.6", + "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -232,6 +232,18 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/generator/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", @@ -383,13 +395,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", - "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", + "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.6", + "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" }, "engines": { @@ -685,9 +697,9 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", - "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.23.5", @@ -735,9 +747,9 @@ "dev": true }, "node_modules/@csstools/css-parser-algorithms": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.4.0.tgz", - "integrity": "sha512-/PPLr2g5PAUCKAPEbfyk6/baZA+WJHQtUhPkoCQMpyRE8I0lXrG1QFRN8e5s3ZYxM8d/g5BZc6lH3s8Op7/VEg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.5.0.tgz", + "integrity": "sha512-abypo6m9re3clXA00eu5syw+oaPHbJTPapu9C4pzNsJ4hdZDzushT50Zhu+iIYXgEe1CxnRMn7ngsbV+MLrlpQ==", "dev": true, "funding": [ { @@ -753,13 +765,13 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^2.2.2" + "@csstools/css-tokenizer": "^2.2.3" } }, "node_modules/@csstools/css-tokenizer": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.2.tgz", - "integrity": "sha512-wCDUe/MAw7npAHFLyW3QjSyLA66S5QFaV1jIXlNQvdJ8RzXDSgALa49eWcUO6P55ARQaz0TsDdAgdRgkXFYY8g==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.3.tgz", + "integrity": "sha512-pp//EvZ9dUmGuGtG1p+n17gTHEOqu9jO+FiCUjNN3BDmyhdA2Jq9QsVeR7K8/2QCK17HSsioPlTW9ZkzoWb3Lg==", "dev": true, "funding": [ { @@ -776,9 +788,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.6.tgz", - "integrity": "sha512-R6AKl9vaU0It7D7TR2lQn0pre5aQfdeqHRePlaRCY8rHL3l9eVlNRpsEVDKFi/zAjzv68CxH2M5kqbhPFPKjvw==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.7.tgz", + "integrity": "sha512-lHPKJDkPUECsyAvD60joYfDmp8UERYxHGkFfyLJFTVK/ERJe0sVlIFLXU5XFxdjNDTerp5L4KeaKG+Z5S94qxQ==", "dev": true, "funding": [ { @@ -794,8 +806,8 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.4.0", - "@csstools/css-tokenizer": "^2.2.2" + "@csstools/css-parser-algorithms": "^2.5.0", + "@csstools/css-tokenizer": "^2.2.3" } }, "node_modules/@csstools/selector-specificity": { @@ -937,12 +949,12 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -982,9 +994,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -1260,6 +1272,21 @@ } } }, + "node_modules/@jest/core/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -1513,9 +1540,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", + "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1768,9 +1795,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", - "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" @@ -1862,9 +1889,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", - "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", + "version": "18.19.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.7.tgz", + "integrity": "sha512-IGRJfoNX10N/PfrReRZ1br/7SQ+2vF/tK3KXNwzXz82D32z5dMQEoOlFew18nLSN+vMNcLY4GrKfzwi/yWI8/w==", "dependencies": { "undici-types": "~5.26.4" } @@ -1921,13 +1948,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz", - "integrity": "sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", + "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0" + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1938,9 +1965,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.18.0.tgz", - "integrity": "sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", + "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1951,13 +1978,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz", - "integrity": "sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", + "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/visitor-keys": "6.18.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/visitor-keys": "6.19.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1979,17 +2006,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.18.0.tgz", - "integrity": "sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", + "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.18.0", - "@typescript-eslint/types": "6.18.0", - "@typescript-eslint/typescript-estree": "6.18.0", + "@typescript-eslint/scope-manager": "6.19.0", + "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.0", "semver": "^7.5.4" }, "engines": { @@ -2004,12 +2031,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz", - "integrity": "sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA==", + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", + "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.18.0", + "@typescript-eslint/types": "6.19.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2683,9 +2710,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001572", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz", - "integrity": "sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==", + "version": "1.0.30001577", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz", + "integrity": "sha512-rs2ZygrG1PNXMfmncM0B5H1hndY5ZCC9b5TkFaVNfZ+AUlyqcMyVIQtc3fsezi0NUCk5XZfDf9WS6WxMxnfdrg==", "dev": true, "funding": [ { @@ -2727,9 +2754,9 @@ } }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", "dev": true, "funding": [ { @@ -3430,9 +3457,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "27.2.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-27.2.1.tgz", - "integrity": "sha512-bYUzyptYrUIFtPnyF2x6DnhF1E9FCthctjbNSKMqg7dG4NqSwyuZzEku3Wts55u8R+ddNFbLoLwRHHLvYTCQlA==", + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/electron/-/electron-28.1.3.tgz", + "integrity": "sha512-NSFyTo6SndTPXzU18XRePv4LnjmuM9rF5GMKta1/kPmi02ISoSRonnD7wUlWXD2x53XyJ6d/TbSVesMW6sXkEQ==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -3448,9 +3475,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.616", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.616.tgz", - "integrity": "sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg==", + "version": "1.4.632", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.632.tgz", + "integrity": "sha512-JGmudTwg7yxMYvR/gWbalqqQiyu7WTFv2Xu3vw4cJHXPFxNgAk0oy8UHaer8nLF4lZJa+rNoj6GsrKIVJTV6Tw==", "dev": true }, "node_modules/emittery": { @@ -3909,9 +3936,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.1.tgz", - "integrity": "sha512-WEYkyVXD9NlmFBKvrkmzrC+C9yZoz5pAml2hO19PlS3spJtoiwj4p2u8spd/7zx5IvRsZsCmsoImaAvBB9X93Q==", + "version": "27.6.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", + "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -4111,33 +4138,6 @@ "eslint": ">=8.56.0" } }, - "node_modules/eslint-plugin-unicorn/node_modules/ci-info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", - "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -4596,7 +4596,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -4605,9 +4605,9 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==" }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", @@ -5742,39 +5742,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-instrument/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/istanbul-lib-report": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", @@ -5983,6 +5950,21 @@ } } }, + "node_modules/jest-config/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -6311,6 +6293,21 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-util/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/jest-validate": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", @@ -6456,15 +6453,15 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -6516,9 +6513,9 @@ } }, "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, "node_modules/keyv": { @@ -6981,39 +6978,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -7060,9 +7024,9 @@ } }, "node_modules/meow": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.0.0.tgz", - "integrity": "sha512-4Hu+75Vo7EOR+8C9RmkabfLijuwd9SrzQ8f0SyC4qZZwU6BlxeOt5ulF3PGCpcMJX4hI+ktpJhea0P6PN1RiWw==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.1.0.tgz", + "integrity": "sha512-o5R/R3Tzxq0PJ3v3qcQJtSvSE9nKOLSAaDuuoMzDVuGTwHdccMWcYomh9Xolng2tjT6O/Y83d+0coVGof6tqmA==", "dev": true, "engines": { "node": ">=18" @@ -7215,9 +7179,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.43", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", - "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", + "version": "0.5.44", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz", + "integrity": "sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==", "dependencies": { "moment": "^2.29.4" }, @@ -7267,41 +7231,32 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/nise": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.5.tgz", - "integrity": "sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw==", + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.7.tgz", + "integrity": "sha512-wWtNUhkT7k58uvWTB/Gy26eA/EJKtPZFVAhEilN5UYVmmGRYOURbejRUyKm0Uu9XVEW7K5nBOZfR8VMB4QR2RQ==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" } }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/nise/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true }, "node_modules/node-ical": { "version": "0.17.1", @@ -7811,12 +7766,12 @@ } }, "node_modules/playwright": { - "version": "1.40.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.1.tgz", - "integrity": "sha512-2eHI7IioIpQ0bS1Ovg/HszsN/XKNwEG1kbzSDDmADpclKc7CyqkHw7Mg2JCz/bbCxg25QUPcjksoMW7JcIFQmw==", + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.0.tgz", + "integrity": "sha512-XOsfl5ZtAik/T9oek4V0jAypNlaCNzuKOwVhqhgYT3os6kH34PzbRb74F0VWcLYa5WFdnmxl7qyAHBXvPv7lqQ==", "dev": true, "dependencies": { - "playwright-core": "1.40.1" + "playwright-core": "1.41.0" }, "bin": { "playwright": "cli.js" @@ -7829,9 +7784,9 @@ } }, "node_modules/playwright-core": { - "version": "1.40.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.1.tgz", - "integrity": "sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==", + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.0.tgz", + "integrity": "sha512-UGKASUhXmvqm2Lxa1fNr8sFwAtqjpgBRr9jQ7XBI8Rn5uFiEowGUGwrruUQsVPIom4bk7Lt+oLGpXobnXzrBIw==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -7864,9 +7819,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "dev": true, "funding": [ { @@ -7924,9 +7879,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.14.tgz", - "integrity": "sha512-65xXYsT40i9GyWzlHQ5ShZoK7JZdySeOozi/tz2EezDo6c04q6+ckYMeoY7idaie1qp2dT5KoYQ2yky6JuoHnA==", + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -7951,9 +7906,9 @@ } }, "node_modules/prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", - "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.2.tgz", + "integrity": "sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -8536,12 +8491,12 @@ } }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -8572,14 +8527,17 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8739,14 +8697,15 @@ } }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", "dependencies": { "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -8888,9 +8847,9 @@ } }, "node_modules/socket.io": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.3.tgz", - "integrity": "sha512-SE+UIQXBQE+GPG2oszWMlsEmWtHVqw/h1VrYJGK5/MC7CH5p58N448HwIrtREcvR4jfdOJAY4ieQfxMr55qbbw==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz", + "integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -9094,48 +9053,27 @@ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=8" } }, "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/string-width-cjs/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, - "dependencies": { - "ansi-regex": "^6.0.1" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/string-width/node_modules/ansi-regex": { @@ -10344,77 +10282,44 @@ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/wrap-ansi-cjs/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, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/wrap-ansi-cjs/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, "dependencies": { - "ansi-regex": "^6.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { diff --git a/package.json b/package.json index 6ecce674bc..196dde586c 100644 --- a/package.json +++ b/package.json @@ -51,16 +51,16 @@ "devDependencies": { "@stylistic/eslint-plugin": "^1.5.3", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.1", + "eslint-plugin-jest": "^27.6.3", "eslint-plugin-jsdoc": "^48.0.2", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", "jest": "^29.7.0", - "jsdom": "^23.0.1", + "jsdom": "^23.2.0", "lint-staged": "^15.2.0", - "playwright": "^1.40.1", - "prettier": "^3.1.1", + "playwright": "^1.41.0", + "prettier": "^3.2.2", "sinon": "^17.0.1", "stylelint": "^16.1.0", "stylelint-config-standard": "^36.0.0", @@ -68,7 +68,7 @@ "suncalc": "^1.9.0" }, "optionalDependencies": { - "electron": "^27.2.0" + "electron": "^28.1.3" }, "dependencies": { "colors": "^1.4.0", @@ -85,7 +85,7 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.17.1", - "socket.io": "^4.7.2", + "socket.io": "^4.7.4", "systeminformation": "^5.21.22" }, "lint-staged": { From 6dbacbb77391543a794fe31cc7cf2533134d292b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 16 Jan 2024 21:54:55 +0100 Subject: [PATCH 014/418] Rework logging colors (#3350) - Replacing old package `colors` by drop-in replacement `ansis` - Rework `console-stamp` config to show all Log outputs in same color (errors = red, warnings = yellow, debug = blue background (only for the label), info = blue) - This also fixes `npm run config:check` (broken since 6097547c103be1bc89c572e5bd2be50b342967fa) Feel free to let me know if the PR is too big and you want me to do individual PRs for the changes. Before: ![before](https://github.com/MagicMirrorOrg/MagicMirror/assets/35647502/88e48ec3-102c-40f3-9e9b-5d14fe446a43) After: ![after](https://github.com/MagicMirrorOrg/MagicMirror/assets/35647502/4c8c4bad-08c9-46a3-92c9-14b996c13a7d) --------- Co-authored-by: Veeck --- CHANGELOG.md | 1 + js/app.js | 8 ++++---- js/check_config.js | 12 +++++------ js/logger.js | 33 ++++++++++++++++++++++++++++-- js/server.js | 2 +- js/utils.js | 11 +++------- package-lock.json | 22 ++++++++++++-------- package.json | 2 +- tests/unit/classes/utils_spec.js | 35 ++------------------------------ 9 files changed, 62 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fe6df62e3..29876fa5bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ _This release is scheduled to be released on 2024-04-01._ - Removing lodash dependency by replacing merge by spread operator (#3339) - Use node prefix for build-in modules (#3340) +- Rework logging colors (#3350) - Update electron to v28 and update other dependencies ### Fixed diff --git a/js/app.js b/js/app.js index 33db688233..086f4ec5c2 100644 --- a/js/app.js +++ b/js/app.js @@ -126,11 +126,11 @@ function App () { return Object.assign(defaults, c); } catch (e) { if (e.code === "ENOENT") { - Log.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration.")); + Log.error("WARNING! Could not find config file. Please create one. Starting with default configuration."); } else if (e instanceof ReferenceError || e instanceof SyntaxError) { - Log.error(Utils.colors.error(`WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: ${e.stack}`)); + Log.error(`WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: ${e.stack}`); } else { - Log.error(Utils.colors.error(`WARNING! Could not load config file. Starting with default configuration. Error found: ${e}`)); + Log.error(`WARNING! Could not load config file. Starting with default configuration. Error found: ${e}`); } } @@ -148,7 +148,7 @@ function App () { const usedDeprecated = deprecatedOptions.filter((option) => userConfig.hasOwnProperty(option)); if (usedDeprecated.length > 0) { - Log.warn(Utils.colors.warn(`WARNING! Your config is using deprecated options: ${usedDeprecated.join(", ")}. Check README and CHANGELOG for more up-to-date ways of getting the same functionality.`)); + Log.warn(`WARNING! Your config is using deprecated options: ${usedDeprecated.join(", ")}. Check README and CHANGELOG for more up-to-date ways of getting the same functionality.`); } } diff --git a/js/check_config.js b/js/check_config.js index b3a0fe9429..d190f22a75 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -7,13 +7,13 @@ */ const path = require("node:path"); const fs = require("node:fs"); +const colors = require("ansis"); const { Linter } = require("eslint"); const linter = new Linter(); const rootPath = path.resolve(`${__dirname}/../`); const Log = require(`${rootPath}/js/logger.js`); -const Utils = require(`${rootPath}/js/utils.js`); /** * Returns a string with path of configuration file. @@ -33,7 +33,7 @@ function checkConfigFile () { // Check if file is present if (fs.existsSync(configFileName) === false) { - Log.error(Utils.colors.error("File not found: "), configFileName); + Log.error(`File not found: ${configFileName}`); throw new Error("No config file present!"); } @@ -41,12 +41,12 @@ function checkConfigFile () { try { fs.accessSync(configFileName, fs.F_OK); } catch (e) { - Log.error(Utils.colors.error(e)); + Log.error(e); throw new Error("No permission to access config file!"); } // Validate syntax of the configuration file. - Log.info(Utils.colors.info("Checking file... "), configFileName); + Log.info("Checking file... ", configFileName); // I'm not sure if all ever is utf-8 const configFile = fs.readFileSync(configFileName, "utf-8"); @@ -59,9 +59,9 @@ function checkConfigFile () { }); if (errors.length === 0) { - Log.info(Utils.colors.pass("Your configuration file doesn't contain syntax errors :)")); + Log.info(colors.green("Your configuration file doesn't contain syntax errors :)")); } else { - Log.error(Utils.colors.error("Your configuration file contains syntax errors :(")); + Log.error(colors.red("Your configuration file contains syntax errors :(")); for (const error of errors) { Log.error(`Line ${error.line} column ${error.column}: ${error.message}`); diff --git a/js/logger.js b/js/logger.js index 228c53e999..da295bb990 100644 --- a/js/logger.js +++ b/js/logger.js @@ -10,10 +10,39 @@ (function (root, factory) { if (typeof exports === "object") { if (process.env.JEST_WORKER_ID === undefined) { + const colors = require("ansis"); + // add timestamps in front of log messages require("console-stamp")(console, { - pattern: "yyyy-mm-dd HH:MM:ss.l", - include: ["debug", "log", "info", "warn", "error"] + format: ":date(yyyy-mm-dd HH:MM:ss.l) :label(7) :msg", + tokens: { + label: (arg) => { + const { method, defaultTokens } = arg; + let label = defaultTokens.label(arg); + if (method === "error") { + label = colors.red(label); + } else if (method === "warn") { + label = colors.yellow(label); + } else if (method === "debug") { + label = colors.bgBlue(label); + } else if (method === "info") { + label = colors.blue(label); + } + return label; + }, + msg: (arg) => { + const { method, defaultTokens } = arg; + let msg = defaultTokens.msg(arg); + if (method === "error") { + msg = colors.red(msg); + } else if (method === "warn") { + msg = colors.yellow(msg); + } else if (method === "info") { + msg = colors.blue(msg); + } + return msg; + } + } }); } // Node, CommonJS-like diff --git a/js/server.js b/js/server.js index a183fe4df8..03de57ebef 100644 --- a/js/server.js +++ b/js/server.js @@ -62,7 +62,7 @@ function Server (config) { server.listen(port, config.address || "localhost"); if (config.ipWhitelist instanceof Array && config.ipWhitelist.length === 0) { - Log.warn(Utils.colors.warn("You're using a full whitelist configuration to allow for all IPs")); + Log.warn("You're using a full whitelist configuration to allow for all IPs"); } app.use(function (req, res, next) { diff --git a/js/utils.js b/js/utils.js index b3b2992a69..395feceff9 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,21 +1,13 @@ /* MagicMirror² * Utils * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com * MIT Licensed. */ const execSync = require("node:child_process").execSync; -const colors = require("colors/safe"); const Log = require("logger"); const si = require("systeminformation"); module.exports = { - colors: { - warn: colors.yellow, - error: colors.red, - info: colors.blue, - pass: colors.green - }, async logSystemInformation () { try { @@ -32,6 +24,9 @@ module.exports = { systemDataString += `\n### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData["versions"]["node"]}; installed node: ${installedNodeVersion}; npm: ${staticData["versions"]["npm"]}; pm2: ${staticData["versions"]["pm2"]}`; systemDataString += `\n### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}`; Log.info(systemDataString); + + // Return is currently only for jest + return systemDataString; } catch (e) { Log.error(e); } diff --git a/package-lock.json b/package-lock.json index 22e97abbe9..557bbc0f5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "colors": "^1.4.0", + "ansis": "^2.0.3", "command-exists": "^1.2.9", "console-stamp": "^3.1.2", "envsub": "^4.1.0", @@ -2159,6 +2159,18 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansis": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-2.0.3.tgz", + "integrity": "sha512-tcSGX0mhuDFHsgRrT56xnZ9v2X+TOeKhJ75YopI5OBgyT7tGaG5m6BmeC+6KHjiucfBvUHehQMecHbULIAkFPA==", + "engines": { + "node": ">=12.13" + }, + "funding": { + "type": "patreon", + "url": "https://patreon.com/biodiscus" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2952,14 +2964,6 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", diff --git a/package.json b/package.json index 196dde586c..fea92522fe 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "electron": "^28.1.3" }, "dependencies": { - "colors": "^1.4.0", + "ansis": "^2.0.3", "command-exists": "^1.2.9", "console-stamp": "^3.1.2", "envsub": "^4.1.0", diff --git a/tests/unit/classes/utils_spec.js b/tests/unit/classes/utils_spec.js index bf7a5c593a..772bdf61df 100644 --- a/tests/unit/classes/utils_spec.js +++ b/tests/unit/classes/utils_spec.js @@ -1,38 +1,7 @@ -const colors = require("colors/safe"); const Utils = require("../../../js/utils"); describe("Utils", () => { - describe("colors", () => { - const colorsEnabled = colors.enabled; - - afterEach(() => { - colors.enabled = colorsEnabled; - }); - - it("should have info, warn and error properties", () => { - expect(Utils.colors).toHaveProperty("info"); - expect(Utils.colors).toHaveProperty("warn"); - expect(Utils.colors).toHaveProperty("error"); - }); - - it("properties should be functions", () => { - expect(typeof Utils.colors.info).toBe("function"); - expect(typeof Utils.colors.warn).toBe("function"); - expect(typeof Utils.colors.error).toBe("function"); - }); - - it("should print colored message in supported consoles", () => { - colors.enabled = true; - expect(Utils.colors.info("some informations")).toBe("\u001b[34msome informations\u001b[39m"); - expect(Utils.colors.warn("a warning")).toBe("\u001b[33ma warning\u001b[39m"); - expect(Utils.colors.error("ERROR!")).toBe("\u001b[31mERROR!\u001b[39m"); - }); - - it("should print message in unsupported consoles", () => { - colors.enabled = false; - expect(Utils.colors.info("some informations")).toBe("some informations"); - expect(Utils.colors.warn("a warning")).toBe("a warning"); - expect(Utils.colors.error("ERROR!")).toBe("ERROR!"); - }); + it("should output system information", async () => { + await expect(Utils.logSystemInformation()).resolves.toContain("platform: linux"); }); }); From 35e4dfb3fe9eef14457bc826ac9ab281502573e8 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 16 Jan 2024 23:16:47 +0100 Subject: [PATCH 015/418] Ignore all custom css files (#3359) For experimenting, I sometimes work with different CSS files. I can imagine that others do this too. This setting for the css folder corresponds to the setting we already have for the config folder. --- .gitignore | 6 ++++-- CHANGELOG.md | 7 ++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 861213ce73..945c6c244b 100644 --- a/.gitignore +++ b/.gitignore @@ -63,8 +63,10 @@ Temporary Items !/modules/default/** !/modules/README.md** -# Ignore changes to the custom css files. -/css/custom.css +# Ignore changes to the custom css files but keep the sample and main. +/css/* +!/css/custom.css.sample +!/css/main.css # Ignore users config file but keep the sample. /config/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 29876fa5bf..9c3268b7eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,13 +18,14 @@ _This release is scheduled to be released on 2024-04-01._ - Removing lodash dependency by replacing merge by spread operator (#3339) - Use node prefix for build-in modules (#3340) - Rework logging colors (#3350) -- Update electron to v28 and update other dependencies +- Update electron to v28 and update other dependencies (#3357) ### Fixed - Skip changelog requirement when running tests for dependency updates (#3320) -- [newsfeed] Suppress unsightly animation cases when there are 0 or 1 active news items -- [newsfeed] Always compute the feed item URL using the same helper function +- [newsfeed] Suppress unsightly animation cases when there are 0 or 1 active news items (#3336) +- [newsfeed] Always compute the feed item URL using the same helper function (#3336) +- Ignore all custom css files (#3359) ### Deleted From b005a8f30eddbefbf0b9d40bb940e44ce519c395 Mon Sep 17 00:00:00 2001 From: Ross Younger Date: Fri, 19 Jan 2024 00:05:26 +1300 Subject: [PATCH 016/418] [newsfeed] Fix bug where the newsfeed sometimes stops (#3361) It appears that #3336 introduced a bug where a newsfeed with >1 items would stop updating after a while (usually after `activeItem` wraps around the end of the list). Sorry! My bad, I hadn't tested that case well enough. --- CHANGELOG.md | 1 + modules/default/newsfeed/newsfeed.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c3268b7eb..099cb7c88d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ _This release is scheduled to be released on 2024-04-01._ - [newsfeed] Suppress unsightly animation cases when there are 0 or 1 active news items (#3336) - [newsfeed] Always compute the feed item URL using the same helper function (#3336) - Ignore all custom css files (#3359) +- [newsfeed] Fix newsfeed stall issue introduced by #3336 (#3361) ### Deleted diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 2ecd2ad645..329c04bb33 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -335,7 +335,7 @@ Module.register("newsfeed", { * * (N.B. We set activeItemCount and activeItemHash in getTemplateData().) */ - if (this.newsItems.length !== this.activeItemCount || this.activeItemHash !== this.newsItems[0]?.hash) { + if (this.newsItems.length > 1 || this.newsItems.length !== this.activeItemCount || this.activeItemHash !== this.newsItems[0]?.hash) { this.activeItem++; // this is OK if newsItems.Length==1; getTemplateData will wrap it around this.updateDom(this.config.animationSpeed); } From c09338ab806e3448c94ba11ab95cff1ad467168b Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Thu, 18 Jan 2024 19:18:58 +0100 Subject: [PATCH 017/418] changed `log.debug` to `log.log` in `app.js` (#3362) where logLevel is not set because config is not loaded at this time, see #3353 --- CHANGELOG.md | 1 + js/app.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 099cb7c88d..5de50d3462 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ _This release is scheduled to be released on 2024-04-01._ - [newsfeed] Always compute the feed item URL using the same helper function (#3336) - Ignore all custom css files (#3359) - [newsfeed] Fix newsfeed stall issue introduced by #3336 (#3361) +- Changed `log.debug` to `log.log` in `app.js` where logLevel is not set because config is not loaded at this time (#3353) ### Deleted diff --git a/js/app.js b/js/app.js index 086f4ec5c2..05212f2e11 100644 --- a/js/app.js +++ b/js/app.js @@ -76,7 +76,7 @@ function App () { fs.accessSync(templateFile, fs.F_OK); } catch (err) { templateFile = null; - Log.debug("config template file not exists, no envsubst"); + Log.log("config template file not exists, no envsubst"); } if (templateFile) { @@ -97,7 +97,7 @@ function App () { envFiles.push(configEnvFile); } } catch (err) { - Log.debug(`${configEnvFile} does not exist. ${err.message}`); + Log.log(`${configEnvFile} does not exist. ${err.message}`); } let options = { From 995b61b6894bfc17df0b2231c7e48114d0332791 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Jan 2024 17:35:49 +0100 Subject: [PATCH 018/418] Bump follow-redirects from 1.15.3 to 1.15.5 (#3356) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.3 to 1.15.5.
Commits
  • b1677ce Release version 1.15.5 of the npm package.
  • d8914f7 Preserve fragment in responseUrl.
  • 6585820 Release version 1.15.4 of the npm package.
  • 7a6567e Disallow bracketed hostnames.
  • 05629af Prefer native URL instead of deprecated url.parse.
  • 1cba8e8 Prefer native URL instead of legacy url.resolve.
  • 72bc2a4 Simplify _processResponse error handling.
  • 3d42aec Add bracket tests.
  • bcbb096 Do not directly set Error properties.
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.3&new-version=1.15.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/MagicMirrorOrg/MagicMirror/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From c96ced91374aca23c8684848e44d76c5d29a54b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Sat, 20 Jan 2024 17:38:22 +0100 Subject: [PATCH 019/418] updatenotification: update_helper.js recode with pm2 library (v2.27.x) (#3332) #3285 Because there is so many conflit with package, I have rewrite the code with v2.27.0-develop For remember: * recode: `update_helper.js` with `pm2` library * fix: default config -> `updates` is a array * delete: `command-exists` library (not used) * delete: `PM2_GetList()` function (not used) * add: check `updates.length` (prevent crash) * add: `[PM2]` tag in log (for better visibility) * add: `pm2` library advantage: * we use the pm2 library directly * avoids weird returns from child_process.exec when requesting a json format from pm2 * simplified the code inconvenient: * we have vulnerabilities with axios 240120 Fix: * use `pm2_env.pm_cwd` instead of `pm2_env.PWD` : prevent using `pm2 restart --update-env` in other directory (for enable GPU rendering for exemple) * resolve packages (again) --- .github/workflows/depsreview.yaml | 2 + CHANGELOG.md | 1 + .../updatenotification/update_helper.js | 53 +- .../updatenotification/updatenotification.js | 2 +- package-lock.json | 1105 ++++++++++++++++- package.json | 2 +- 6 files changed, 1071 insertions(+), 94 deletions(-) diff --git a/.github/workflows/depsreview.yaml b/.github/workflows/depsreview.yaml index 7d8866d89b..d70d79d38a 100644 --- a/.github/workflows/depsreview.yaml +++ b/.github/workflows/depsreview.yaml @@ -16,3 +16,5 @@ jobs: uses: actions/checkout@v4 - name: "Dependency Review" uses: actions/dependency-review-action@v3 + with: + allow-ghsas: GHSA-wf5p-g6vw-rhxx diff --git a/CHANGELOG.md b/CHANGELOG.md index 5de50d3462..0b6138f847 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ _This release is scheduled to be released on 2024-04-01._ ### Updated +- Update updatenotification (update_helper.js): Recode with pm2 library (#3332) - Removing lodash dependency by replacing merge by spread operator (#3339) - Use node prefix for build-in modules (#3340) - Rework logging colors (#3350) diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index 00afb65836..33130f1988 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -1,6 +1,7 @@ const Exec = require("node:child_process").exec; const Spawn = require("node:child_process").spawn; -const commandExists = require("command-exists"); +const pm2 = require("pm2"); + const Log = require("logger"); /* class Updater @@ -138,7 +139,7 @@ class Updater { // restart MagicMiror with "pm2" pm2Restart () { Log.info("updatenotification: PM2 will restarting MagicMirror..."); - Exec(`pm2 restart ${this.PM2}`, (err, std, sde) => { + pm2.restart(this.PM2, (err, proc) => { if (err) { Log.error("updatenotification:[PM2] restart Error", err); } @@ -159,53 +160,35 @@ class Updater { check_PM2_Process () { Log.info("updatenotification: Checking PM2 using..."); return new Promise((resolve) => { - commandExists("pm2") - .then(async () => { - var PM2_List = await this.PM2_GetList(); - if (!PM2_List) { + pm2.connect((err) => { + if (err) { + Log.error("updatenotification: [PM2]", err); + this.usePM2 = false; + resolve(false); + return; + } + pm2.list((err, list) => { + if (err) { Log.error("updatenotification: [PM2] Can't get process List!"); this.usePM2 = false; resolve(false); return; } - PM2_List.forEach((pm) => { - if (pm.pm2_env.version === this.version && pm.pm2_env.status === "online" && pm.pm2_env.PWD.includes(this.root_path)) { + list.forEach((pm) => { + if (pm.pm2_env.version === this.version && pm.pm2_env.status === "online" && pm.pm2_env.pm_cwd.includes(`${this.root_path}/`)) { this.PM2 = pm.name; this.usePM2 = true; - Log.info("updatenotification: You are using pm2 with", this.PM2); + Log.info("updatenotification: [PM2] You are using pm2 with", this.PM2); resolve(true); } }); + pm2.disconnect(); if (!this.PM2) { - Log.info("updatenotification: You are not using pm2"); + Log.info("updatenotification: [PM2] You are not using pm2"); this.usePM2 = false; resolve(false); } - }) - .catch(() => { - Log.info("updatenotification: You are not using pm2"); - this.usePM2 = false; - resolve(false); }); - }); - } - - // Get the list of pm2 process - PM2_GetList () { - return new Promise((resolve) => { - Exec("pm2 jlist", (err, std, sde) => { - if (err) { - resolve(null); - return; - } - try { - let result = JSON.parse(std); - resolve(result); - } catch (e) { - Log.error("updatenotification: [PM2] can't GetList!"); - Log.debug("updatenotification: [PM2] GetList is not an JSON format", e); - resolve(null); - } }); }); } @@ -218,7 +201,7 @@ class Updater { // search update module command applyCommand (module) { - if (this.isMagicMirror(module.module)) return null; + if (this.isMagicMirror(module.module) || !this.updates.length) return null; let command = null; this.updates.forEach((updater) => { if (updater[module]) command = updater[module]; diff --git a/modules/default/updatenotification/updatenotification.js b/modules/default/updatenotification/updatenotification.js index eb5528e114..3973c35961 100644 --- a/modules/default/updatenotification/updatenotification.js +++ b/modules/default/updatenotification/updatenotification.js @@ -18,7 +18,7 @@ Module.register("updatenotification", { suspended: false, moduleList: {}, needRestart: false, - updates: {}, + updates: [], start () { Log.info(`Starting module: ${this.name}`); diff --git a/package-lock.json b/package-lock.json index 557bbc0f5a..da68f8fe00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "license": "MIT", "dependencies": { "ansis": "^2.0.3", - "command-exists": "^1.2.9", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.56.0", @@ -24,7 +23,7 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.17.1", - "socket.io": "^4.7.4", + "pm2": "^5.3.0", "systeminformation": "^5.21.22" }, "devDependencies": { @@ -1581,6 +1580,82 @@ "node": ">= 8" } }, + "node_modules/@opencensus/core": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.9.tgz", + "integrity": "sha512-31Q4VWtbzXpVUd2m9JS6HEaPjlKvNMOiF7lWKNmXF84yUcgfAFL5re7/hjDmdyQbOp32oGc+RFV78jXIldVz6Q==", + "dependencies": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^5.5.0", + "shimmer": "^1.2.0", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/core/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@opencensus/core/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/@opencensus/propagation-b3": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@opencensus/propagation-b3/-/propagation-b3-0.0.8.tgz", + "integrity": "sha512-PffXX2AL8Sh0VHQ52jJC4u3T0H6wDK6N/4bg7xh4ngMYOIi13aR1kzVvX1sVDBgfGwDOkMbl4c54Xm3tlPx/+A==", + "dependencies": { + "@opencensus/core": "^0.0.8", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/propagation-b3/node_modules/@opencensus/core": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.8.tgz", + "integrity": "sha512-yUFT59SFhGMYQgX0PhoTR0LBff2BEhPrD9io1jWfF/VDbakRfs6Pq60rjv0Z7iaTav5gQlttJCX2+VPxFWCuoQ==", + "dependencies": { + "continuation-local-storage": "^3.2.1", + "log-driver": "^1.2.7", + "semver": "^5.5.0", + "shimmer": "^1.2.0", + "uuid": "^3.2.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@opencensus/propagation-b3/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@opencensus/propagation-b3/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1591,6 +1666,160 @@ "node": ">=14" } }, + "node_modules/@pm2/agent": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.3.tgz", + "integrity": "sha512-xkqqCoTf5VsciMqN0vb9jthW7olVAi4KRFNddCc7ZkeJZ3i8QwZANr4NSH2H5DvseRFHq7MiPspRY/EWAFWWTg==", + "dependencies": { + "async": "~3.2.0", + "chalk": "~3.0.0", + "dayjs": "~1.8.24", + "debug": "~4.3.1", + "eventemitter2": "~5.0.1", + "fast-json-patch": "^3.0.0-1", + "fclone": "~1.0.11", + "nssocket": "0.6.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.0", + "proxy-agent": "~6.3.0", + "semver": "~7.5.0", + "ws": "~7.4.0" + } + }, + "node_modules/@pm2/agent/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@pm2/agent/node_modules/dayjs": { + "version": "1.8.36", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz", + "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==" + }, + "node_modules/@pm2/agent/node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@pm2/io": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-5.0.2.tgz", + "integrity": "sha512-XAvrNoQPKOyO/jJyCu8jPhLzlyp35MEf7w/carHXmWKddPzeNOFSEpSEqMzPDawsvpxbE+i918cNN+MwgVsStA==", + "dependencies": { + "@opencensus/core": "0.0.9", + "@opencensus/propagation-b3": "0.0.8", + "async": "~2.6.1", + "debug": "~4.3.1", + "eventemitter2": "^6.3.1", + "require-in-the-middle": "^5.0.0", + "semver": "~7.5.4", + "shimmer": "^1.2.0", + "signal-exit": "^3.0.3", + "tslib": "1.9.3" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@pm2/io/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/@pm2/io/node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + }, + "node_modules/@pm2/js-api": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.6.7.tgz", + "integrity": "sha512-jiJUhbdsK+5C4zhPZNnyA3wRI01dEc6a2GhcQ9qI38DyIk+S+C8iC3fGjcjUbt/viLYKPjlAaE+hcT2/JMQPXw==", + "dependencies": { + "async": "^2.6.3", + "axios": "^0.21.0", + "debug": "~4.3.1", + "eventemitter2": "^6.3.1", + "ws": "^7.0.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@pm2/js-api/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/@pm2/js-api/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/@pm2/js-api/node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + }, + "node_modules/@pm2/js-api/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@pm2/pm2-version-check": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz", + "integrity": "sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==", + "dependencies": { + "debug": "^4.3.1" + } + }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", @@ -1762,6 +1991,11 @@ "node": ">=10" } }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2087,7 +2321,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", - "dev": true, "dependencies": { "debug": "^4.3.4" }, @@ -2110,6 +2343,27 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/amp": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", + "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==" + }, + "node_modules/amp-message": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz", + "integrity": "sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==", + "dependencies": { + "amp": "0.3.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -2175,7 +2429,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -2318,6 +2571,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -2327,6 +2596,31 @@ "node": ">=8" } }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "node_modules/async-listener": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", + "integrity": "sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw==", + "dependencies": { + "semver": "^5.3.0", + "shimmer": "^1.1.0" + }, + "engines": { + "node": "<=0.11.8 || >0.11.10" + } + }, + "node_modules/async-listener/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2500,6 +2794,14 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/basic-ftp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.4.tgz", + "integrity": "sha512-8PzkB0arJFV4jJWSGOYR+OEic6aeKMu/osRhBULN6RY0ykby6LKhbmuQ5ublvaas5BOwboah5D87nrHyuh8PPA==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/bidi-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", @@ -2509,11 +2811,35 @@ "require-from-string": "^2.0.2" } }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/blessed": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", + "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==", + "bin": { + "blessed": "bin/tput.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "node_modules/bodec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", + "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==" + }, "node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -2580,7 +2906,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -2641,8 +2966,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/builtin-modules": { "version": "3.3.0", @@ -2765,6 +3089,48 @@ "node": ">=10" } }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ci-info": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", @@ -2832,6 +3198,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-tableau": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz", + "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==", + "dependencies": { + "chalk": "3.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/cli-tableau/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cli-truncate": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", @@ -2975,11 +3364,6 @@ "node": ">= 0.8" } }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -3033,6 +3417,15 @@ "node": ">= 0.6" } }, + "node_modules/continuation-local-storage": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", + "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", + "dependencies": { + "async-listener": "^0.6.0", + "emitter-listener": "^1.1.1" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -3124,6 +3517,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/croner": { + "version": "4.1.97", + "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -3183,6 +3581,19 @@ "node": ">=18" } }, + "node_modules/culvert": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", + "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==" + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", + "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", + "engines": { + "node": ">= 14" + } + }, "node_modules/data-urls": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", @@ -3204,6 +3615,11 @@ "node": "*" } }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -3318,6 +3734,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3484,6 +3913,14 @@ "integrity": "sha512-JGmudTwg7yxMYvR/gWbalqqQiyu7WTFv2Xu3vw4cJHXPFxNgAk0oy8UHaer8nLF4lZJa+rNoj6GsrKIVJTV6Tw==", "dev": true }, + "node_modules/emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "dependencies": { + "shimmer": "^1.2.0" + } + }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", @@ -3575,6 +4012,17 @@ } } }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -3756,6 +4204,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, "node_modules/eslint": { "version": "8.56.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", @@ -4208,7 +4676,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4263,6 +4730,11 @@ "node": ">= 0.6" } }, + "node_modules/eventemitter2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", + "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==" + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -4465,6 +4937,11 @@ "node": ">= 6" } }, + "node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4501,6 +4978,11 @@ "bser": "2.1.1" } }, + "node_modules/fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -4537,7 +5019,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -4696,7 +5177,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "optional": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -4715,7 +5195,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -4841,6 +5320,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-uri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", + "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.0", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/git-node-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", + "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==" + }, + "node_modules/git-sha1": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", + "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -5039,8 +5542,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "devOptional": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", @@ -5243,7 +5745,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", - "dev": true, "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -5269,7 +5770,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", - "dev": true, "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -5389,8 +5889,7 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/internal-slot": { "version": "1.0.6", @@ -5456,6 +5955,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -5501,7 +6011,6 @@ "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, "dependencies": { "hasown": "^2.0.0" }, @@ -5578,7 +6087,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -6390,6 +6898,17 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/js-git": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", + "integrity": "sha512-+E5ZH/HeRnoc/LW0AmAyhU+mNcWBzAKE+30+IDMLSLbbK+Tdt02AdkOKq9u15rlJsDEGFqtgckc8ZM59LhhiUA==", + "dependencies": { + "bodec": "^0.1.0", + "culvert": "^0.1.2", + "git-sha1": "^0.1.2", + "pako": "^0.2.5" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6511,7 +7030,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optional": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -6554,6 +7072,14 @@ "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", "dev": true }, + "node_modules/lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==", + "engines": { + "node": ">=0.2.0" + } + }, "node_modules/leac": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", @@ -6833,6 +7359,14 @@ "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true }, + "node_modules/log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "engines": { + "node": ">=0.8.6" + } + }, "node_modules/log-update": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", @@ -7169,11 +7703,27 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/module-alias": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz", "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==" }, + "node_modules/module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -7198,6 +7748,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -7213,14 +7768,49 @@ "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/needle": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/needle/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -7234,6 +7824,14 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "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==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/nise": { "version": "5.1.7", "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.7.tgz", @@ -7310,7 +7908,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7339,6 +7936,23 @@ "node": ">=8" } }, + "node_modules/nssocket": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", + "integrity": "sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==", + "dependencies": { + "eventemitter2": "~0.4.14", + "lazy": "~1.0.11" + }, + "engines": { + "node": ">= 0.10.x" + } + }, + "node_modules/nssocket/node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7522,6 +8136,42 @@ "node": ">=6" } }, + "node_modules/pac-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "pac-resolver": "^7.0.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", + "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "dependencies": { + "degenerator": "^5.0.0", + "ip": "^1.1.8", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -7610,8 +8260,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { "version": "1.10.1", @@ -7676,7 +8325,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -7696,6 +8344,17 @@ "node": ">=0.10" } }, + "node_modules/pidusage": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz", + "integrity": "sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==", + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -7822,6 +8481,150 @@ "node": ">=4" } }, + "node_modules/pm2": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.3.0.tgz", + "integrity": "sha512-xscmQiAAf6ArVmKhjKTeeN8+Td7ZKnuZFFPw1DGkdFPR/0Iyx+m+1+OpCdf9+HQopX3VPc9/wqPQHqVOfHum9w==", + "dependencies": { + "@pm2/agent": "~2.0.0", + "@pm2/io": "~5.0.0", + "@pm2/js-api": "~0.6.7", + "@pm2/pm2-version-check": "latest", + "async": "~3.2.0", + "blessed": "0.1.81", + "chalk": "3.0.0", + "chokidar": "^3.5.3", + "cli-tableau": "^2.0.0", + "commander": "2.15.1", + "croner": "~4.1.92", + "dayjs": "~1.11.5", + "debug": "^4.3.1", + "enquirer": "2.3.6", + "eventemitter2": "5.0.1", + "fclone": "1.0.11", + "mkdirp": "1.0.4", + "needle": "2.4.0", + "pidusage": "~3.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.1", + "pm2-deploy": "~1.0.2", + "pm2-multimeter": "^0.1.2", + "promptly": "^2", + "semver": "^7.2", + "source-map-support": "0.5.21", + "sprintf-js": "1.1.2", + "vizion": "~2.2.1", + "yamljs": "0.3.0" + }, + "bin": { + "pm2": "bin/pm2", + "pm2-dev": "bin/pm2-dev", + "pm2-docker": "bin/pm2-docker", + "pm2-runtime": "bin/pm2-runtime" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "pm2-sysmonit": "^1.2.8" + } + }, + "node_modules/pm2-axon": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz", + "integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==", + "dependencies": { + "amp": "~0.3.1", + "amp-message": "~0.1.1", + "debug": "^4.3.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/pm2-axon-rpc": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz", + "integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==", + "dependencies": { + "debug": "^4.3.1" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/pm2-deploy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-1.0.2.tgz", + "integrity": "sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==", + "dependencies": { + "run-series": "^1.1.8", + "tv4": "^1.3.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pm2-multimeter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz", + "integrity": "sha512-S+wT6XfyKfd7SJIBqRgOctGxaBzUOmVQzTAS+cg04TsEUObJVreha7lvCfX8zzGVr871XwCSnHUU7DQQ5xEsfA==", + "dependencies": { + "charm": "~0.1.1" + } + }, + "node_modules/pm2-sysmonit": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz", + "integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==", + "optional": true, + "dependencies": { + "async": "^3.2.0", + "debug": "^4.3.1", + "pidusage": "^2.0.21", + "systeminformation": "^5.7", + "tx2": "~1.0.4" + } + }, + "node_modules/pm2-sysmonit/node_modules/pidusage": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", + "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", + "optional": true, + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pm2/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pm2/node_modules/commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "node_modules/pm2/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/postcss": { "version": "8.4.33", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", @@ -7971,6 +8774,14 @@ "node": ">=0.4.0" } }, + "node_modules/promptly": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", + "integrity": "sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==", + "dependencies": { + "read": "^1.0.4" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -7996,6 +8807,32 @@ "node": ">= 0.10" } }, + "node_modules/proxy-agent": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -8143,6 +8980,17 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -8245,6 +9093,17 @@ "node": ">=8" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/regexp-tree": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", @@ -8317,6 +9176,19 @@ "node": ">=0.10.0" } }, + "node_modules/require-in-the-middle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", + "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -8327,7 +9199,6 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -8466,6 +9337,11 @@ "tslib": "^2.4.0" } }, + "node_modules/rrule/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/rrweb-cssom": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", @@ -8494,6 +9370,25 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/run-series": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", + "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-array-concat": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", @@ -8583,7 +9478,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "devOptional": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -8604,7 +9498,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "devOptional": true, "dependencies": { "yallist": "^4.0.0" }, @@ -8615,8 +9508,7 @@ "node_modules/semver/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "devOptional": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/send": { "version": "0.18.0", @@ -8752,6 +9644,11 @@ "node": ">=8" } }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -8768,8 +9665,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sinon": { "version": "17.0.1", @@ -8850,6 +9746,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/socket.io": { "version": "4.7.4", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz", @@ -8907,6 +9812,37 @@ "node": ">=10.0.0" } }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/socks/node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -8977,10 +9913,9 @@ "dev": true }, "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "optional": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" }, "node_modules/stack-utils": { "version": "2.0.6", @@ -9552,7 +10487,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -9741,7 +10675,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -9839,9 +10772,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -9858,11 +10791,22 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/tv4": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", + "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tx2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz", + "integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==", + "optional": true, + "dependencies": { + "json-stringify-safe": "^5.0.1" + } }, "node_modules/type-check": { "version": "0.4.0", @@ -10017,7 +10961,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "optional": true, "engines": { "node": ">= 4.0.0" } @@ -10146,6 +11089,28 @@ "node": ">= 0.8" } }, + "node_modules/vizion": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vizion/-/vizion-2.2.1.tgz", + "integrity": "sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==", + "dependencies": { + "async": "^2.6.3", + "git-node-fs": "^1.0.0", + "ini": "^1.3.5", + "js-git": "^0.7.8" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vizion/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", @@ -10443,6 +11408,32 @@ "node": ">= 14" } }, + "node_modules/yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "dependencies": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + }, + "bin": { + "json2yaml": "bin/json2yaml", + "yaml2json": "bin/yaml2json" + } + }, + "node_modules/yamljs/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/yamljs/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index fea92522fe..dd88a2dbf0 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ }, "dependencies": { "ansis": "^2.0.3", - "command-exists": "^1.2.9", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.56.0", @@ -85,6 +84,7 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.17.1", + "pm2": "^5.3.0", "socket.io": "^4.7.4", "systeminformation": "^5.21.22" }, From c75b7d4a706b73f09688c1a84e8a98927623e118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Sat, 20 Jan 2024 22:55:01 +0100 Subject: [PATCH 020/418] pm2 update ;) (#3364) `pm2` just updated to v5.3.1 with `0 vulnerabilities` let's delete `allow-ghsas` in depsreview and update dependencies --- .github/workflows/depsreview.yaml | 2 -- CHANGELOG.md | 1 + package-lock.json | 35 ++++++++++++++++--------------- package.json | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/depsreview.yaml b/.github/workflows/depsreview.yaml index d70d79d38a..7d8866d89b 100644 --- a/.github/workflows/depsreview.yaml +++ b/.github/workflows/depsreview.yaml @@ -16,5 +16,3 @@ jobs: uses: actions/checkout@v4 - name: "Dependency Review" uses: actions/dependency-review-action@v3 - with: - allow-ghsas: GHSA-wf5p-g6vw-rhxx diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b6138f847..c0884bc48d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ _This release is scheduled to be released on 2024-04-01._ - Use node prefix for build-in modules (#3340) - Rework logging colors (#3350) - Update electron to v28 and update other dependencies (#3357) +- Update pm2 to v5.3.1 with no allow-ghsas (#3364) ### Fixed diff --git a/package-lock.json b/package-lock.json index da68f8fe00..09fe1f6e2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,8 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.17.1", - "pm2": "^5.3.0", + "pm2": "^5.3.1", + "socket.io": "^4.7.4", "systeminformation": "^5.21.22" }, "devDependencies": { @@ -1757,14 +1758,14 @@ "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" }, "node_modules/@pm2/js-api": { - "version": "0.6.7", - "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.6.7.tgz", - "integrity": "sha512-jiJUhbdsK+5C4zhPZNnyA3wRI01dEc6a2GhcQ9qI38DyIk+S+C8iC3fGjcjUbt/viLYKPjlAaE+hcT2/JMQPXw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.8.0.tgz", + "integrity": "sha512-nmWzrA/BQZik3VBz+npRcNIu01kdBhWL0mxKmP1ciF/gTcujPTQqt027N9fc1pK9ERM8RipFhymw7RcmCyOEYA==", "dependencies": { "async": "^2.6.3", - "axios": "^0.21.0", "debug": "~4.3.1", "eventemitter2": "^6.3.1", + "extrareqp2": "^1.0.0", "ws": "^7.0.0" }, "engines": { @@ -1779,14 +1780,6 @@ "lodash": "^4.17.14" } }, - "node_modules/@pm2/js-api/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, "node_modules/@pm2/js-api/node_modules/eventemitter2": { "version": "6.4.9", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", @@ -4898,6 +4891,14 @@ "@types/yauzl": "^2.9.1" } }, + "node_modules/extrareqp2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz", + "integrity": "sha512-Gum0g1QYb6wpPJCVypWP3bbIuaibcFiJcpuPM10YSXp/tzqi84x9PJageob+eN4xVRIOto4wjSGNLyMD54D2xA==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -8482,13 +8483,13 @@ } }, "node_modules/pm2": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.3.0.tgz", - "integrity": "sha512-xscmQiAAf6ArVmKhjKTeeN8+Td7ZKnuZFFPw1DGkdFPR/0Iyx+m+1+OpCdf9+HQopX3VPc9/wqPQHqVOfHum9w==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.3.1.tgz", + "integrity": "sha512-DLVQHpSR1EegaTaRH3KbRXxpPVaqYwAp3uHSCtCsS++LSErvk07WSxuUnntFblBRqNU/w2KQyqs12mSq5wurkg==", "dependencies": { "@pm2/agent": "~2.0.0", "@pm2/io": "~5.0.0", - "@pm2/js-api": "~0.6.7", + "@pm2/js-api": "~0.8.0", "@pm2/pm2-version-check": "latest", "async": "~3.2.0", "blessed": "0.1.81", diff --git a/package.json b/package.json index dd88a2dbf0..67c274ae77 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.17.1", - "pm2": "^5.3.0", + "pm2": "^5.3.1", "socket.io": "^4.7.4", "systeminformation": "^5.21.22" }, From 339aaf4c01e17e8da233f26c0443203553953c78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 19:04:32 +0100 Subject: [PATCH 021/418] Bump actions/dependency-review-action from 3 to 4 (#3366) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 3 to 4.
Release notes

Sourced from actions/dependency-review-action's releases.

v4.0.0

New Contributors

Full Changelog: https://github.com/actions/dependency-review-action/compare/v3.1.5...v4.0.0

3.1.5

What's Changed

Full Changelog: https://github.com/actions/dependency-review-action/compare/v3.1.4...v3.1.5

3.1.4

What's Changed

Full Changelog: https://github.com/actions/dependency-review-action/compare/v3...v3.1.4

3.1.3

What's Changed

Full Changelog: https://github.com/actions/dependency-review-action/compare/v3...v3.1.3

3.1.2

What's Changed

... (truncated)

Commits
  • 4cd9eb2 Updating docs to point to v4.
  • 4901385 bump to 4.0.0
  • dbf82a4 Merge pull request #639 from takost/takost/update-to-node-20
  • 78aeb2a Merge pull request #663 from actions/dependabot/npm_and_yarn/typescript-eslin...
  • 4e51000 Bump @​typescript-eslint/parser from 6.18.0 to 6.18.1
  • 9560737 Merge pull request #661 from actions/dependabot/npm_and_yarn/typescript-eslin...
  • 4125f47 Merge pull request #660 from actions/dependabot/npm_and_yarn/types/node-16.18.70
  • 07cc93e Bump @​typescript-eslint/eslint-plugin from 6.18.0 to 6.18.1
  • e2c203b Bump @​types/node from 16.18.62 to 16.18.70
  • f0b304d Merge pull request #653 from actions/dependabot/npm_and_yarn/got-14.0.0
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/dependency-review-action&package-manager=github_actions&previous-version=3&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/depsreview.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/depsreview.yaml b/.github/workflows/depsreview.yaml index 7d8866d89b..141e821b9c 100644 --- a/.github/workflows/depsreview.yaml +++ b/.github/workflows/depsreview.yaml @@ -15,4 +15,4 @@ jobs: - name: "Checkout code" uses: actions/checkout@v4 - name: "Dependency Review" - uses: actions/dependency-review-action@v3 + uses: actions/dependency-review-action@v4 From f88b92fb1fe1329dac159a05627b06e7874bad42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 20:54:29 +0100 Subject: [PATCH 022/418] Bump follow-redirects from 1.15.3 to 1.15.5 (#3367) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.3 to 1.15.5.
Commits
  • b1677ce Release version 1.15.5 of the npm package.
  • d8914f7 Preserve fragment in responseUrl.
  • 6585820 Release version 1.15.4 of the npm package.
  • 7a6567e Disallow bracketed hostnames.
  • 05629af Prefer native URL instead of deprecated url.parse.
  • 1cba8e8 Prefer native URL instead of legacy url.resolve.
  • 72bc2a4 Simplify _processResponse error handling.
  • 3d42aec Add bracket tests.
  • bcbb096 Do not directly set Error properties.
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.3&new-version=1.15.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/MagicMirrorOrg/MagicMirror/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From b0161fe0115acd0f2cfed4abde69120e260490ac Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 24 Jan 2024 20:43:59 +0100 Subject: [PATCH 023/418] Lint package.json files (#3368) Notable changes in this context: - simplification of the ESLint calls - there is no longer a combination of two file/directory lists (one in `package.json` and one in `.eslintignore`) - removal of a non-existent path from the `.eslintignore` - use shorthand declaration for GitHub repository Normally the new plugin would also sort the scripts in the package.json alphabetically, but I think the current order is fine, so I deactivated it. Is it overkill to introduce a linter plugin just for the `package.json` files? In other projects I have seen that such internal changes were marked with "chore" in the changelog. That's what I've done here. These chore changes are less interesting for "normal" users. Please feel free to give me feedback. --- .eslintignore | 3 +- .eslintrc.json | 9 +++ .prettierignore | 1 + CHANGELOG.md | 1 + fonts/package-lock.json | 2 + fonts/package.json | 8 +-- package-lock.json | 119 +++++++++++++++++++++++++++++++++++++++ package.json | 10 ++-- vendor/package-lock.json | 2 + vendor/package.json | 8 +-- 10 files changed, 146 insertions(+), 17 deletions(-) diff --git a/.eslintignore b/.eslintignore index fa7668825a..24f4f1f599 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,2 @@ -modules/default/calendar/vendor/* +modules/* +!modules/default/ \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 1eaa9b43df..dccd2ee2dc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -79,6 +79,15 @@ "rules": { "@stylistic/quotes": "off" } + }, + { + "extends": ["plugin:package-json/recommended"], + "files": ["package.json"], + "parser": "jsonc-eslint-parser", + "plugins": ["package-json"], + "rules": { + "package-json/sort-collections": ["error", ["devDependencies", "dependencies", "peerDependencies", "config"]] + } } ] } diff --git a/.prettierignore b/.prettierignore index 231245b1c1..dba12af8e1 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ *.js +.eslintignore .prettierignore /config /coverage diff --git a/CHANGELOG.md b/CHANGELOG.md index c0884bc48d..f1307cf6fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ _This release is scheduled to be released on 2024-04-01._ ### Added - Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 +- [chore] Add `eslint-plugin-package-json` to lint the `package.json` files ### Updated diff --git a/fonts/package-lock.json b/fonts/package-lock.json index d2b9f51074..fb2f9ebad3 100644 --- a/fonts/package-lock.json +++ b/fonts/package-lock.json @@ -1,10 +1,12 @@ { "name": "magicmirror-fonts", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror-fonts", + "version": "1.0.0", "license": "MIT", "dependencies": { "@fontsource/roboto": "^5.0.8", diff --git a/fonts/package.json b/fonts/package.json index 7dd6fd2516..3b5714d166 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -1,10 +1,8 @@ { "name": "magicmirror-fonts", - "description": "Package for fonts use by MagicMirror² Core.", - "repository": { - "type": "git", - "url": "git+https://github.com/MagicMirrorOrg/MagicMirror.git" - }, + "version": "1.0.0", + "description": "Package for fonts use by MagicMirror² core.", + "repository": "MagicMirrorOrg/MagicMirror", "license": "MIT", "bugs": { "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" diff --git a/package-lock.json b/package-lock.json index 09fe1f6e2e..23c0a30d7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.3", "eslint-plugin-jsdoc": "^48.0.2", + "eslint-plugin-package-json": "^0.10.0", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", @@ -2055,6 +2056,16 @@ "@types/node": "*" } }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -2115,6 +2126,12 @@ "@types/node": "*" } }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "node_modules/@types/node": { "version": "18.19.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.7.tgz", @@ -2973,6 +2990,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -3765,6 +3791,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -4570,6 +4605,25 @@ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-package-json": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.10.0.tgz", + "integrity": "sha512-vUEfGptdpaEw0DTzN8Yl4cjZ2XZosuzAbZ+kOKJN+tJRe2hZDogesMhNYT8FI26QZ1rYUnfQ0wwzBTjswGr04g==", + "dev": true, + "dependencies": { + "package-json-validator": "^0.6.3", + "semver": "^7.5.4", + "sort-package-json": "^1.57.0", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": ">=8.0.0", + "jsonc-eslint-parser": "^2.0.0" + } + }, "node_modules/eslint-plugin-unicorn": { "version": "50.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-50.0.1.tgz", @@ -6114,6 +6168,15 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -7027,6 +7090,25 @@ "node": ">=6" } }, + "node_modules/jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", + "dev": true, + "peer": true, + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -8075,6 +8157,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", + "dev": true, + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "node_modules/optimist/node_modules/minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==", + "dev": true + }, + "node_modules/optimist/node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -11082,6 +11189,18 @@ "spdx-license-ids": "^3.0.0" } }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dev": true, + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 67c274ae77..ccd735af16 100644 --- a/package.json +++ b/package.json @@ -18,20 +18,17 @@ "test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit", "test:unit": "NODE_ENV=test jest --selectProjects unit", "test:prettier": "prettier . --check", - "test:js": "eslint 'js/**/*.js' 'modules/default/**/*.js' 'clientonly/*.js' 'serveronly/*.js' 'translations/*.js' 'vendor/*.js' 'tests/**/*.js' 'config/*'", + "test:js": "eslint .", "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json", "test:calendar": "node ./modules/default/calendar/debug.js", "config:check": "node js/check_config.js", "lint:prettier": "prettier . --write", - "lint:js": "eslint 'js/**/*.js' 'modules/default/**/*.js' 'clientonly/*.js' 'serveronly/*.js' 'translations/*.js' 'vendor/*.js' 'tests/**/*.js' 'config/*' --fix", + "lint:js": "eslint . --fix", "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix", "lint:staged": "lint-staged", "prepare": "[ -f node_modules/.bin/husky ] && husky install || echo no husky installed." }, - "repository": { - "type": "git", - "url": "git+https://github.com/MagicMirrorOrg/MagicMirror.git" - }, + "repository": "MagicMirrorOrg/MagicMirror", "keywords": [ "magic mirror", "magicmirror", @@ -53,6 +50,7 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.3", "eslint-plugin-jsdoc": "^48.0.2", + "eslint-plugin-package-json": "^0.10.0", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", diff --git a/vendor/package-lock.json b/vendor/package-lock.json index c20e2d49bd..e5b2476e85 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -1,10 +1,12 @@ { "name": "magicmirror-vendors", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror-vendors", + "version": "1.0.0", "license": "MIT", "dependencies": { "@fortawesome/fontawesome-free": "^6.5.1", diff --git a/vendor/package.json b/vendor/package.json index 3d1ef83ec0..468321d6c2 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -1,10 +1,8 @@ { "name": "magicmirror-vendors", - "description": "Package for vendors use by MagicMirror² Core.", - "repository": { - "type": "git", - "url": "git+https://github.com/MagicMirrorOrg/MagicMirror.git" - }, + "version": "1.0.0", + "description": "Package for vendors use by MagicMirror² core.", + "repository": "MagicMirrorOrg/MagicMirror", "license": "MIT", "bugs": { "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" From 27f3c86c41007f9879f2f18b98fd86a8a14fdaab Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 24 Jan 2024 21:39:06 +0100 Subject: [PATCH 024/418] remove all useless header comments (#3363) see #3358 used command: `find ./ -type f -exec perl -i -0pe 's/\/\*\s*magicmirror.*?\*\/\s*//si' {} \;` This is a first draft, I think we should preserve some of the comments. --- CHANGELOG.md | 2 ++ config/config.js.sample | 5 +---- css/custom.css.sample | 8 +++----- js/animateCSS.js | 7 ------- js/app.js | 7 ------- js/check_config.js | 7 ------- js/defaults.js | 6 ------ js/deprecated.js | 8 -------- js/loader.js | 6 ------ js/logger.js | 10 +--------- js/main.js | 6 ------ js/module.js | 6 +----- js/node_helper.js | 6 ------ js/server.js | 6 ------ js/socketclient.js | 6 ------ js/translator.js | 6 ------ js/utils.js | 5 ----- modules/default/alert/alert.js | 6 ------ modules/default/calendar/calendar.js | 6 ------ modules/default/calendar/calendarfetcher.js | 7 ------- modules/default/calendar/calendarfetcherutils.js | 7 ------- modules/default/calendar/calendarutils.js | 6 ------ modules/default/calendar/debug.js | 3 --- modules/default/calendar/node_helper.js | 6 ------ modules/default/clock/clock.js | 6 ------ modules/default/compliments/compliments.js | 6 ------ modules/default/defaultmodules.js | 5 +---- modules/default/helloworld/helloworld.js | 6 ------ modules/default/newsfeed/newsfeed.js | 6 ------ modules/default/newsfeed/newsfeedfetcher.js | 7 ------- modules/default/newsfeed/node_helper.js | 7 ------- .../default/updatenotification/updatenotification.js | 6 ------ modules/default/weather/providers/envcanada.js | 8 +------- modules/default/weather/providers/openmeteo.js | 12 +++--------- modules/default/weather/providers/openweathermap.js | 9 ++------- modules/default/weather/providers/pirateweather.js | 11 ++--------- modules/default/weather/providers/smhi.js | 12 +++--------- modules/default/weather/providers/ukmetoffice.js | 9 ++------- .../default/weather/providers/ukmetofficedatahub.js | 9 +-------- modules/default/weather/providers/weatherbit.js | 11 ++--------- modules/default/weather/providers/weatherflow.js | 10 +--------- modules/default/weather/providers/weathergov.js | 7 +------ modules/default/weather/providers/yr.js | 10 +--------- modules/default/weather/weather.js | 6 ------ modules/default/weather/weatherobject.js | 12 ------------ modules/default/weather/weatherprovider.js | 9 +-------- modules/default/weather/weatherutils.js | 6 ------ tests/configs/default.js | 5 ----- tests/configs/empty_ipWhiteList.js | 5 ----- tests/configs/modules/alert/default.js | 5 ----- tests/configs/modules/calendar/auth-default.js | 5 ----- tests/configs/modules/calendar/bad_rrule.js | 5 ----- tests/configs/modules/calendar/basic-auth.js | 5 ----- tests/configs/modules/calendar/changed-port.js | 5 ----- tests/configs/modules/calendar/custom.js | 5 ----- tests/configs/modules/calendar/default.js | 5 ----- tests/configs/modules/calendar/exdate.js | 7 +------ tests/configs/modules/calendar/fail-basic-auth.js | 7 ------- tests/configs/modules/calendar/old-basic-auth.js | 5 ----- tests/configs/modules/calendar/recurring.js | 5 ----- .../modules/calendar/show-duplicates-in-calendar.js | 5 ----- tests/configs/modules/clock/clock_12hr.js | 5 ----- tests/configs/modules/clock/clock_24hr.js | 5 ----- tests/configs/modules/clock/clock_analog.js | 4 ---- .../modules/clock/clock_displaySeconds_false.js | 5 ----- tests/configs/modules/clock/clock_showDateAnalog.js | 5 ----- tests/configs/modules/clock/clock_showPeriodUpper.js | 5 ----- tests/configs/modules/clock/clock_showSunMoon.js | 5 ----- tests/configs/modules/clock/clock_showTime.js | 5 ----- tests/configs/modules/clock/clock_showWeek.js | 5 ----- tests/configs/modules/clock/es/clock_12hr.js | 5 ----- tests/configs/modules/clock/es/clock_24hr.js | 5 ----- .../modules/clock/es/clock_showPeriodUpper.js | 5 ----- tests/configs/modules/clock/es/clock_showWeek.js | 6 ------ .../modules/compliments/compliments_animateCSS.js | 6 ------ .../compliments_animateCSS_fallbackToDefault.js | 7 ------- .../compliments_animateCSS_invertedAnimationName.js | 6 ------ .../modules/compliments/compliments_anytime.js | 5 ----- .../configs/modules/compliments/compliments_date.js | 5 ----- .../modules/compliments/compliments_only_anytime.js | 5 ----- .../modules/compliments/compliments_parts_day.js | 5 ----- .../modules/compliments/compliments_remote.js | 5 ----- tests/configs/modules/display.js | 5 ----- tests/configs/modules/helloworld/helloworld.js | 5 ----- .../configs/modules/helloworld/helloworld_default.js | 5 ----- tests/configs/modules/newsfeed/default.js | 5 ----- tests/configs/modules/newsfeed/ignore_items.js | 4 ---- tests/configs/modules/newsfeed/incorrect_url.js | 4 ---- tests/configs/modules/newsfeed/prohibited_words.js | 4 ---- tests/configs/modules/positions.js | 5 ----- .../modules/weather/currentweather_compliments.js | 5 ----- .../modules/weather/currentweather_default.js | 5 ----- .../modules/weather/currentweather_options.js | 5 ----- .../configs/modules/weather/currentweather_units.js | 5 ----- .../modules/weather/forecastweather_absolute.js | 5 ----- .../modules/weather/forecastweather_default.js | 5 ----- .../modules/weather/forecastweather_options.js | 5 ----- .../configs/modules/weather/forecastweather_units.js | 5 ----- .../configs/modules/weather/hourlyweather_default.js | 5 ----- .../configs/modules/weather/hourlyweather_options.js | 5 ----- .../weather/hourlyweather_showPrecipitation.js | 5 ----- tests/configs/noIpWhiteList.js | 5 ----- tests/configs/port_8090.js | 5 ----- tests/configs/port_variable.js.template | 5 ----- tests/configs/without_modules.js | 5 ----- tests/e2e/animateCSS_spec.js | 7 ------- translations/translations.js | 7 ------- vendor/vendor.js | 6 ------ 108 files changed, 30 insertions(+), 623 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1307cf6fe..86a024297a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Deleted +- Unneeded file headers (#3358) + ## [2.26.0] - 01-01-2024 Thanks to: @bnitkin, @bugsounet, @dependabot, @jkriegshauser, @kaennchenstruggle, @KristjanESPERANTO and @Ybbet. diff --git a/config/config.js.sample b/config/config.js.sample index 06ff3a5d93..688f627286 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -1,7 +1,4 @@ -/* MagicMirror² Config Sample - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. +/* Config Sample * * For more information on how you can configure this file * see https://docs.magicmirror.builders/configuration/introduction.html diff --git a/css/custom.css.sample b/css/custom.css.sample index 48cc17a0af..29590206a7 100644 --- a/css/custom.css.sample +++ b/css/custom.css.sample @@ -1,10 +1,8 @@ -/* MagicMirror² Custom CSS Sample +/* Custom CSS Sample * * Change color and fonts here. * * Beware that properties cannot be unitless, so for example write '--gap-body: 0px;' instead of just '--gap-body: 0;' - * - * MIT Licensed. */ /* Uncomment and adjust accordingly if you want to import another font from the google-fonts-api: */ @@ -18,7 +16,7 @@ --font-primary: "Roboto Condensed"; --font-secondary: "Roboto"; - + --font-size: 20px; --font-size-small: 0.75rem; @@ -26,6 +24,6 @@ --gap-body-right: 60px; --gap-body-bottom: 60px; --gap-body-left: 60px; - + --gap-modules: 30px; } diff --git a/js/animateCSS.js b/js/animateCSS.js index b4db77b9ab..057d53c72d 100644 --- a/js/animateCSS.js +++ b/js/animateCSS.js @@ -1,10 +1,3 @@ -/* MagicMirror² - * AnimateCSS System from https://animate.style/ - * by @bugsounet - * for Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ - /* enumeration of animations in Array **/ const AnimateCSSIn = [ // Attention seekers diff --git a/js/app.js b/js/app.js index 05212f2e11..ec8f42f3dd 100644 --- a/js/app.js +++ b/js/app.js @@ -1,10 +1,3 @@ -/* MagicMirror² - * The Core App (Server) - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ - // Alias modules mentioned in package.js under _moduleAliases. require("module-alias/register"); diff --git a/js/check_config.js b/js/check_config.js index d190f22a75..ec5ebcae66 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -1,10 +1,3 @@ -/* MagicMirror² - * - * Check the configuration file for errors - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ const path = require("node:path"); const fs = require("node:fs"); const colors = require("ansis"); diff --git a/js/defaults.js b/js/defaults.js index ce49bf5bee..c4efa77e95 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -1,11 +1,5 @@ /* global mmPort */ -/* MagicMirror² - * Config Defaults - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ const address = "localhost"; let port = 8080; if (typeof mmPort !== "undefined") { diff --git a/js/deprecated.js b/js/deprecated.js index e2c70322ac..b0aca56ca0 100644 --- a/js/deprecated.js +++ b/js/deprecated.js @@ -1,11 +1,3 @@ -/* MagicMirror² Deprecated Config Options List - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - * - * Olex S. original idea this deprecated option - */ - module.exports = { configs: ["kioskmode"] }; diff --git a/js/loader.js b/js/loader.js index b4b32f4f3c..0d59858c77 100644 --- a/js/loader.js +++ b/js/loader.js @@ -1,11 +1,5 @@ /* global defaultModules, vendor */ -/* MagicMirror² - * Module and File loaders. - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ const Loader = (function () { /* Create helper variables */ diff --git a/js/logger.js b/js/logger.js index da295bb990..0c254082c4 100644 --- a/js/logger.js +++ b/js/logger.js @@ -1,12 +1,4 @@ -/* MagicMirror² - * Log - * - * This logger is very simple, but needs to be extended. - * This system can eventually be used to push the log messages to an external target. - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ +// This logger is very simple, but needs to be extended. (function (root, factory) { if (typeof exports === "object") { if (process.env.JEST_WORKER_ID === undefined) { diff --git a/js/main.js b/js/main.js index 7bda7ababa..43ec02ad87 100644 --- a/js/main.js +++ b/js/main.js @@ -1,11 +1,5 @@ /* global Loader, defaults, Translator, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut */ -/* MagicMirror² - * Main System - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ const MM = (function () { let modules = []; diff --git a/js/module.js b/js/module.js index d9d40ac50b..71451763d0 100644 --- a/js/module.js +++ b/js/module.js @@ -1,11 +1,7 @@ /* global Class, cloneObject, Loader, MMSocket, nunjucks, Translator */ -/* MagicMirror² - * Module Blueprint. +/* Module Blueprint. * @typedef {Object} Module - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. */ const Module = Class.extend({ diff --git a/js/node_helper.js b/js/node_helper.js index dee0beeb3a..42da0efcff 100644 --- a/js/node_helper.js +++ b/js/node_helper.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Node Helper Superclass - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ const express = require("express"); const Log = require("logger"); const Class = require("./class"); diff --git a/js/server.js b/js/server.js index 03de57ebef..bfa0f911d7 100644 --- a/js/server.js +++ b/js/server.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Server - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ const fs = require("node:fs"); const http = require("node:http"); const https = require("node:https"); diff --git a/js/socketclient.js b/js/socketclient.js index a8d2e4b592..d8408e9e93 100644 --- a/js/socketclient.js +++ b/js/socketclient.js @@ -1,11 +1,5 @@ /* global io */ -/* MagicMirror² - * TODO add description - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ 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 d329ffd076..e742eb9c3b 100644 --- a/js/translator.js +++ b/js/translator.js @@ -1,11 +1,5 @@ /* global translations */ -/* MagicMirror² - * Translator (l10n) - * - * By Christopher Fenner https://github.com/CFenner - * MIT Licensed. - */ const Translator = (function () { /** diff --git a/js/utils.js b/js/utils.js index 395feceff9..ba80004bb3 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,8 +1,3 @@ -/* MagicMirror² - * Utils - * - * MIT Licensed. - */ const execSync = require("node:child_process").execSync; const Log = require("logger"); const si = require("systeminformation"); diff --git a/modules/default/alert/alert.js b/modules/default/alert/alert.js index da26292372..a436a74c7b 100644 --- a/modules/default/alert/alert.js +++ b/modules/default/alert/alert.js @@ -1,11 +1,5 @@ /* global NotificationFx */ -/* MagicMirror² - * Module: alert - * - * By Paul-Vincent Roll https://paulvincentroll.com/ - * MIT Licensed. - */ Module.register("alert", { alerts: {}, diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index bfb49af78e..fe08a883af 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -1,11 +1,5 @@ /* global CalendarUtils */ -/* MagicMirror² - * Module: Calendar - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ Module.register("calendar", { // Define module defaults defaults: { diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 2ba4e12ea6..824c7c5b4f 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -1,10 +1,3 @@ -/* MagicMirror² - * Node Helper: Calendar - CalendarFetcher - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ - const https = require("node:https"); const ical = require("node-ical"); const Log = require("logger"); diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index 7a0b8b4053..c2067296cd 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -1,10 +1,3 @@ -/* MagicMirror² - * Calendar Fetcher Util Methods - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ - /** * @external Moment */ diff --git a/modules/default/calendar/calendarutils.js b/modules/default/calendar/calendarutils.js index 68aef52154..5cbc8d6824 100644 --- a/modules/default/calendar/calendarutils.js +++ b/modules/default/calendar/calendarutils.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Calendar Util Methods - * - * By Rejas - * MIT Licensed. - */ const CalendarUtils = { /** diff --git a/modules/default/calendar/debug.js b/modules/default/calendar/debug.js index 5e19e13134..71ed2f4abd 100644 --- a/modules/default/calendar/debug.js +++ b/modules/default/calendar/debug.js @@ -1,9 +1,6 @@ /* CalendarFetcher Tester * use this script with `node debug.js` to test the fetcher without the need * of starting the MagicMirror² core. Adjust the values below to your desire. - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. */ // Alias modules mentioned in package.js under _moduleAliases. require("module-alias/register"); diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js index c0d46ae468..e485926099 100644 --- a/modules/default/calendar/node_helper.js +++ b/modules/default/calendar/node_helper.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Node Helper: Calendar - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ const NodeHelper = require("node_helper"); const Log = require("logger"); const CalendarFetcher = require("./calendarfetcher"); diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 549026eaef..3796a2c359 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -1,11 +1,5 @@ /* global SunCalc, formatTime */ -/* MagicMirror² - * Module: Clock - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ Module.register("clock", { // Module config defaults. defaults: { diff --git a/modules/default/compliments/compliments.js b/modules/default/compliments/compliments.js index 374cd54f76..10e54afd40 100644 --- a/modules/default/compliments/compliments.js +++ b/modules/default/compliments/compliments.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Module: Compliments - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ Module.register("compliments", { // Module config defaults. defaults: { diff --git a/modules/default/defaultmodules.js b/modules/default/defaultmodules.js index c74e94a45c..e28413ff7b 100644 --- a/modules/default/defaultmodules.js +++ b/modules/default/defaultmodules.js @@ -1,8 +1,5 @@ -/* MagicMirror² Default Modules List +/* Default Modules List * Modules listed below can be loaded without the 'default/' prefix. Omitting the default folder name. - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. */ const defaultModules = ["alert", "calendar", "clock", "compliments", "helloworld", "newsfeed", "updatenotification", "weather"]; diff --git a/modules/default/helloworld/helloworld.js b/modules/default/helloworld/helloworld.js index 6adb382e07..53fbd80c03 100644 --- a/modules/default/helloworld/helloworld.js +++ b/modules/default/helloworld/helloworld.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Module: HelloWorld - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ Module.register("helloworld", { // Default module config. defaults: { diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 329c04bb33..c66f8990d8 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Module: NewsFeed - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ Module.register("newsfeed", { // Default module config. defaults: { diff --git a/modules/default/newsfeed/newsfeedfetcher.js b/modules/default/newsfeed/newsfeedfetcher.js index ea1c7712fd..ea181b60b4 100644 --- a/modules/default/newsfeed/newsfeedfetcher.js +++ b/modules/default/newsfeed/newsfeedfetcher.js @@ -1,10 +1,3 @@ -/* MagicMirror² - * Node Helper: Newsfeed - NewsfeedFetcher - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ - const crypto = require("node:crypto"); const stream = require("node:stream"); const FeedMe = require("feedme"); diff --git a/modules/default/newsfeed/node_helper.js b/modules/default/newsfeed/node_helper.js index 2110fde406..c8cdaa0c37 100644 --- a/modules/default/newsfeed/node_helper.js +++ b/modules/default/newsfeed/node_helper.js @@ -1,10 +1,3 @@ -/* MagicMirror² - * Node Helper: Newsfeed - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ - const NodeHelper = require("node_helper"); const Log = require("logger"); const NewsfeedFetcher = require("./newsfeedfetcher"); diff --git a/modules/default/updatenotification/updatenotification.js b/modules/default/updatenotification/updatenotification.js index 3973c35961..a18bc4db0e 100644 --- a/modules/default/updatenotification/updatenotification.js +++ b/modules/default/updatenotification/updatenotification.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Module: UpdateNotification - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ Module.register("updatenotification", { defaults: { updateInterval: 10 * 60 * 1000, // every 10 minutes diff --git a/modules/default/weather/providers/envcanada.js b/modules/default/weather/providers/envcanada.js index 934c5831d4..7372e17689 100644 --- a/modules/default/weather/providers/envcanada.js +++ b/modules/default/weather/providers/envcanada.js @@ -1,10 +1,6 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* MagicMirror² - * Module: Weather - * Provider: Environment Canada (EC) - * - * This class is a provider for Environment Canada MSC Datamart +/* This class is a provider for Environment Canada MSC Datamart * Note that this is only for Canadian locations and does not require an API key (access is anonymous) * * EC Documentation at following links: @@ -27,8 +23,6 @@ * with locations you can search under column B (English Names), with the corresponding siteCode under * column A (Codes) and provCode under column C (Province). * - * Original by Kevin Godin - * * License to use Environment Canada (EC) data is detailed here: * https://eccc-msc.github.io/open-data/licence/readme_en/ * diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index b80601a12e..5c4b232200 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -1,15 +1,9 @@ /* global WeatherProvider, WeatherObject */ -/* MagicMirror² - * Module: Weather - * Provider: Open-Meteo - * - * By Andrés Vanegas - * MIT Licensed - * - * This class is a provider for Open-Meteo, based on Andrew Pometti's class - * for Weatherbit. +/* This class is a provider for Open-Meteo, + * see https://open-meteo.com/ */ + // https://www.bigdatacloud.com/docs/api/free-reverse-geocode-to-city-api const GEOCODE_BASE = "https://api.bigdatacloud.net/data/reverse-geocode-client"; const OPEN_METEO_BASE = "https://api.open-meteo.com/v1"; diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index c389b7fd97..0999c83f0a 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -1,12 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* MagicMirror² - * Module: Weather - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - * - * This class is the blueprint for a weather provider. +/* This class is a provider for Openweathermap, + * see https://openweathermap.org/ */ WeatherProvider.register("openweathermap", { // Set the name of the provider. diff --git a/modules/default/weather/providers/pirateweather.js b/modules/default/weather/providers/pirateweather.js index 46106cfc3e..dd20ccf47d 100644 --- a/modules/default/weather/providers/pirateweather.js +++ b/modules/default/weather/providers/pirateweather.js @@ -1,14 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* MagicMirror² - * Module: Weather - * Provider: Pirate Weather - * - * Written by Nicholas Hubbard https://github.com/nhubbard for formerly Dark Sky Provider - * Modified by Karsten Hassel for Pirate Weather - * MIT Licensed - * - * This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api). +/* This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api), + * see http://pirateweather.net/en/latest/ */ WeatherProvider.register("pirateweather", { // Set the name of the provider. diff --git a/modules/default/weather/providers/smhi.js b/modules/default/weather/providers/smhi.js index d1641b4214..d7dcdf1b6f 100644 --- a/modules/default/weather/providers/smhi.js +++ b/modules/default/weather/providers/smhi.js @@ -1,14 +1,8 @@ /* global WeatherProvider, WeatherObject */ -/* MagicMirror² - * Module: Weather - * Provider: SMHI - * - * By BuXXi https://github.com/buxxi - * MIT Licensed - * - * This class is a provider for SMHI (Sweden only). Metric system is the only - * supported unit. +/* This class is a provider for SMHI (Sweden only). + * Metric system is the only supported unit, + * see https://www.smhi.se/ */ WeatherProvider.register("smhi", { providerName: "SMHI", diff --git a/modules/default/weather/providers/ukmetoffice.js b/modules/default/weather/providers/ukmetoffice.js index e4e020b371..c2db4cda37 100644 --- a/modules/default/weather/providers/ukmetoffice.js +++ b/modules/default/weather/providers/ukmetoffice.js @@ -1,12 +1,7 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* MagicMirror² - * Module: Weather - * - * By Malcolm Oakes https://github.com/maloakes - * MIT Licensed. - * - * This class is a provider for UK Met Office Datapoint. +/* This class is a provider for UK Met Office Datapoint, + * see https://www.metoffice.gov.uk/ */ WeatherProvider.register("ukmetoffice", { // Set the name of the provider. diff --git a/modules/default/weather/providers/ukmetofficedatahub.js b/modules/default/weather/providers/ukmetofficedatahub.js index 225e7b4660..1ca4da5c01 100644 --- a/modules/default/weather/providers/ukmetofficedatahub.js +++ b/modules/default/weather/providers/ukmetofficedatahub.js @@ -1,13 +1,6 @@ /* global WeatherProvider, WeatherObject */ -/* MagicMirror² - * Module: Weather - * - * By Malcolm Oakes https://github.com/maloakes - * Existing Met Office provider edited for new MetOffice Data Hub by CreepinJesus http://github.com/XBCreepinJesus - * MIT Licensed. - * - * This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services). +/* This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services). * For more information on Data Hub, see https://www.metoffice.gov.uk/services/data/datapoint/notifications/weather-datahub * Data available: * Hourly data for next 2 days ("hourly") - https://www.metoffice.gov.uk/binaries/content/assets/metofficegovuk/pdf/data/global-spot-data-hourly.pdf diff --git a/modules/default/weather/providers/weatherbit.js b/modules/default/weather/providers/weatherbit.js index 5bde8003bb..7c01f5d6be 100644 --- a/modules/default/weather/providers/weatherbit.js +++ b/modules/default/weather/providers/weatherbit.js @@ -1,14 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* MagicMirror² - * Module: Weather - * Provider: Weatherbit - * - * By Andrew Pometti - * MIT Licensed - * - * This class is a provider for Weatherbit, based on Nicholas Hubbard's class - * for Dark Sky & Vince Peri's class for Weather.gov. +/* This class is a provider for Weatherbit, + * see https://www.weatherbit.io/ */ WeatherProvider.register("weatherbit", { // Set the name of the provider. diff --git a/modules/default/weather/providers/weatherflow.js b/modules/default/weather/providers/weatherflow.js index 9e15be82d8..54066d7b40 100644 --- a/modules/default/weather/providers/weatherflow.js +++ b/modules/default/weather/providers/weatherflow.js @@ -1,16 +1,8 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* MagicMirror² - * Module: Weather - * Provider: Weatherflow - * - * By Tobias Dreyem https://github.com/10bias - * MIT Licensed - * - * This class is a provider for Weatherflow. +/* This class is a provider for Weatherflow. * Note that the Weatherflow API does not provide snowfall. */ - WeatherProvider.register("weatherflow", { // Set the name of the provider. // Not strictly required, but helps for debugging diff --git a/modules/default/weather/providers/weathergov.js b/modules/default/weather/providers/weathergov.js index f66101468b..661f36af59 100644 --- a/modules/default/weather/providers/weathergov.js +++ b/modules/default/weather/providers/weathergov.js @@ -1,13 +1,8 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* MagicMirror² - * Module: Weather - * Provider: weather.gov +/* Provider: weather.gov * https://weather-gov.github.io/api/general-faqs * - * Original by Vince Peri - * MIT Licensed. - * * This class is a provider for weather.gov. * Note that this is only for US locations (lat and lon) and does not require an API key * Since it is free, there are some items missing - like sunrise, sunset diff --git a/modules/default/weather/providers/yr.js b/modules/default/weather/providers/yr.js index 0c6701bfab..35493a1653 100644 --- a/modules/default/weather/providers/yr.js +++ b/modules/default/weather/providers/yr.js @@ -1,14 +1,6 @@ /* global WeatherProvider, WeatherObject */ -/* MagicMirror² - * Module: Weather - * Provider: Yr.no - * - * By Magnus Marthinsen - * MIT Licensed - * - * This class is a provider for Yr.no, a norwegian weather service. - * +/* This class is a provider for Yr.no, a norwegian weather service. * Terms of service: https://developer.yr.no/doc/TermsOfService/ */ WeatherProvider.register("yr", { diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index 15e6cfc51b..f4149652df 100644 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -1,11 +1,5 @@ /* global WeatherProvider, WeatherUtils, formatTime */ -/* MagicMirror² - * Module: Weather - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ Module.register("weather", { // Default module config. defaults: { diff --git a/modules/default/weather/weatherobject.js b/modules/default/weather/weatherobject.js index 33c9e669bf..5d6801ce13 100644 --- a/modules/default/weather/weatherobject.js +++ b/modules/default/weather/weatherobject.js @@ -1,17 +1,5 @@ /* global SunCalc, WeatherUtils */ -/* MagicMirror² - * Module: Weather - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - * - * This class is the blueprint for a day which includes weather information. - * - * Currently this is focused on the information which is necessary for the current weather. - * As soon as we start implementing the forecast, mode properties will be added. - */ - /** * @external Moment */ diff --git a/modules/default/weather/weatherprovider.js b/modules/default/weather/weatherprovider.js index b85e1a9924..3646441094 100644 --- a/modules/default/weather/weatherprovider.js +++ b/modules/default/weather/weatherprovider.js @@ -1,13 +1,6 @@ /* global Class, performWebRequest, OverrideWrapper */ -/* MagicMirror² - * Module: Weather - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - * - * This class is the blueprint for a weather provider. - */ +// This class is the blueprint for a weather provider. const WeatherProvider = Class.extend({ // Weather Provider Properties providerName: null, diff --git a/modules/default/weather/weatherutils.js b/modules/default/weather/weatherutils.js index e0c5709e0f..e75baf20f7 100644 --- a/modules/default/weather/weatherutils.js +++ b/modules/default/weather/weatherutils.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Weather Util Methods - * - * By Rejas - * MIT Licensed. - */ const WeatherUtils = { /** diff --git a/tests/configs/default.js b/tests/configs/default.js index 509dfd9860..ba6652068c 100644 --- a/tests/configs/default.js +++ b/tests/configs/default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test default config for modules - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ exports.configFactory = (options) => { return Object.assign( { diff --git a/tests/configs/empty_ipWhiteList.js b/tests/configs/empty_ipWhiteList.js index 5288112d08..8fdfc0e42d 100644 --- a/tests/configs/empty_ipWhiteList.js +++ b/tests/configs/empty_ipWhiteList.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config sample ipWhitelist - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = require(`${process.cwd()}/tests/configs/default.js`).configFactory({ ipWhitelist: [], port: 8282 diff --git a/tests/configs/modules/alert/default.js b/tests/configs/modules/alert/default.js index 45ffefe5b2..ea77b574be 100644 --- a/tests/configs/modules/alert/default.js +++ b/tests/configs/modules/alert/default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config sample module alert - * - * By rejas - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/calendar/auth-default.js b/tests/configs/modules/calendar/auth-default.js index 0b2491612f..99ce3922b0 100644 --- a/tests/configs/modules/calendar/auth-default.js +++ b/tests/configs/modules/calendar/auth-default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default calendar with auth by default - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/calendar/bad_rrule.js b/tests/configs/modules/calendar/bad_rrule.js index 5a89b5e616..3810794384 100644 --- a/tests/configs/modules/calendar/bad_rrule.js +++ b/tests/configs/modules/calendar/bad_rrule.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test ics with out of date event causing bad return from rrule.between - * - * By Sam Detweiler - * MIT Licensed. - */ let config = { timeFormat: 12, logLevel: ["INFO", "LOG", "WARN", "ERROR", "DEBUG"], diff --git a/tests/configs/modules/calendar/basic-auth.js b/tests/configs/modules/calendar/basic-auth.js index 5cbebceb2f..f322f573d7 100644 --- a/tests/configs/modules/calendar/basic-auth.js +++ b/tests/configs/modules/calendar/basic-auth.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default calendar - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/calendar/changed-port.js b/tests/configs/modules/calendar/changed-port.js index 5027726115..15bf920739 100644 --- a/tests/configs/modules/calendar/changed-port.js +++ b/tests/configs/modules/calendar/changed-port.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default calendar with auth by default - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/calendar/custom.js b/tests/configs/modules/calendar/custom.js index 4153da0460..4c6deb7838 100644 --- a/tests/configs/modules/calendar/custom.js +++ b/tests/configs/modules/calendar/custom.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config custom calendar - * - * By Rejas - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/calendar/default.js b/tests/configs/modules/calendar/default.js index 2dee121203..67c943d3c9 100644 --- a/tests/configs/modules/calendar/default.js +++ b/tests/configs/modules/calendar/default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default calendar - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/calendar/exdate.js b/tests/configs/modules/calendar/exdate.js index 574b24fef8..bb52561aa0 100644 --- a/tests/configs/modules/calendar/exdate.js +++ b/tests/configs/modules/calendar/exdate.js @@ -1,9 +1,4 @@ -/* MagicMirror² Test calendar exdate - * - * By jkriegshauser - * MIT Licensed. - * - * NOTE: calendar_test_exdate.ics has exdate entries for the next 20 years, but without some +/* NOTE: calendar_test_exdate.ics has exdate entries for the next 20 years, but without some * way to set a debug date for tests, this test may become flaky on specific days (i.e. could * not test easily on leap-years, the BYDAY specified in exdate, etc.) or when the 20 years * elapses if this project is still in active development ;) diff --git a/tests/configs/modules/calendar/fail-basic-auth.js b/tests/configs/modules/calendar/fail-basic-auth.js index e0b3ff15ae..2a58d623d6 100644 --- a/tests/configs/modules/calendar/fail-basic-auth.js +++ b/tests/configs/modules/calendar/fail-basic-auth.js @@ -1,10 +1,3 @@ -/* MagicMirror² Test calendar calendar - * - * This configuration is a wrong authentication - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/calendar/old-basic-auth.js b/tests/configs/modules/calendar/old-basic-auth.js index 01805e5c8c..08dc407316 100644 --- a/tests/configs/modules/calendar/old-basic-auth.js +++ b/tests/configs/modules/calendar/old-basic-auth.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default calendar - * with authentication old config - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/calendar/recurring.js b/tests/configs/modules/calendar/recurring.js index d05cce6c9b..fe1d36629e 100644 --- a/tests/configs/modules/calendar/recurring.js +++ b/tests/configs/modules/calendar/recurring.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config custom calendar - * - * By Rejas - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/calendar/show-duplicates-in-calendar.js b/tests/configs/modules/calendar/show-duplicates-in-calendar.js index 89fb8eb93e..c4a1c95811 100644 --- a/tests/configs/modules/calendar/show-duplicates-in-calendar.js +++ b/tests/configs/modules/calendar/show-duplicates-in-calendar.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for multiple calendar events having the same name and start date/time - * - * By Paranoid93 https://github.com/Paranoid93/ - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/clock/clock_12hr.js b/tests/configs/modules/clock/clock_12hr.js index 18170e7c9c..4a7318f58d 100644 --- a/tests/configs/modules/clock/clock_12hr.js +++ b/tests/configs/modules/clock/clock_12hr.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Sergey Morozov - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/clock/clock_24hr.js b/tests/configs/modules/clock/clock_24hr.js index f9bd451436..f75287eb04 100644 --- a/tests/configs/modules/clock/clock_24hr.js +++ b/tests/configs/modules/clock/clock_24hr.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Sergey Morozov - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/clock/clock_analog.js b/tests/configs/modules/clock/clock_analog.js index d303c3f995..98331ee389 100644 --- a/tests/configs/modules/clock/clock_analog.js +++ b/tests/configs/modules/clock/clock_analog.js @@ -1,7 +1,3 @@ -/* MagicMirror² Test config for analog clock face - * - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/clock/clock_displaySeconds_false.js b/tests/configs/modules/clock/clock_displaySeconds_false.js index cf33332090..181e8c6085 100644 --- a/tests/configs/modules/clock/clock_displaySeconds_false.js +++ b/tests/configs/modules/clock/clock_displaySeconds_false.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/clock/clock_showDateAnalog.js b/tests/configs/modules/clock/clock_showDateAnalog.js index e5f5c49b7d..772261c187 100644 --- a/tests/configs/modules/clock/clock_showDateAnalog.js +++ b/tests/configs/modules/clock/clock_showDateAnalog.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Johan Hammar - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/clock/clock_showPeriodUpper.js b/tests/configs/modules/clock/clock_showPeriodUpper.js index 3dd8b5c52f..78a1f315ef 100644 --- a/tests/configs/modules/clock/clock_showPeriodUpper.js +++ b/tests/configs/modules/clock/clock_showPeriodUpper.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Sergey Morozov - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/clock/clock_showSunMoon.js b/tests/configs/modules/clock/clock_showSunMoon.js index 025e054d1d..c5766aa255 100644 --- a/tests/configs/modules/clock/clock_showSunMoon.js +++ b/tests/configs/modules/clock/clock_showSunMoon.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Johan Hammar - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/clock/clock_showTime.js b/tests/configs/modules/clock/clock_showTime.js index 17ea4590d1..5e68951e2f 100644 --- a/tests/configs/modules/clock/clock_showTime.js +++ b/tests/configs/modules/clock/clock_showTime.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Johan Hammar - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/clock/clock_showWeek.js b/tests/configs/modules/clock/clock_showWeek.js index 71377e0bc5..7af4740655 100644 --- a/tests/configs/modules/clock/clock_showWeek.js +++ b/tests/configs/modules/clock/clock_showWeek.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Johan Hammar - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/clock/es/clock_12hr.js b/tests/configs/modules/clock/es/clock_12hr.js index 44444c06e4..66d380f8bf 100644 --- a/tests/configs/modules/clock/es/clock_12hr.js +++ b/tests/configs/modules/clock/es/clock_12hr.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { language: "es", timeFormat: 12, diff --git a/tests/configs/modules/clock/es/clock_24hr.js b/tests/configs/modules/clock/es/clock_24hr.js index 66b5304d17..752c5fd054 100644 --- a/tests/configs/modules/clock/es/clock_24hr.js +++ b/tests/configs/modules/clock/es/clock_24hr.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { language: "es", diff --git a/tests/configs/modules/clock/es/clock_showPeriodUpper.js b/tests/configs/modules/clock/es/clock_showPeriodUpper.js index 5e1fbb4be2..76f5fd0433 100644 --- a/tests/configs/modules/clock/es/clock_showPeriodUpper.js +++ b/tests/configs/modules/clock/es/clock_showPeriodUpper.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default clock module - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { language: "es", timeFormat: 12, diff --git a/tests/configs/modules/clock/es/clock_showWeek.js b/tests/configs/modules/clock/es/clock_showWeek.js index 73635c0ec0..c43eccdaef 100644 --- a/tests/configs/modules/clock/es/clock_showWeek.js +++ b/tests/configs/modules/clock/es/clock_showWeek.js @@ -1,9 +1,3 @@ -/* MagicMirror² Test config for default clock module - * Language es for showWeek feature - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { language: "es", timeFormat: 12, diff --git a/tests/configs/modules/compliments/compliments_animateCSS.js b/tests/configs/modules/compliments/compliments_animateCSS.js index 24e2736073..1e3d3d2f9d 100644 --- a/tests/configs/modules/compliments/compliments_animateCSS.js +++ b/tests/configs/modules/compliments/compliments_animateCSS.js @@ -1,9 +1,3 @@ -/* MagicMirror² Test config sample for AnimateCSS integration with compliments module - * - * By bugsounet https://github.com/bugsounet - * 09/2023 - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js b/tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js index 89c0694466..48f41cbfeb 100644 --- a/tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js +++ b/tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js @@ -1,10 +1,3 @@ -/* MagicMirror² Test config sample for AnimateCSS integration with compliments module - * --> if animation name is not an AnimateCSS animation - * --> must fallback to default (no animation) - * By bugsounet https://github.com/bugsounet - * 09/2023 - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js b/tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js index eb4af0ca1b..310210bfc1 100644 --- a/tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js +++ b/tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js @@ -1,9 +1,3 @@ -/* MagicMirror² Test config sample for AnimateCSS integration with compliments module - * --> inversed name animation : in for out and vice versa (must return no animation) - * By bugsounet https://github.com/bugsounet - * 09/2023 - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/compliments/compliments_anytime.js b/tests/configs/modules/compliments/compliments_anytime.js index 89253d9140..102b59ca8e 100644 --- a/tests/configs/modules/compliments/compliments_anytime.js +++ b/tests/configs/modules/compliments/compliments_anytime.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config compliments with anytime type - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/compliments/compliments_date.js b/tests/configs/modules/compliments/compliments_date.js index 2d9018b1d6..f1822f6a1c 100644 --- a/tests/configs/modules/compliments/compliments_date.js +++ b/tests/configs/modules/compliments/compliments_date.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config compliments with date type - * - * By Rejas - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/compliments/compliments_only_anytime.js b/tests/configs/modules/compliments/compliments_only_anytime.js index f1da683a94..8714bebd7e 100644 --- a/tests/configs/modules/compliments/compliments_only_anytime.js +++ b/tests/configs/modules/compliments/compliments_only_anytime.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config compliments with anytime type - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/compliments/compliments_parts_day.js b/tests/configs/modules/compliments/compliments_parts_day.js index ff34803a5b..f5a2bb7f42 100644 --- a/tests/configs/modules/compliments/compliments_parts_day.js +++ b/tests/configs/modules/compliments/compliments_parts_day.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for default compliments - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/compliments/compliments_remote.js b/tests/configs/modules/compliments/compliments_remote.js index 4658929682..5d8543e1c8 100644 --- a/tests/configs/modules/compliments/compliments_remote.js +++ b/tests/configs/modules/compliments/compliments_remote.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config compliments with remote file - * - * By Rejas - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/display.js b/tests/configs/modules/display.js index a416607743..c66e586a7b 100644 --- a/tests/configs/modules/display.js +++ b/tests/configs/modules/display.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for display setters module using the helloworld module - * - * By Rejas - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/helloworld/helloworld.js b/tests/configs/modules/helloworld/helloworld.js index 7225662127..d9aa0cb442 100644 --- a/tests/configs/modules/helloworld/helloworld.js +++ b/tests/configs/modules/helloworld/helloworld.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config sample module hello world - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/helloworld/helloworld_default.js b/tests/configs/modules/helloworld/helloworld_default.js index 06e6fe8dda..b0b35c7e48 100644 --- a/tests/configs/modules/helloworld/helloworld_default.js +++ b/tests/configs/modules/helloworld/helloworld_default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config sample module hello world default config - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/newsfeed/default.js b/tests/configs/modules/newsfeed/default.js index 34a7587fb0..0023c4c386 100644 --- a/tests/configs/modules/newsfeed/default.js +++ b/tests/configs/modules/newsfeed/default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config newsfeed module - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/newsfeed/ignore_items.js b/tests/configs/modules/newsfeed/ignore_items.js index fd104ba414..425ef78398 100644 --- a/tests/configs/modules/newsfeed/ignore_items.js +++ b/tests/configs/modules/newsfeed/ignore_items.js @@ -1,7 +1,3 @@ -/* MagicMirror² Test config newsfeed module - * - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/newsfeed/incorrect_url.js b/tests/configs/modules/newsfeed/incorrect_url.js index f9d75b09a3..565da18997 100644 --- a/tests/configs/modules/newsfeed/incorrect_url.js +++ b/tests/configs/modules/newsfeed/incorrect_url.js @@ -1,7 +1,3 @@ -/* MagicMirror² Test config newsfeed module - * - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/newsfeed/prohibited_words.js b/tests/configs/modules/newsfeed/prohibited_words.js index 4ff6aec0fa..143fcf903c 100644 --- a/tests/configs/modules/newsfeed/prohibited_words.js +++ b/tests/configs/modules/newsfeed/prohibited_words.js @@ -1,7 +1,3 @@ -/* MagicMirror² Test config newsfeed module - * - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/positions.js b/tests/configs/modules/positions.js index a40bfab959..e9e0d07a76 100644 --- a/tests/configs/modules/positions.js +++ b/tests/configs/modules/positions.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config for position setters module using the helloworld module - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { modules: // Using exotic content. This is why don't accept go to JSON configuration file diff --git a/tests/configs/modules/weather/currentweather_compliments.js b/tests/configs/modules/weather/currentweather_compliments.js index 4af544663f..25303fd3cb 100644 --- a/tests/configs/modules/weather/currentweather_compliments.js +++ b/tests/configs/modules/weather/currentweather_compliments.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config current weather compliments - * - * By rejas https://github.com/rejas - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/weather/currentweather_default.js b/tests/configs/modules/weather/currentweather_default.js index e2ef16b764..cd02cdecc5 100644 --- a/tests/configs/modules/weather/currentweather_default.js +++ b/tests/configs/modules/weather/currentweather_default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default weather - * - * By fewieden https://github.com/fewieden - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/weather/currentweather_options.js b/tests/configs/modules/weather/currentweather_options.js index 2dd9216327..5ad748e480 100644 --- a/tests/configs/modules/weather/currentweather_options.js +++ b/tests/configs/modules/weather/currentweather_options.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default weather - * - * By fewieden https://github.com/fewieden - * MIT Licensed. - */ let config = { modules: [ { diff --git a/tests/configs/modules/weather/currentweather_units.js b/tests/configs/modules/weather/currentweather_units.js index ac007314a5..a51bb58ab7 100644 --- a/tests/configs/modules/weather/currentweather_units.js +++ b/tests/configs/modules/weather/currentweather_units.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default weather - * - * By fewieden https://github.com/fewieden - * MIT Licensed. - */ let config = { units: "imperial", diff --git a/tests/configs/modules/weather/forecastweather_absolute.js b/tests/configs/modules/weather/forecastweather_absolute.js index 9972383b4e..a2640d3025 100644 --- a/tests/configs/modules/weather/forecastweather_absolute.js +++ b/tests/configs/modules/weather/forecastweather_absolute.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default weather - * - * By fewieden https://github.com/fewieden - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/weather/forecastweather_default.js b/tests/configs/modules/weather/forecastweather_default.js index 6f535b39c3..4cddef62fa 100644 --- a/tests/configs/modules/weather/forecastweather_default.js +++ b/tests/configs/modules/weather/forecastweather_default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default weather - * - * By fewieden https://github.com/fewieden - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/weather/forecastweather_options.js b/tests/configs/modules/weather/forecastweather_options.js index 23cda84f67..0eea8292ed 100644 --- a/tests/configs/modules/weather/forecastweather_options.js +++ b/tests/configs/modules/weather/forecastweather_options.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default weather - * - * By fewieden https://github.com/fewieden - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/weather/forecastweather_units.js b/tests/configs/modules/weather/forecastweather_units.js index 22a9820a1e..8ac58a43b0 100644 --- a/tests/configs/modules/weather/forecastweather_units.js +++ b/tests/configs/modules/weather/forecastweather_units.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config default weather - * - * By rejas - * MIT Licensed. - */ let config = { units: "imperial", diff --git a/tests/configs/modules/weather/hourlyweather_default.js b/tests/configs/modules/weather/hourlyweather_default.js index aca5ced8f8..8e46b44cab 100644 --- a/tests/configs/modules/weather/hourlyweather_default.js +++ b/tests/configs/modules/weather/hourlyweather_default.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config hourly weather - * - * By rejas https://github.com/rejas - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/weather/hourlyweather_options.js b/tests/configs/modules/weather/hourlyweather_options.js index 0d73311768..b37fd7b9f1 100644 --- a/tests/configs/modules/weather/hourlyweather_options.js +++ b/tests/configs/modules/weather/hourlyweather_options.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config hourly weather options - * - * By rejas https://github.com/rejas - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js index 4ba579e1d3..0e79858f16 100644 --- a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js +++ b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config hourly weather - * - * By rejas https://github.com/rejas - * MIT Licensed. - */ let config = { timeFormat: 12, diff --git a/tests/configs/noIpWhiteList.js b/tests/configs/noIpWhiteList.js index 09e74061a2..57eaa91215 100644 --- a/tests/configs/noIpWhiteList.js +++ b/tests/configs/noIpWhiteList.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config sample ipWhitelist - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = require(`${process.cwd()}/tests/configs/default.js`).configFactory({ ipWhitelist: ["x.x.x.x"], port: 8181 diff --git a/tests/configs/port_8090.js b/tests/configs/port_8090.js index 25d4bce224..4019be8e89 100644 --- a/tests/configs/port_8090.js +++ b/tests/configs/port_8090.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test config sample environment set port 8090 - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = require(`${process.cwd()}/tests/configs/default.js`).configFactory({ port: 8090 }); diff --git a/tests/configs/port_variable.js.template b/tests/configs/port_variable.js.template index 0a0d58bb9a..e44aa5ac90 100644 --- a/tests/configs/port_variable.js.template +++ b/tests/configs/port_variable.js.template @@ -1,8 +1,3 @@ -/* MagicMirror² Test config sample environment set port 8090 - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = require(`${process.cwd()}/tests/configs/default.js`).configFactory({ port: ${MM_PORT} }); diff --git a/tests/configs/without_modules.js b/tests/configs/without_modules.js index 51ce02f6e0..abe8fbc42e 100644 --- a/tests/configs/without_modules.js +++ b/tests/configs/without_modules.js @@ -1,8 +1,3 @@ -/* MagicMirror² Test default config for modules - * - * By Rodrigo Ramírez Norambuena https://rodrigoramirez.com - * MIT Licensed. - */ let config = { ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.10.1"] }; diff --git a/tests/e2e/animateCSS_spec.js b/tests/e2e/animateCSS_spec.js index 3cb3aca607..d7fcb52e44 100644 --- a/tests/e2e/animateCSS_spec.js +++ b/tests/e2e/animateCSS_spec.js @@ -1,10 +1,3 @@ -/* AnimateCSS integration Test with compliments module - * - * By bugsounet https://github.com/bugsounet - * and helped by khassel - * 09/2023 - * MIT Licensed. - */ const helpers = require("./helpers/global-setup"); describe("AnimateCSS integration Test", () => { diff --git a/translations/translations.js b/translations/translations.js index f3b2d2c14a..69d1591dfa 100644 --- a/translations/translations.js +++ b/translations/translations.js @@ -1,10 +1,3 @@ -/* MagicMirror² - * Translation Definition - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ - let translations = { en: "translations/en.json", // English nl: "translations/nl.json", // Dutch diff --git a/vendor/vendor.js b/vendor/vendor.js index 7d7a2a8ee8..b2d912d4de 100644 --- a/vendor/vendor.js +++ b/vendor/vendor.js @@ -1,9 +1,3 @@ -/* MagicMirror² - * Vendor File Definition - * - * By Michael Teeuw https://michaelteeuw.nl - * MIT Licensed. - */ const vendor = { "moment.js": "node_modules/moment/min/moment-with-locales.js", "moment-timezone.js": "node_modules/moment-timezone/builds/moment-timezone-with-data.js", From 7f0b8e4054bf5e16f0e90de5ebe44ac0b4c4f032 Mon Sep 17 00:00:00 2001 From: jkriegshauser Date: Fri, 26 Jan 2024 22:56:54 -0800 Subject: [PATCH 025/418] Better fixes for #3291 and the underlying exdate issues (#3342) * Worked around several issues in the RRULE library that were causing deleted calender events to still show, some initial and recurring events to not show, and some event times to be off an hour. (#3291) * Renamed variables in *calendarfetcherutils.js* to be more clear about use of `moment` and js's `Date` class. * Added calendar config option `forceUseCurrentTime` (default:`false`) which will ignore overridden `Date.now` in the config in order to keep some tests consistent. * Added several unit tests for crossing DST in different timezones with excluded events. --- CHANGELOG.md | 7 + modules/default/calendar/calendar.js | 14 +- .../default/calendar/calendarfetcherutils.js | 253 ++++++++---------- tests/configs/modules/calendar/custom.js | 1 + tests/configs/modules/calendar/exdate.js | 31 --- .../calendar/exdate_la_at_midnight_dst.js | 37 +++ .../calendar/exdate_la_at_midnight_std.js | 37 +++ .../calendar/exdate_la_before_midnight.js | 37 +++ .../calendar/exdate_syd_at_midnight_dst.js | 37 +++ .../calendar/exdate_syd_at_midnight_std.js | 37 +++ .../calendar/exdate_syd_before_midnight.js | 37 +++ tests/electron/helpers/global-setup.js | 6 +- tests/electron/modules/calendar_spec.js | 89 +++++- tests/mocks/calendar_test_exdate.ics | 34 --- tests/mocks/exdate_la_at_midnight_dst.ics | 15 ++ tests/mocks/exdate_la_at_midnight_std.ics | 15 ++ tests/mocks/exdate_la_before_midnight.ics | 15 ++ tests/mocks/exdate_syd_at_midnight_dst.ics | 15 ++ tests/mocks/exdate_syd_at_midnight_std.ics | 15 ++ tests/mocks/exdate_syd_before_midnight.ics | 15 ++ 20 files changed, 528 insertions(+), 219 deletions(-) delete mode 100644 tests/configs/modules/calendar/exdate.js create mode 100644 tests/configs/modules/calendar/exdate_la_at_midnight_dst.js create mode 100644 tests/configs/modules/calendar/exdate_la_at_midnight_std.js create mode 100644 tests/configs/modules/calendar/exdate_la_before_midnight.js create mode 100644 tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js create mode 100644 tests/configs/modules/calendar/exdate_syd_at_midnight_std.js create mode 100644 tests/configs/modules/calendar/exdate_syd_before_midnight.js delete mode 100644 tests/mocks/calendar_test_exdate.ics create mode 100644 tests/mocks/exdate_la_at_midnight_dst.ics create mode 100644 tests/mocks/exdate_la_at_midnight_std.ics create mode 100644 tests/mocks/exdate_la_before_midnight.ics create mode 100644 tests/mocks/exdate_syd_at_midnight_dst.ics create mode 100644 tests/mocks/exdate_syd_at_midnight_std.ics create mode 100644 tests/mocks/exdate_syd_before_midnight.ics diff --git a/CHANGELOG.md b/CHANGELOG.md index 86a024297a..6842a60592 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,13 @@ _This release is scheduled to be released on 2024-04-01._ - Unneeded file headers (#3358) +## [2.27.0] - UNRELEASED + +### Fixed + +- Worked around several issues in the RRULE library that were causing deleted calender events to still show, some + initial and recurring events to not show, and some event times to be off an hour. (#3291) + ## [2.26.0] - 01-01-2024 Thanks to: @bnitkin, @bugsounet, @dependabot, @jkriegshauser, @kaennchenstruggle, @KristjanESPERANTO and @Ybbet. diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index fe08a883af..3b10b922d1 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -36,6 +36,7 @@ Module.register("calendar", { hideDuplicates: true, showTimeToday: false, colored: false, + forceUseCurrentTime: false, tableClass: "small", calendars: [ { @@ -567,9 +568,16 @@ Module.register("calendar", { const ONE_HOUR = ONE_MINUTE * 60; const ONE_DAY = ONE_HOUR * 24; - const now = new Date(); - const today = moment().startOf("day"); - const future = moment().startOf("day").add(this.config.maximumNumberOfDays, "days").toDate(); + let now, today, future; + if (this.config.forceUseCurrentTime || this.defaults.forceUseCurrentTime) { + now = new Date(); + today = moment().startOf("day"); + future = moment().startOf("day").add(this.config.maximumNumberOfDays, "days").toDate(); + } else { + now = new Date(Date.now()); // Can use overridden time + today = moment(now).startOf("day"); + future = moment(now).startOf("day").add(this.config.maximumNumberOfDays, "days").toDate(); + } let events = []; for (const calendarUrl in this.calendarData) { diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index c2067296cd..4be451eb51 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -56,7 +56,7 @@ const CalendarFetcherUtils = { event.start.tz = ""; Log.debug(`ical offset=${current_offset} date=${date}`); mm = moment(date); - let x = parseInt(moment(new Date()).utcOffset()); + let x = moment(new Date()).utcOffset(); Log.debug(`net mins=${current_offset * 60 - x}`); mm = mm.add(x - current_offset * 60, "minutes"); @@ -128,24 +128,26 @@ const CalendarFetcherUtils = { }; const eventDate = function (event, time) { - return CalendarFetcherUtils.isFullDayEvent(event) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); + return CalendarFetcherUtils.isFullDayEvent(event) ? moment(event[time]).startOf("day") : moment(event[time]); }; Log.debug(`There are ${Object.entries(data).length} calendar entries.`); + + const now = new Date(Date.now()); + const todayLocal = moment(now).startOf("day").toDate(); + const futureLocalDate + = moment(now) + .startOf("day") + .add(config.maximumNumberOfDays, "days") + .subtract(1, "seconds") // Subtract 1 second so that events that start on the middle of the night will not repeat. + .toDate(); + Object.entries(data).forEach(([key, event]) => { Log.debug("Processing entry..."); - const now = new Date(); - const today = moment().startOf("day").toDate(); - const future - = moment() - .startOf("day") - .add(config.maximumNumberOfDays, "days") - .subtract(1, "seconds") // Subtract 1 second so that events that start on the middle of the night will not repeat. - .toDate(); - let past = today; + let pastLocalDate = todayLocal; if (config.includePastEvents) { - past = moment().startOf("day").subtract(config.maximumNumberOfDays, "days").toDate(); + pastLocalDate = moment(now).startOf("day").subtract(config.maximumNumberOfDays, "days").toDate(); } // FIXME: Ugly fix to solve the facebook birthday issue. @@ -159,33 +161,33 @@ const CalendarFetcherUtils = { if (event.type === "VEVENT") { Log.debug(`Event:\n${JSON.stringify(event)}`); - let startDate = eventDate(event, "start"); - let endDate; + let startMoment = eventDate(event, "start"); + let endMoment; if (typeof event.end !== "undefined") { - endDate = eventDate(event, "end"); + endMoment = eventDate(event, "end"); } else if (typeof event.duration !== "undefined") { - endDate = startDate.clone().add(moment.duration(event.duration)); + endMoment = startMoment.clone().add(moment.duration(event.duration)); } else { if (!isFacebookBirthday) { // make copy of start date, separate storage area - endDate = moment(startDate.format("x"), "x"); + endMoment = moment(startMoment.valueOf()); } else { - endDate = moment(startDate).add(1, "days"); + endMoment = moment(startMoment).add(1, "days"); } } - Log.debug(`start: ${startDate.toDate()}`); - Log.debug(`end:: ${endDate.toDate()}`); + Log.debug(`start: ${startMoment.toDate()}`); + Log.debug(`end:: ${endMoment.toDate()}`); // Calculate the duration of the event for use with recurring events. - let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x")); - Log.debug(`duration: ${duration}`); + const durationMs = endMoment.valueOf() - startMoment.valueOf(); + Log.debug(`duration: ${durationMs}`); // FIXME: Since the parsed json object from node-ical comes with time information // this check could be removed (?) if (event.start.length === 8) { - startDate = startDate.startOf("day"); + startMoment = startMoment.startOf("day"); } const title = CalendarFetcherUtils.getTitleFromEvent(event); @@ -245,11 +247,11 @@ const CalendarFetcherUtils = { const geo = event.geo || false; const description = event.description || false; - if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) { + if (event.rrule && typeof event.rrule !== "undefined" && !isFacebookBirthday) { const rule = event.rrule; - const pastMoment = moment(past); - const futureMoment = moment(future); + const pastMoment = moment(pastLocalDate); + const futureMoment = moment(futureLocalDate); // can cause problems with e.g. birthdays before 1900 if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) { @@ -260,8 +262,8 @@ const CalendarFetcherUtils = { // For recurring events, get the set of start dates that fall within the range // of dates we're looking for. // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time - let pastLocal = 0; - let futureLocal = 0; + let pastLocal; + let futureLocal; if (CalendarFetcherUtils.isFullDayEvent(event)) { Log.debug("fullday"); // if full day event, only use the date part of the ranges @@ -277,17 +279,51 @@ const CalendarFetcherUtils = { pastLocal = pastMoment.toDate(); } else { // otherwise use NOW.. cause we shouldn't use any before now - pastLocal = moment().toDate(); //now + pastLocal = moment(now).toDate(); //now } futureLocal = futureMoment.toDate(); // future } Log.debug(`Search for recurring events between: ${pastLocal} and ${futureLocal}`); - let dates = rule.between(pastLocal, futureLocal, true, limitFunction); + const hasByWeekdayRule = rule.options.byweekday !== undefined && rule.options.byweekday !== null; + const oneDayInMs = 24 * 60 * 60 * 1000; + Log.debug(`RRule: ${rule.toString()}`); + rule.options.tzid = null; // RRule gets *very* confused with timezones + let dates = rule.between(new Date(pastLocal.valueOf() - oneDayInMs), new Date(futureLocal.valueOf() + oneDayInMs), true, () => { return true; }); Log.debug(`Title: ${event.summary}, with dates: ${JSON.stringify(dates)}`); dates = dates.filter((d) => { if (JSON.stringify(d) === "null") return false; else return true; }); + + // RRule can generate dates with an incorrect recurrence date. Process the array here and apply date correction. + if (hasByWeekdayRule) { + Log.debug("Rule has byweekday, checking for correction"); + dates.forEach((date, index, arr) => { + // NOTE: getTimezoneOffset() is negative of the expected value. For America/Los_Angeles under DST (GMT-7), + // this value is +420. For Australia/Sydney under DST (GMT+11), this value is -660. + const tzOffset = date.getTimezoneOffset() / 60; + const hour = date.getHours(); + if ((tzOffset < 0) && (hour < -tzOffset)) { // east of GMT + Log.debug(`East of GMT (tzOffset: ${tzOffset}) and hour=${hour} < ${-tzOffset}, Subtracting 1 day from ${date}`); + arr[index] = new Date(date.valueOf() - oneDayInMs); + } else if ((tzOffset > 0) && (hour >= (24 - tzOffset))) { // west of GMT + Log.debug(`West of GMT (tzOffset: ${tzOffset}) and hour=${hour} >= 24-${tzOffset}, Adding 1 day to ${date}`); + arr[index] = new Date(date.valueOf() + oneDayInMs); + } + }); + } + + // The dates array from rrule can be confused by DST. If the event was created during DST and we + // are querying a date range during non-DST, rrule can have the incorrect time for the date range. + // Reprocess the array here computing and applying the time offset. + dates.forEach((date, index, arr) => { + let adjustHours = CalendarFetcherUtils.calculateTimezoneAdjustment(event, date); + if (adjustHours !== 0) { + Log.debug(`Applying timezone adjustment hours=${adjustHours} to ${date}`); + arr[index] = new Date(date.valueOf() + (adjustHours * 60 * 60 * 1000)); + } + }); + // The "dates" array contains the set of dates within our desired date range range that are valid // for the recurrence rule. *However*, it's possible for us to have a specific recurrence that // had its date changed from outside the range to inside the range. For the time being, @@ -297,108 +333,35 @@ const CalendarFetcherUtils = { // Would be great if there was a better way to handle this. Log.debug(`event.recurrences: ${event.recurrences}`); if (event.recurrences !== undefined) { - for (let r in event.recurrences) { + for (let dateKey in event.recurrences) { // Only add dates that weren't already in the range we added from the rrule so that - // we don"t double-add those events. - if (moment(new Date(r)).isBetween(pastMoment, futureMoment) !== true) { - dates.push(new Date(r)); + // we don't double-add those events. + let d = new Date(dateKey); + if (!moment(d).isBetween(pastMoment, futureMoment)) { + dates.push(d); } } } + + // Lastly, sometimes rrule doesn't include the event.start even if it is in the requested range. Ensure + // inclusion here. Unfortunately dates.includes() doesn't find it so we have to do forEach(). + { + let found = false; + dates.forEach((d) => { if (d.valueOf() === event.start.valueOf()) found = true; }); + if (!found) { + Log.debug(`event.start=${event.start} was not included in results from rrule; adding`); + dates.splice(0, 0, event.start); + } + } + // Loop through the set of date entries to see which recurrences should be added to our event list. for (let d in dates) { let date = dates[d]; let curEvent = event; + let curDurationMs = durationMs; let showRecurrence = true; - // set the time information in the date to equal the time information in the event - date.setUTCHours(curEvent.start.getUTCHours(), curEvent.start.getUTCMinutes(), curEvent.start.getUTCSeconds(), curEvent.start.getUTCMilliseconds()); - - // Get the offset of today where we are processing - // This will be the correction, we need to apply. - let nowOffset = new Date().getTimezoneOffset(); - // For full day events, the time might be off from RRULE/Luxon problem - // Get time zone offset of the rule calculated event - let dateoffset = date.getTimezoneOffset(); - - // Reduce the time by the following offset. - Log.debug(` recurring date is ${date} offset is ${dateoffset}`); - - let dh = moment(date).format("HH"); - Log.debug(` recurring date is ${date} offset is ${dateoffset / 60} Hour is ${dh}`); - - if (CalendarFetcherUtils.isFullDayEvent(event)) { - Log.debug("Fullday"); - // If the offset is negative (east of GMT), where the problem is - if (dateoffset < 0) { - if (dh < Math.abs(dateoffset / 60)) { - // if the rrule byweekday WAS explicitly set , correct it - // reduce the time by the offset - if (curEvent.rrule.origOptions.byweekday !== undefined) { - // Apply the correction to the date/time to get it UTC relative - date = new Date(date.getTime() - Math.abs(24 * 60) * 60000); - } - // the duration was calculated way back at the top before we could correct the start time.. - // fix it for this event entry - //duration = 24 * 60 * 60 * 1000; - Log.debug(`new recurring date1 fulldate is ${date}`); - } - } else { - // if the timezones are the same, correct date if needed - //if (event.start.tz === moment.tz.guess()) { - // if the date hour is less than the offset - if (24 - dh <= Math.abs(dateoffset / 60)) { - // if the rrule byweekday WAS explicitly set , correct it - if (curEvent.rrule.origOptions.byweekday !== undefined) { - // apply the correction to the date/time back to right day - date = new Date(date.getTime() + Math.abs(24 * 60) * 60000); - } - // the duration was calculated way back at the top before we could correct the start time.. - // fix it for this event entry - //duration = 24 * 60 * 60 * 1000; - Log.debug(`new recurring date2 fulldate is ${date}`); - } - //} - } - } else { - // not full day, but luxon can still screw up the date on the rule processing - // we need to correct the date to get back to the right event for - if (dateoffset < 0) { - // if the date hour is less than the offset - if (dh <= Math.abs(dateoffset / 60)) { - // if the rrule byweekday WAS explicitly set , correct it - if (curEvent.rrule.origOptions.byweekday !== undefined) { - // Reduce the time by t: - // Apply the correction to the date/time to get it UTC relative - date = new Date(date.getTime() - Math.abs(24 * 60) * 60000); - } - // the duration was calculated way back at the top before we could correct the start time.. - // fix it for this event entry - //duration = 24 * 60 * 60 * 1000; - Log.debug(`new recurring date1 is ${date}`); - } - } else { - // if the timezones are the same, correct date if needed - //if (event.start.tz === moment.tz.guess()) { - // if the date hour is less than the offset - if (24 - dh <= Math.abs(dateoffset / 60)) { - // if the rrule byweekday WAS explicitly set , correct it - if (curEvent.rrule.origOptions.byweekday !== undefined) { - // apply the correction to the date/time back to right day - date = new Date(date.getTime() + Math.abs(24 * 60) * 60000); - } - // the duration was calculated way back at the top before we could correct the start time.. - // fix it for this event entry - //duration = 24 * 60 * 60 * 1000; - Log.debug(`new recurring date2 is ${date}`); - } - //} - } - } - startDate = moment(date); - Log.debug(`Corrected startDate: ${startDate.toDate()}`); - - let adjustDays = CalendarFetcherUtils.calculateTimezoneAdjustment(event, date); + startMoment = moment(date); // Remove the time information of each date by using its substring, using the following method: // .toISOString().substring(0,10). @@ -411,30 +374,30 @@ const CalendarFetcherUtils = { if (curEvent.recurrences !== undefined && curEvent.recurrences[dateKey] !== undefined) { // We found an override, so for this recurrence, use a potentially different title, start date, and duration. curEvent = curEvent.recurrences[dateKey]; - startDate = moment(curEvent.start); - duration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x")); + startMoment = moment(curEvent.start); + curDurationMs = curEvent.end.valueOf() - startMoment.valueOf(); } // If there's no recurrence override, check for an exception date. Exception dates represent exceptions to the rule. else if (curEvent.exdate !== undefined && curEvent.exdate[dateKey] !== undefined) { // This date is an exception date, which means we should skip it in the recurrence pattern. showRecurrence = false; } - Log.debug(`duration: ${duration}`); + Log.debug(`duration: ${curDurationMs}`); - endDate = moment(parseInt(startDate.format("x")) + duration, "x"); - if (startDate.format("x") === endDate.format("x")) { - endDate = endDate.endOf("day"); + endMoment = moment(startMoment.valueOf() + curDurationMs); + if (startMoment.valueOf() === endMoment.valueOf()) { + endMoment = endMoment.endOf("day"); } const recurrenceTitle = CalendarFetcherUtils.getTitleFromEvent(curEvent); // If this recurrence ends before the start of the date range, or starts after the end of the date range, don"t add // it to the event list. - if (endDate.isBefore(past) || startDate.isAfter(future)) { + if (endMoment.isBefore(pastLocal) || startMoment.isAfter(futureLocal)) { showRecurrence = false; } - if (CalendarFetcherUtils.timeFilterApplies(now, endDate, dateFilter)) { + if (CalendarFetcherUtils.timeFilterApplies(now, endMoment, dateFilter)) { showRecurrence = false; } @@ -442,8 +405,8 @@ const CalendarFetcherUtils = { Log.debug(`saving event: ${description}`); newEvents.push({ title: recurrenceTitle, - startDate: (adjustDays ? (adjustDays > 0 ? startDate.add(adjustDays, "hours") : startDate.subtract(Math.abs(adjustDays), "hours")) : startDate).format("x"), - endDate: (adjustDays ? (adjustDays > 0 ? endDate.add(adjustDays, "hours") : endDate.subtract(Math.abs(adjustDays), "hours")) : endDate).format("x"), + startDate: startMoment.format("x"), + endDate: endMoment.format("x"), fullDayEvent: CalendarFetcherUtils.isFullDayEvent(event), recurringEvent: true, class: event.class, @@ -461,43 +424,47 @@ const CalendarFetcherUtils = { // Log.debug("full day event") // if the start and end are the same, then make end the 'end of day' value (start is at 00:00:00) - if (fullDayEvent && startDate.format("x") === endDate.format("x")) { - endDate = endDate.endOf("day"); + if (fullDayEvent && startMoment.valueOf() === endMoment.valueOf()) { + endMoment = endMoment.endOf("day"); } if (config.includePastEvents) { // Past event is too far in the past, so skip. - if (endDate < past) { + if (endMoment < pastLocalDate) { return; } } else { // It's not a fullday event, and it is in the past, so skip. - if (!fullDayEvent && endDate < new Date()) { + if (!fullDayEvent && endMoment < now) { return; } // It's a fullday event, and it is before today, So skip. - if (fullDayEvent && endDate <= today) { + if (fullDayEvent && endMoment <= todayLocal) { return; } } // It exceeds the maximumNumberOfDays limit, so skip. - if (startDate > future) { + if (startMoment > futureLocalDate) { return; } - if (CalendarFetcherUtils.timeFilterApplies(now, endDate, dateFilter)) { + if (CalendarFetcherUtils.timeFilterApplies(now, endMoment, dateFilter)) { return; } // get correction for date saving and dst change between now and then - let adjustDays = CalendarFetcherUtils.calculateTimezoneAdjustment(event, startDate.toDate()); + let adjustHours = CalendarFetcherUtils.calculateTimezoneAdjustment(event, startMoment.toDate()); + // This shouldn't happen + if (adjustHours) { + Log.warn(`Unexpected timezone adjustment of ${adjustHours} hours on non-recurring event`); + } // Every thing is good. Add it to the list. newEvents.push({ title: title, - startDate: (adjustDays ? (adjustDays > 0 ? startDate.add(adjustDays, "hours") : startDate.subtract(Math.abs(adjustDays), "hours")) : startDate).format("x"), - endDate: (adjustDays ? (adjustDays > 0 ? endDate.add(adjustDays, "hours") : endDate.subtract(Math.abs(adjustDays), "hours")) : endDate).format("x"), + startDate: startMoment.add(adjustHours, "hours").format("x"), + endDate: endMoment.add(adjustHours, "hours").format("x"), fullDayEvent: fullDayEvent, class: event.class, location: location, @@ -578,7 +545,7 @@ const CalendarFetcherUtils = { increment = until[1].slice(-1) === "s" ? until[1] : `${until[1]}s`, // Massage the data for moment js filterUntil = moment(endDate.format()).subtract(value, increment); - return now < filterUntil.format("x"); + return now < filterUntil.toDate(); } return false; diff --git a/tests/configs/modules/calendar/custom.js b/tests/configs/modules/calendar/custom.js index 4c6deb7838..8552bcbe5c 100644 --- a/tests/configs/modules/calendar/custom.js +++ b/tests/configs/modules/calendar/custom.js @@ -7,6 +7,7 @@ let config = { position: "bottom_bar", config: { customEvents: [{ keyword: "CustomEvent", symbol: "dice", eventClass: "undo" }], + forceUseCurrentTime: true, calendars: [ { maximumEntries: 5, diff --git a/tests/configs/modules/calendar/exdate.js b/tests/configs/modules/calendar/exdate.js deleted file mode 100644 index bb52561aa0..0000000000 --- a/tests/configs/modules/calendar/exdate.js +++ /dev/null @@ -1,31 +0,0 @@ -/* NOTE: calendar_test_exdate.ics has exdate entries for the next 20 years, but without some - * way to set a debug date for tests, this test may become flaky on specific days (i.e. could - * not test easily on leap-years, the BYDAY specified in exdate, etc.) or when the 20 years - * elapses if this project is still in active development ;) - * See issue #3250 - */ -let config = { - timeFormat: 12, - - modules: [ - { - module: "calendar", - position: "bottom_bar", - config: { - maximumEntries: 100, - calendars: [ - { - maximumEntries: 100, - maximumNumberOfDays: 364, - url: "http://localhost:8080/tests/mocks/calendar_test_exdate.ics" - } - ] - } - } - ] -}; - -/*************** DO NOT EDIT THE LINE BELOW ***************/ -if (typeof module !== "undefined") { - module.exports = config; -} diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js new file mode 100644 index 0000000000..608c71da96 --- /dev/null +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js @@ -0,0 +1,37 @@ +/* MagicMirror² Test calendar exdate + * + * By jkriegshauser + * MIT Licensed. + * + * See issue #3250 + * See tests/electron/modules/calendar_spec.js + */ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + maximumEntries: 100, + calendars: [ + { + maximumEntries: 100, + maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped + url: "http://localhost:8080/tests/mocks/exdate_la_at_midnight_dst.ics" + } + ] + } + } + ] +}; + +Date.now = () => { + return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf(); +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js new file mode 100644 index 0000000000..6128c97f50 --- /dev/null +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js @@ -0,0 +1,37 @@ +/* MagicMirror² Test calendar exdate + * + * By jkriegshauser + * MIT Licensed. + * + * See issue #3250 + * See tests/electron/modules/calendar_spec.js + */ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + maximumEntries: 100, + calendars: [ + { + maximumEntries: 100, + maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped + url: "http://localhost:8080/tests/mocks/exdate_la_at_midnight_std.ics" + } + ] + } + } + ] +}; + +Date.now = () => { + return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf(); +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/exdate_la_before_midnight.js b/tests/configs/modules/calendar/exdate_la_before_midnight.js new file mode 100644 index 0000000000..8c886f775a --- /dev/null +++ b/tests/configs/modules/calendar/exdate_la_before_midnight.js @@ -0,0 +1,37 @@ +/* MagicMirror² Test calendar exdate + * + * By jkriegshauser + * MIT Licensed. + * + * See issue #3250 + * See tests/electron/modules/calendar_spec.js + */ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + maximumEntries: 100, + calendars: [ + { + maximumEntries: 100, + maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped + url: "http://localhost:8080/tests/mocks/exdate_la_before_midnight.ics" + } + ] + } + } + ] +}; + +Date.now = () => { + return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf(); +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js new file mode 100644 index 0000000000..f98b75f4c7 --- /dev/null +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js @@ -0,0 +1,37 @@ +/* MagicMirror² Test calendar exdate + * + * By jkriegshauser + * MIT Licensed. + * + * See issue #3250 + * See tests/electron/modules/calendar_spec.js + */ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + maximumEntries: 100, + calendars: [ + { + maximumEntries: 100, + maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped + url: "http://localhost:8080/tests/mocks/exdate_syd_at_midnight_dst.ics" + } + ] + } + } + ] +}; + +Date.now = () => { + return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf(); +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js new file mode 100644 index 0000000000..06c7ff5319 --- /dev/null +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js @@ -0,0 +1,37 @@ +/* MagicMirror² Test calendar exdate + * + * By jkriegshauser + * MIT Licensed. + * + * See issue #3250 + * See tests/electron/modules/calendar_spec.js + */ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + maximumEntries: 100, + calendars: [ + { + maximumEntries: 100, + maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped + url: "http://localhost:8080/tests/mocks/exdate_syd_at_midnight_std.ics" + } + ] + } + } + ] +}; + +Date.now = () => { + return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf(); +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/exdate_syd_before_midnight.js b/tests/configs/modules/calendar/exdate_syd_before_midnight.js new file mode 100644 index 0000000000..849c1f5363 --- /dev/null +++ b/tests/configs/modules/calendar/exdate_syd_before_midnight.js @@ -0,0 +1,37 @@ +/* MagicMirror² Test calendar exdate + * + * By jkriegshauser + * MIT Licensed. + * + * See issue #3250 + * See tests/electron/modules/calendar_spec.js + */ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + maximumEntries: 100, + calendars: [ + { + maximumEntries: 100, + maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped + url: "http://localhost:8080/tests/mocks/exdate_syd_before_midnight.ics" + } + ] + } + } + ] +}; + +Date.now = () => { + return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf(); +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/electron/helpers/global-setup.js b/tests/electron/helpers/global-setup.js index 164c7f6630..71dfd0ddbe 100644 --- a/tests/electron/helpers/global-setup.js +++ b/tests/electron/helpers/global-setup.js @@ -3,11 +3,11 @@ // https://www.anycodings.com/1questions/958135/can-i-set-the-date-for-playwright-browser const { _electron: electron } = require("playwright"); -exports.startApplication = async (configFilename, systemDate = null, electronParams = ["js/electron.js"]) => { +exports.startApplication = async (configFilename, systemDate = null, electronParams = ["js/electron.js"], timezone = "GMT") => { global.electronApp = null; global.page = null; process.env.MM_CONFIG_FILE = configFilename; - process.env.TZ = "GMT"; + process.env.TZ = timezone; global.electronApp = await electron.launch({ args: electronParams }); await global.electronApp.firstWindow(); @@ -20,7 +20,7 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar if (systemDate) { await global.page.evaluate((systemDate) => { Date.now = () => { - return new Date(systemDate); + return new Date(systemDate).valueOf(); }; }, systemDate); } diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 2af61a93df..3dcbd36f68 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -44,17 +44,96 @@ describe("Calendar module", () => { }); }); - describe("Exdate check", () => { - it("should show the recurring event 51 times (excluded once) in a 364-day (inclusive) period", async () => { - // test must run on a Thursday - await helpers.startApplication("tests/configs/modules/calendar/exdate.js", "14 Dec 2023 12:30:00 GMT"); + /****************************/ + // LOS ANGELES TESTS: + // In 2023, DST (GMT-7) was until 5 Nov, after which is standard (STD) (GMT-8) time. + // Test takes place on Thu 19 Oct, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be + // 4 events (25 Oct, 1 Nov, (switch to STD), 8 Nov, Nov 15), but 1 Nov and 8 Nov are excluded. + // There are three separate tests: + // * before midnight GMT (3pm local time) + // * at midnight GMT in STD time (4pm local time) + // * at midnight GMT in DST time (5pm local time) + describe("Exdate: LA crossover DST before midnight GMT", () => { + it("LA crossover DST before midnight GMT should have 2 events", async () => { + await helpers.startApplication("tests/configs/modules/calendar/exdate_la_before_midnight.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); expect(global.page).not.toBeNull(); const loc = await global.page.locator(".calendar .event"); const elem = loc.first(); await elem.waitFor(); expect(elem).not.toBeNull(); const cnt = await loc.count(); - expect(cnt).toBe(51); + expect(cnt).toBe(2); + }); + }); + + describe("Exdate: LA crossover DST at midnight GMT local STD", () => { + it("LA crossover DST before midnight GMT should have 2 events", async () => { + await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_std.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + const cnt = await loc.count(); + expect(cnt).toBe(2); + }); + }); + describe("Exdate: LA crossover DST at midnight GMT local DST", () => { + it("LA crossover DST before midnight GMT should have 2 events", async () => { + await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_dst.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + const cnt = await loc.count(); + expect(cnt).toBe(2); + }); + }); + + /****************************/ + // SYDNEY TESTS: + // In 2023, standard time (STD) (GMT+10) was until 1 Oct, after which is DST (GMT+11). + // Test takes place on Thu 14 Sep, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be + // 4 events (20 Sep, 27 Sep, (switch to DST), 4 Oct, 11 Oct), but 27 Sep and 4 Oct are excluded. + // There are three separate tests: + // * before midnight GMT (9am local time) + // * at midnight GMT in STD time (10am local time) + // * at midnight GMT in DST time (11am local time) + describe("Exdate: SYD crossover DST before midnight GMT", () => { + it("LA crossover DST before midnight GMT should have 2 events", async () => { + await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_before_midnight.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + const cnt = await loc.count(); + expect(cnt).toBe(2); + }); + }); + describe("Exdate: SYD crossover DST at midnight GMT local STD", () => { + it("LA crossover DST before midnight GMT should have 2 events", async () => { + await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_std.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + const cnt = await loc.count(); + expect(cnt).toBe(2); + }); + }); + describe("Exdate: SYD crossover DST at midnight GMT local DST", () => { + it("SYD crossover DST at midnight GMT local DST should have 2 events", async () => { + await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + const cnt = await loc.count(); + expect(cnt).toBe(2); }); }); }); diff --git a/tests/mocks/calendar_test_exdate.ics b/tests/mocks/calendar_test_exdate.ics deleted file mode 100644 index 8f1f8b9f32..0000000000 --- a/tests/mocks/calendar_test_exdate.ics +++ /dev/null @@ -1,34 +0,0 @@ -BEGIN:VEVENT -DTSTART;TZID=UTC:20231025T181000 -DTEND;TZID=UTC:20231025T195000 -RRULE:FREQ=WEEKLY;BYDAY=WE -EXDATE;TZID=UTC:20231101T181000 -EXDATE;TZID=UTC:20241030T181000 -EXDATE;TZID=UTC:20251029T181000 -EXDATE;TZID=UTC:20261028T181000 -EXDATE;TZID=UTC:20271027T181000 -EXDATE;TZID=UTC:20281025T181000 -EXDATE;TZID=UTC:20291024T181000 -EXDATE;TZID=UTC:20301023T181000 -EXDATE;TZID=UTC:20311022T181000 -EXDATE;TZID=UTC:20321020T181000 -EXDATE;TZID=UTC:20331019T181000 -EXDATE;TZID=UTC:20341018T181000 -EXDATE;TZID=UTC:20351017T181000 -EXDATE;TZID=UTC:20361015T181000 -EXDATE;TZID=UTC:20371014T181000 -EXDATE;TZID=UTC:20381013T181000 -EXDATE;TZID=UTC:20391012T181000 -EXDATE;TZID=UTC:20401010T181000 -EXDATE;TZID=UTC:20411009T181000 -EXDATE;TZID=UTC:20421008T181000 -EXDATE;TZID=UTC:20431007T181000 -DTSTAMP:20231025T233434Z -UID:sdflbkasuhdb5fkauglkb@google.com -CREATED:20230306T193128Z -LAST-MODIFIED:20231024T222515Z -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:My Event -TRANSP:OPAQUE -END:VEVENT diff --git a/tests/mocks/exdate_la_at_midnight_dst.ics b/tests/mocks/exdate_la_at_midnight_dst.ics new file mode 100644 index 0000000000..6f8575f5d7 --- /dev/null +++ b/tests/mocks/exdate_la_at_midnight_dst.ics @@ -0,0 +1,15 @@ +BEGIN:VEVENT +DTSTART;TZID=America/Los_Angeles:20231025T170000 +DTEND;TZID=America/Los_Angeles:20231025T180000 +RRULE:FREQ=WEEKLY;BYDAY=WE +EXDATE;TZID=America/Los_Angeles:20231101T170000 +EXDATE;TZID=America/Los_Angeles:20231108T170000 +DTSTAMP:20231025T233434Z +UID:sdflbkasuhdb5fkauglkb@google.com +CREATED:20230306T193128Z +LAST-MODIFIED:20231024T222515Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:My Event +TRANSP:OPAQUE +END:VEVENT \ No newline at end of file diff --git a/tests/mocks/exdate_la_at_midnight_std.ics b/tests/mocks/exdate_la_at_midnight_std.ics new file mode 100644 index 0000000000..553ca10eef --- /dev/null +++ b/tests/mocks/exdate_la_at_midnight_std.ics @@ -0,0 +1,15 @@ +BEGIN:VEVENT +DTSTART;TZID=America/Los_Angeles:20231025T160000 +DTEND;TZID=America/Los_Angeles:20231025T170000 +RRULE:FREQ=WEEKLY;BYDAY=WE +EXDATE;TZID=America/Los_Angeles:20231101T160000 +EXDATE;TZID=America/Los_Angeles:20231108T160000 +DTSTAMP:20231025T233434Z +UID:sdflbkasuhdb5fkauglkb@google.com +CREATED:20230306T193128Z +LAST-MODIFIED:20231024T222515Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:My Event +TRANSP:OPAQUE +END:VEVENT \ No newline at end of file diff --git a/tests/mocks/exdate_la_before_midnight.ics b/tests/mocks/exdate_la_before_midnight.ics new file mode 100644 index 0000000000..5cdb069b45 --- /dev/null +++ b/tests/mocks/exdate_la_before_midnight.ics @@ -0,0 +1,15 @@ +BEGIN:VEVENT +DTSTART;TZID=America/Los_Angeles:20231025T150000 +DTEND;TZID=America/Los_Angeles:20231025T160000 +RRULE:FREQ=WEEKLY;BYDAY=WE +EXDATE;TZID=America/Los_Angeles:20231101T150000 +EXDATE;TZID=America/Los_Angeles:20231108T150000 +DTSTAMP:20231025T233434Z +UID:sdflbkasuhdb5fkauglkb@google.com +CREATED:20230306T193128Z +LAST-MODIFIED:20231024T222515Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:My Event +TRANSP:OPAQUE +END:VEVENT \ No newline at end of file diff --git a/tests/mocks/exdate_syd_at_midnight_dst.ics b/tests/mocks/exdate_syd_at_midnight_dst.ics new file mode 100644 index 0000000000..9a88a10b6d --- /dev/null +++ b/tests/mocks/exdate_syd_at_midnight_dst.ics @@ -0,0 +1,15 @@ +BEGIN:VEVENT +DTSTART;TZID=Australia/Sydney:20230920T110000 +DTEND;TZID=Australia/Sydney:20230920T111000 +RRULE:FREQ=WEEKLY;BYDAY=WE +EXDATE;TZID=Australia/Sydney:20230927T110000 +EXDATE;TZID=Australia/Sydney:20231004T110000 +DTSTAMP:20231025T233434Z +UID:sdflbkasuhdb5fkauglkb@google.com +CREATED:20230306T193128Z +LAST-MODIFIED:20231024T222515Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:My Event +TRANSP:OPAQUE +END:VEVENT \ No newline at end of file diff --git a/tests/mocks/exdate_syd_at_midnight_std.ics b/tests/mocks/exdate_syd_at_midnight_std.ics new file mode 100644 index 0000000000..af444e8cc0 --- /dev/null +++ b/tests/mocks/exdate_syd_at_midnight_std.ics @@ -0,0 +1,15 @@ +BEGIN:VEVENT +DTSTART;TZID=Australia/Sydney:20230920T100000 +DTEND;TZID=Australia/Sydney:20230920T110000 +RRULE:FREQ=WEEKLY;BYDAY=WE +EXDATE;TZID=Australia/Sydney:20230927T100000 +EXDATE;TZID=Australia/Sydney:20231004T100000 +DTSTAMP:20231025T233434Z +UID:sdflbkasuhdb5fkauglkb@google.com +CREATED:20230306T193128Z +LAST-MODIFIED:20231024T222515Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:My Event +TRANSP:OPAQUE +END:VEVENT \ No newline at end of file diff --git a/tests/mocks/exdate_syd_before_midnight.ics b/tests/mocks/exdate_syd_before_midnight.ics new file mode 100644 index 0000000000..5b5e53d2a2 --- /dev/null +++ b/tests/mocks/exdate_syd_before_midnight.ics @@ -0,0 +1,15 @@ +BEGIN:VEVENT +DTSTART;TZID=Australia/Sydney:20230920T090000 +DTEND;TZID=Australia/Sydney:20230920T100000 +RRULE:FREQ=WEEKLY;BYDAY=WE +EXDATE;TZID=Australia/Sydney:20230927T090000 +EXDATE;TZID=Australia/Sydney:20231004T090000 +DTSTAMP:20231025T233434Z +UID:sdflbkasuhdb5fkauglkb@google.com +CREATED:20230306T193128Z +LAST-MODIFIED:20231024T222515Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:My Event +TRANSP:OPAQUE +END:VEVENT \ No newline at end of file From fb5fab8145c7e6f21641192a451450b6ec330690 Mon Sep 17 00:00:00 2001 From: Veeck Date: Sat, 27 Jan 2024 21:11:57 +0100 Subject: [PATCH 026/418] Cleanups (#3369) - Remove useless css class in clock - Fix typo in calendar - Changelog also got a little screwed after last merge - updated dependencies --- CHANGELOG.md | 9 +- modules/default/calendar/calendar.js | 4 +- modules/default/clock/clock.js | 1 - package-lock.json | 233 +++++++++++++++++---------- package.json | 16 +- 5 files changed, 160 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6842a60592..298462847b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Fixed +- Worked around several issues in the RRULE library that were causing deleted calender events to still show, some + initial and recurring events to not show, and some event times to be off an hour. (#3291) - Skip changelog requirement when running tests for dependency updates (#3320) - [newsfeed] Suppress unsightly animation cases when there are 0 or 1 active news items (#3336) - [newsfeed] Always compute the feed item URL using the same helper function (#3336) @@ -36,13 +38,6 @@ _This release is scheduled to be released on 2024-04-01._ - Unneeded file headers (#3358) -## [2.27.0] - UNRELEASED - -### Fixed - -- Worked around several issues in the RRULE library that were causing deleted calender events to still show, some - initial and recurring events to not show, and some event times to be off an hour. (#3291) - ## [2.26.0] - 01-01-2024 Thanks to: @bnitkin, @bugsounet, @dependabot, @jkriegshauser, @kaennchenstruggle, @KristjanESPERANTO and @Ybbet. diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 3b10b922d1..0ce41cc050 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -92,12 +92,12 @@ Module.register("calendar", { Log.info(`Starting module: ${this.name}`); if (this.config.colored) { - Log.warn("Your are using the deprecated config values 'colored'. Please switch to 'coloredSymbol' & 'coloredText'!"); + Log.warn("Your are using the deprecated config values 'colored'. Please switch to 'coloredSymbol' & 'coloredText'!"); this.config.coloredText = true; this.config.coloredSymbol = true; } if (this.config.coloredSymbolOnly) { - Log.warn("Your are using the deprecated config values 'coloredSymbolOnly'. Please switch to 'coloredSymbol' & 'coloredText'!"); + Log.warn("Your are using the deprecated config values 'coloredSymbolOnly'. Please switch to 'coloredSymbol' & 'coloredText'!"); this.config.coloredText = false; this.config.coloredSymbol = true; } diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 3796a2c359..42b066ab58 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -99,7 +99,6 @@ Module.register("clock", { analogWrapper.className = "clock-circle"; const digitalWrapper = document.createElement("div"); digitalWrapper.className = "digital"; - digitalWrapper.style.gridArea = "center"; /************************************ * Create wrappers for DIGITAL clock diff --git a/package-lock.json b/package-lock.json index 23c0a30d7b..73e79111fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,24 +25,24 @@ "node-ical": "^0.17.1", "pm2": "^5.3.1", "socket.io": "^4.7.4", - "systeminformation": "^5.21.22" + "systeminformation": "^5.21.24" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.5.3", + "@stylistic/eslint-plugin": "^1.5.4", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.3", - "eslint-plugin-jsdoc": "^48.0.2", - "eslint-plugin-package-json": "^0.10.0", + "eslint-plugin-jsdoc": "^48.0.4", + "eslint-plugin-package-json": "^0.10.1", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", "jest": "^29.7.0", "jsdom": "^23.2.0", "lint-staged": "^15.2.0", - "playwright": "^1.41.0", - "prettier": "^3.2.2", + "playwright": "^1.41.1", + "prettier": "^3.2.4", "sinon": "^17.0.1", - "stylelint": "^16.1.0", + "stylelint": "^16.2.0", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0", "suncalc": "^1.9.0" @@ -51,7 +51,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^28.1.3" + "electron": "^28.2.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -1894,15 +1894,15 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.5.3.tgz", - "integrity": "sha512-Vee+hHKaCd8DPRoRJTCV+mOFz+zFIaA9QiNJaAvgBzmPkcDnSC7Ewh518fN6SSNe9psS8TDIpcxd1g5v4MSY5A==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.5.4.tgz", + "integrity": "sha512-zWPXr+O67GC9KDAFkbL1U9UVqE6Iv69YMKhkIECCmE0GvClUJwdfsimm4XebEDondV7kfjMrTDZaYfrI5aS0Jg==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.5.3", - "@stylistic/eslint-plugin-jsx": "1.5.3", - "@stylistic/eslint-plugin-plus": "1.5.3", - "@stylistic/eslint-plugin-ts": "1.5.3" + "@stylistic/eslint-plugin-js": "1.5.4", + "@stylistic/eslint-plugin-jsx": "1.5.4", + "@stylistic/eslint-plugin-plus": "1.5.4", + "@stylistic/eslint-plugin-ts": "1.5.4" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1912,9 +1912,9 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.3.tgz", - "integrity": "sha512-XlKnm82fD7Sw9kQ6FFigE0tobvptNBXZWsdfoKmUyK7bNxHsAHOFT8zJGY3j3MjZ0Fe7rLTu86hX/vOl0bRRdQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.4.tgz", + "integrity": "sha512-3ctWb3NvJNV1MsrZN91cYp2EGInLPSoZKphXIbIRx/zjZxKwLDr9z4LMOWtqjq14li/OgqUUcMq5pj8fgbLoTw==", "dev": true, "dependencies": { "acorn": "^8.11.3", @@ -1930,12 +1930,12 @@ } }, "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.5.3.tgz", - "integrity": "sha512-gKXWFmvg3B4e6G+bVz2p37icjj3gS5lzazZD6oLjmQ2b0Lw527VpnxGjWxQ16keKXtrVzUfebakjskOoALg3CQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.5.4.tgz", + "integrity": "sha512-JUfrpCkeBCqt1IZ4QsP4WgxGza4PhK4LPbc0VnCjHKygl+rgqoDAovqOuzFJ49wJ4Ix3r6OIHFuwiBGswZEVvg==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "^1.5.3", + "@stylistic/eslint-plugin-js": "^1.5.4", "estraverse": "^5.3.0" }, "engines": { @@ -1946,25 +1946,25 @@ } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.5.3.tgz", - "integrity": "sha512-fuOBySbH4dbfY4Dwvu+zg5y+e0lALHTyQske5+a2zNC8Ejnx4rFlVjYOmaVFtxFhTD4V0vM7o21Ozci0igcxKg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.5.4.tgz", + "integrity": "sha512-dI0Cs5vYX/0uMhQDY+NK0cKQ0Pe9B6jWYxd0Ndud+mNloDaVLrsmJocK4zn+YfhGEDs1E4Nk5uAPZEumIpDuSg==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^6.17.0" + "@typescript-eslint/utils": "^6.19.0" }, "peerDependencies": { "eslint": "*" } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.3.tgz", - "integrity": "sha512-/gUEqGo0gpFeu220YmC0788VliKnmTaAz4pI82KA5cUuCp6OzEhGlrNkb1eevMwH0RRgyND20HJxOYvEGlwu+w==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.4.tgz", + "integrity": "sha512-NZDFVIlVNjuPvhT+0Cidm5IS3emtx338xbJTqs2xfOVRDGTpYwRHhNVEGa1rFOpYHmv0sAj6+OXbMDn7ul0K/g==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.5.3", - "@typescript-eslint/utils": "^6.17.0" + "@stylistic/eslint-plugin-js": "1.5.4", + "@typescript-eslint/utils": "^6.19.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2192,13 +2192,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", - "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2209,9 +2209,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", - "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2222,13 +2222,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", - "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2250,17 +2250,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", - "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", + "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", "semver": "^7.5.4" }, "engines": { @@ -2275,12 +2275,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", - "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3918,9 +3918,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/electron/-/electron-28.1.3.tgz", - "integrity": "sha512-NSFyTo6SndTPXzU18XRePv4LnjmuM9rF5GMKta1/kPmi02ISoSRonnD7wUlWXD2x53XyJ6d/TbSVesMW6sXkEQ==", + "version": "28.2.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-28.2.0.tgz", + "integrity": "sha512-22SylXQQ9IHtwLw4D+Z4Si7OUpeDtpHfJVTjy3yv53iLg5zJKKPOCWT4ZwgYGHQZ0eldyBrYBHF/P9FPd2CcVQ==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -4583,9 +4583,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.0.2.tgz", - "integrity": "sha512-CBFl5Jc7+jlV36RwDm+PQ8Uw5r28pn2/uW/OaB+Gw5bFwn4Py/1eYMZ3hGf9S4meUFZ/sRvS+hVif2mRAp6WqQ==", + "version": "48.0.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.0.4.tgz", + "integrity": "sha512-A0cH+5svWPXzGZszBjXA1t0aAqVGS+/x3i02KFmb73rU0iMLnadEcVWcD/dGBZHIfAMKr3YpWh58f6wn4N909w==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.41.0", @@ -4606,9 +4606,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.10.0.tgz", - "integrity": "sha512-vUEfGptdpaEw0DTzN8Yl4cjZ2XZosuzAbZ+kOKJN+tJRe2hZDogesMhNYT8FI26QZ1rYUnfQ0wwzBTjswGr04g==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.10.1.tgz", + "integrity": "sha512-YEiw8Mxjt5UIwefSVW9b7NgkGU6fDFMNm51r3eTrdPMn9hY1ZEYVwrnEAlQ6s57JBk8HBFVhjkyhsQ0KsCf4Pg==", "dev": true, "dependencies": { "package-json-validator": "^0.6.3", @@ -5389,6 +5389,15 @@ "node": ">= 14" } }, + "node_modules/git-hooks-list": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", + "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==", + "dev": true, + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, "node_modules/git-node-fs": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", @@ -8275,6 +8284,18 @@ "node": ">= 14" } }, + "node_modules/package-json-validator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.3.tgz", + "integrity": "sha512-juKiFboV4UKUvWQ+OSxstnyukhuluyuEoFmgZw1Rx21XzmwlgDWLcbl3qzjA3789IRORYhVFs7cmAO0YFGwHCg==", + "dev": true, + "dependencies": { + "optimist": "~0.6.0" + }, + "bin": { + "pjv": "bin/pjv" + } + }, "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -8537,12 +8558,12 @@ } }, "node_modules/playwright": { - "version": "1.41.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.0.tgz", - "integrity": "sha512-XOsfl5ZtAik/T9oek4V0jAypNlaCNzuKOwVhqhgYT3os6kH34PzbRb74F0VWcLYa5WFdnmxl7qyAHBXvPv7lqQ==", + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.1.tgz", + "integrity": "sha512-gdZAWG97oUnbBdRL3GuBvX3nDDmUOuqzV/D24dytqlKt+eI5KbwusluZRGljx1YoJKZ2NRPaeWiFTeGZO7SosQ==", "dev": true, "dependencies": { - "playwright-core": "1.41.0" + "playwright-core": "1.41.1" }, "bin": { "playwright": "cli.js" @@ -8555,9 +8576,9 @@ } }, "node_modules/playwright-core": { - "version": "1.41.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.0.tgz", - "integrity": "sha512-UGKASUhXmvqm2Lxa1fNr8sFwAtqjpgBRr9jQ7XBI8Rn5uFiEowGUGwrruUQsVPIom4bk7Lt+oLGpXobnXzrBIw==", + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.1.tgz", + "integrity": "sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -8821,9 +8842,9 @@ } }, "node_modules/prettier": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.2.tgz", - "integrity": "sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -9951,6 +9972,48 @@ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true + }, + "node_modules/sort-package-json": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.57.0.tgz", + "integrity": "sha512-FYsjYn2dHTRb41wqnv+uEqCUvBpK3jZcTp9rbz2qDTmel7Pmdtf+i2rLaaPMRZeSVM60V3Se31GyWFpmKs4Q5Q==", + "dev": true, + "dependencies": { + "detect-indent": "^6.0.0", + "detect-newline": "3.1.0", + "git-hooks-list": "1.0.3", + "globby": "10.0.0", + "is-plain-obj": "2.1.0", + "sort-object-keys": "^1.1.3" + }, + "bin": { + "sort-package-json": "cli.js" + } + }, + "node_modules/sort-package-json/node_modules/globby": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", + "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -10277,14 +10340,14 @@ } }, "node_modules/stylelint": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.1.0.tgz", - "integrity": "sha512-Sh1rRV0lN1qxz/QsuuooLWsIZ/ona7NKw/fRZd6y6PyXYdD2W0EAzJ8yJcwSx4Iw/muz0CF09VZ+z4EiTAcKmg==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.2.0.tgz", + "integrity": "sha512-gwqU5AkIb52wrAzzn+359S3NIJDMl02TXLUaV2tzA/L6jUdpTwNt+MCxHlc8+Hb2bUHlYVo92YeSIryF2gJthA==", "dev": true, "dependencies": { - "@csstools/css-parser-algorithms": "^2.4.0", - "@csstools/css-tokenizer": "^2.2.2", - "@csstools/media-query-list-parser": "^2.1.6", + "@csstools/css-parser-algorithms": "^2.5.0", + "@csstools/css-tokenizer": "^2.2.3", + "@csstools/media-query-list-parser": "^2.1.7", "@csstools/selector-specificity": "^3.0.1", "balanced-match": "^2.0.0", "colord": "^2.9.3", @@ -10304,14 +10367,14 @@ "is-plain-object": "^5.0.0", "known-css-properties": "^0.29.0", "mathml-tag-names": "^2.1.3", - "meow": "^13.0.0", + "meow": "^13.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.32", + "postcss": "^8.4.33", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^7.0.0", - "postcss-selector-parser": "^6.0.13", + "postcss-selector-parser": "^6.0.15", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", @@ -10615,9 +10678,9 @@ "dev": true }, "node_modules/systeminformation": { - "version": "5.21.22", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.21.22.tgz", - "integrity": "sha512-gNHloAJSyS+sKWkwvmvozZ1eHrdVTEsynWMTY6lvLGBB70gflkBQFw8drXXr1oEXY84+Vr9tOOrN8xHZLJSycA==", + "version": "5.21.24", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.21.24.tgz", + "integrity": "sha512-xQada8ByGGFoRXJaUptGgddn3i7IjtSdqNdCKzB8xkzsM7pHnfLYBWxkPdGzhZ0Z/l+W1yo+aZQZ74d2isj8kw==", "os": [ "darwin", "linux", diff --git a/package.json b/package.json index ccd735af16..860dba45cb 100644 --- a/package.json +++ b/package.json @@ -46,27 +46,27 @@ }, "homepage": "https://magicmirror.builders", "devDependencies": { - "@stylistic/eslint-plugin": "^1.5.3", + "@stylistic/eslint-plugin": "^1.5.4", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.3", - "eslint-plugin-jsdoc": "^48.0.2", - "eslint-plugin-package-json": "^0.10.0", + "eslint-plugin-jsdoc": "^48.0.4", + "eslint-plugin-package-json": "^0.10.1", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", "husky": "^8.0.3", "jest": "^29.7.0", "jsdom": "^23.2.0", "lint-staged": "^15.2.0", - "playwright": "^1.41.0", - "prettier": "^3.2.2", + "playwright": "^1.41.1", + "prettier": "^3.2.4", "sinon": "^17.0.1", - "stylelint": "^16.1.0", + "stylelint": "^16.2.0", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0", "suncalc": "^1.9.0" }, "optionalDependencies": { - "electron": "^28.1.3" + "electron": "^28.2.0" }, "dependencies": { "ansis": "^2.0.3", @@ -84,7 +84,7 @@ "node-ical": "^0.17.1", "pm2": "^5.3.1", "socket.io": "^4.7.4", - "systeminformation": "^5.21.22" + "systeminformation": "^5.21.24" }, "lint-staged": { "*": "prettier --write", From 3bf848075d72ff3ab8a061b87d8f0f3a3be4f3e4 Mon Sep 17 00:00:00 2001 From: Veeck Date: Sat, 27 Jan 2024 22:31:50 +0100 Subject: [PATCH 027/418] Correct apibase of weathergov weatherprovider to match documentation (#2927) Fixes part of #2926 --- CHANGELOG.md | 1 + modules/default/weather/providers/weathergov.js | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 298462847b..a9d516a2cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ _This release is scheduled to be released on 2024-04-01._ ### Fixed +- Correct apibase of weathergov weatherprovider to match documentation (#2926) - Worked around several issues in the RRULE library that were causing deleted calender events to still show, some initial and recurring events to not show, and some event times to be off an hour. (#3291) - Skip changelog requirement when running tests for dependency updates (#3320) diff --git a/modules/default/weather/providers/weathergov.js b/modules/default/weather/providers/weathergov.js index 661f36af59..3c16bd7344 100644 --- a/modules/default/weather/providers/weathergov.js +++ b/modules/default/weather/providers/weathergov.js @@ -34,7 +34,6 @@ WeatherProvider.register("weathergov", { // Called to set the config, this config is the same as the weather module's config. setConfig (config) { this.config = config; - this.config.apiBase = "https://api.weather.gov"; this.fetchWxGovURLs(this.config); }, @@ -118,7 +117,7 @@ WeatherProvider.register("weathergov", { * Get specific URLs */ fetchWxGovURLs (config) { - this.fetchData(`${config.apiBase}/points/${config.lat},${config.lon}`) + this.fetchData(`${config.apiBase}/${config.lat},${config.lon}`) .then((data) => { if (!data || !data.properties) { // points URL did not respond with usable data. From 431bf22adb3dde38518641cb00a1450005c5c1d7 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 28 Jan 2024 23:15:18 +0100 Subject: [PATCH 028/418] Update husky and let lint-staged fix ESLint issues (#3370) The new version of husky makes it possible to simplify the pre-commit hook a little. And since prettier no longer takes care of the JavaScript files in our project, it can no longer come into conflict with ESLint while running lint-staged. Therefore we can activate the correction of ESLint issues here. --- .husky/pre-commit | 2 -- .prettierignore | 1 + CHANGELOG.md | 5 +++-- package-lock.json | 12 ++++++------ package.json | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 7ee201c6c7..d949a3eb50 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,7 +1,5 @@ #!/bin/sh -[ -f "$(dirname "$0")/_/husky.sh" ] && . "$(dirname "$0")/_/husky.sh" - if command -v npm &> /dev/null; then npm run lint:staged fi diff --git a/.prettierignore b/.prettierignore index dba12af8e1..daa42fbebb 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ *.js .eslintignore +.husky/pre-commit .prettierignore /config /coverage diff --git a/CHANGELOG.md b/CHANGELOG.md index a9d516a2cc..55b42adbe9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Added -- Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 -- [chore] Add `eslint-plugin-package-json` to lint the `package.json` files +- Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 (#3349) +- [chore] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368) ### Updated @@ -22,6 +22,7 @@ _This release is scheduled to be released on 2024-04-01._ - Rework logging colors (#3350) - Update electron to v28 and update other dependencies (#3357) - Update pm2 to v5.3.1 with no allow-ghsas (#3364) +- [chore] Update husky and let lint-staged fix ESLint issues ### Fixed diff --git a/package-lock.json b/package-lock.json index 73e79111fd..e08f44fb4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "eslint-plugin-package-json": "^0.10.1", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", - "husky": "^8.0.3", + "husky": "^9.0.6", "jest": "^29.7.0", "jsdom": "^23.2.0", "lint-staged": "^15.2.0", @@ -5852,15 +5852,15 @@ } }, "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.6.tgz", + "integrity": "sha512-EEuw/rfTiMjOfuL7pGO/i9otg1u36TXxqjIA6D9qxVjd/UXoDOsLor/BSFf5hTK50shwzCU3aVVwdXDp/lp7RA==", "dev": true, "bin": { - "husky": "lib/bin.js" + "husky": "bin.js" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" diff --git a/package.json b/package.json index 860dba45cb..83779166d4 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "lint:js": "eslint . --fix", "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix", "lint:staged": "lint-staged", - "prepare": "[ -f node_modules/.bin/husky ] && husky install || echo no husky installed." + "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed." }, "repository": "MagicMirrorOrg/MagicMirror", "keywords": [ @@ -53,7 +53,7 @@ "eslint-plugin-package-json": "^0.10.1", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", - "husky": "^8.0.3", + "husky": "^9.0.6", "jest": "^29.7.0", "jsdom": "^23.2.0", "lint-staged": "^15.2.0", @@ -88,8 +88,8 @@ }, "lint-staged": { "*": "prettier --write", - "*.js": "eslint", - "*.css": "stylelint" + "*.js": "eslint --fix", + "*.css": "stylelint --fix" }, "_moduleAliases": { "node_helper": "js/node_helper.js", From 57de389e01c74a0990d6c2f24cb979d3e72da527 Mon Sep 17 00:00:00 2001 From: Ross Younger Date: Mon, 29 Jan 2024 19:45:49 +1300 Subject: [PATCH 029/418] [cosmetic] Weather module humidity positioning (#3330) This PR adds an option to tweak the layout of the weather module. When set, the humidity appears alongside the temperature: ![Screenshot from 2024-01-03 11-56-55](https://github.com/MagicMirrorOrg/MagicMirror/assets/551990/2a9fdf9a-21e4-49f5-8a48-68ea21902592) --- CHANGELOG.md | 1 + modules/default/weather/current.njk | 18 ++++++++++++++++-- modules/default/weather/weather.js | 6 +++++- .../modules/weather/currentweather_default.js | 1 + .../modules/weather/currentweather_options.js | 2 +- .../modules/weather/currentweather_units.js | 2 +- tests/e2e/modules/weather_current_spec.js | 10 +++++++--- 7 files changed, 32 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55b42adbe9..f512d28011 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ _This release is scheduled to be released on 2024-04-01._ - Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 (#3349) - [chore] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368) +- weather: `showHumidity` config is now a string describing where to show this element. Supported values: "wind", "temp", "feelslike", "below", "none". (#3330) ### Updated diff --git a/modules/default/weather/current.njk b/modules/default/weather/current.njk index e2fa2f51fb..e7a7e3f1b6 100644 --- a/modules/default/weather/current.njk +++ b/modules/default/weather/current.njk @@ -1,3 +1,8 @@ +{% macro humidity() %} + {% if current.humidity %} + {{ current.humidity | decimalSymbol }}  + {% endif %} +{% endmacro %} {% if current %} {% if not config.onlyTemp %}
@@ -16,8 +21,8 @@ {% endif %} - {% if config.showHumidity and current.humidity %} - {{ current.humidity | decimalSymbol }}  + {% if config.showHumidity === "wind" %} + {{ humidity() }} {% endif %} {% if config.showSun %} @@ -40,6 +45,9 @@
{{ current.temperature | roundValue | unit("temperature") | decimalSymbol }} + {% if config.showHumidity === "temp" %} + {{ humidity() }} + {% endif %}
{% if config.showIndoorTemperature and indoor.temperature %} @@ -59,6 +67,9 @@
{% if config.showFeelsLike %} + {% if config.showHumidity === "feelslike" %} + {{ humidity() }} + {% endif %} {{ "FEELS" | translate({DEGREE: current.feelsLike() | roundValue | unit("temperature") | decimalSymbol }) }}
@@ -76,6 +87,9 @@ {% endif %}
{% endif %} + {% if config.showHumidity === "below" %} + {{ humidity() }} + {% endif %} {% else %}
{{ "LOADING" | translate }}
{% endif %} diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index f4149652df..f692562567 100644 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -14,7 +14,7 @@ Module.register("weather", { updateInterval: 10 * 60 * 1000, // every 10 minutes animationSpeed: 1000, showFeelsLike: true, - showHumidity: false, + showHumidity: "none", // this is now a string; see current.njk showIndoorHumidity: false, showIndoorTemperature: false, allowOverrideNotification: false, @@ -80,6 +80,10 @@ Module.register("weather", { Log.warn("Your are using the deprecated config values 'useBeaufort'. Please switch to windUnits!"); this.windUnits = "beaufort"; } + if (typeof this.config.showHumidity === "boolean") { + Log.warn("[weather] Deprecation warning: Please consider updating showHumidity to the new style (config string)."); + this.config.showHumidity = this.config.showHumidity ? "wind" : "none"; + } // Initialize the weather provider. this.weatherProvider = WeatherProvider.initialize(this.config.weatherProvider, this); diff --git a/tests/configs/modules/weather/currentweather_default.js b/tests/configs/modules/weather/currentweather_default.js index cd02cdecc5..b6601aa378 100644 --- a/tests/configs/modules/weather/currentweather_default.js +++ b/tests/configs/modules/weather/currentweather_default.js @@ -7,6 +7,7 @@ let config = { position: "bottom_bar", config: { location: "Munich", + showHumidity: "feelslike", mockData: '"#####WEATHERDATA#####"' } } diff --git a/tests/configs/modules/weather/currentweather_options.js b/tests/configs/modules/weather/currentweather_options.js index 5ad748e480..f7c2e3f116 100644 --- a/tests/configs/modules/weather/currentweather_options.js +++ b/tests/configs/modules/weather/currentweather_options.js @@ -9,7 +9,7 @@ let config = { windUnits: "beaufort", showWindDirectionAsArrow: true, showSun: false, - showHumidity: true, + showHumidity: "wind", roundTemp: true, degreeLabel: true } diff --git a/tests/configs/modules/weather/currentweather_units.js b/tests/configs/modules/weather/currentweather_units.js index a51bb58ab7..eedbc37de8 100644 --- a/tests/configs/modules/weather/currentweather_units.js +++ b/tests/configs/modules/weather/currentweather_units.js @@ -9,7 +9,7 @@ let config = { location: "Munich", mockData: '"#####WEATHERDATA#####"', decimalSymbol: ",", - showHumidity: true + showHumidity: "wind" } } ] diff --git a/tests/e2e/modules/weather_current_spec.js b/tests/e2e/modules/weather_current_spec.js index cc9ea38f52..ac66873b90 100644 --- a/tests/e2e/modules/weather_current_spec.js +++ b/tests/e2e/modules/weather_current_spec.js @@ -23,7 +23,11 @@ describe("Weather module", () => { }); it("should render feels like temperature", async () => { - await expect(weatherFunc.getText(".weather .normal.medium.feelslike span.dimmed", "Feels like -5.6°")).resolves.toBe(true); + // Template contains   which renders as \xa0 + await expect(weatherFunc.getText(".weather .normal.medium.feelslike span.dimmed", "93.7\xa0 Feels like -5.6°")).resolves.toBe(true); + }); + it("should render humidity next to feels-like", async () => { + await expect(weatherFunc.getText(".weather .normal.medium.feelslike span.dimmed .humidity", "93.7")).resolves.toBe(true); }); }); }); @@ -53,8 +57,8 @@ describe("Weather module", () => { expect(elem.outerHTML).toContain("transform:rotate(250deg)"); }); - it("should render humidity", async () => { - await expect(weatherFunc.getText(".weather .normal.medium span:nth-child(3)", "93.7")).resolves.toBe(true); + it("should render humidity next to wind", async () => { + await expect(weatherFunc.getText(".weather .normal.medium .humidity", "93.7")).resolves.toBe(true); }); it("should render degreeLabel for temp", async () => { From 5fb5ef6cc7e20722a8740ab80ff36eb9b49624b8 Mon Sep 17 00:00:00 2001 From: illimarkangur <116028111+illimarkangur@users.noreply.github.com> Date: Thu, 1 Feb 2024 13:16:55 +0200 Subject: [PATCH 030/418] Improved, fixed and added translations for estonian (#3371) Improved wording, fixed grammatical errors and added new translations to the et.json file. --------- Co-authored-by: Veeck --- CHANGELOG.md | 1 + translations/et.json | 31 ++++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f512d28011..95283e7b9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ _This release is scheduled to be released on 2024-04-01._ - Update electron to v28 and update other dependencies (#3357) - Update pm2 to v5.3.1 with no allow-ghsas (#3364) - [chore] Update husky and let lint-staged fix ESLint issues +- Updated translations for estonian (#3371) ### Fixed diff --git a/translations/et.json b/translations/et.json index 7e60043711..cd3d5ebe7a 100644 --- a/translations/et.json +++ b/translations/et.json @@ -1,16 +1,17 @@ { - "LOADING": "Laen …", + "LOADING": "Laadimine…", "DAYBEFOREYESTERDAY": "Üleeile", "YESTERDAY": "Eile", "TODAY": "Täna", "TOMORROW": "Homme", "DAYAFTERTOMORROW": "Ülehomme", - "RUNNING": "Teoksil", - "EMPTY": "Pole tulevasi sündmuseid.", + "RUNNING": "Lõpeb", + "EMPTY": "Eelolevaid sündmusi pole.", + "WEEK": "Nädal {weekNumber}", "N": "Põhi", - "NNE": "Põhikirre", + "NNE": "Põhjakirre", "NE": "Kirre", "ENE": "Idakirre", "E": "Ida", @@ -26,8 +27,24 @@ "NW": "Loe", "NNW": "Põhjaloe", - "UPDATE_NOTIFICATION": "MagicMirror²´le uuendus saadaval.", + "FEELS": "Tajutav temperatuur {DEGREE}", + "PRECIP_POP": "Sademete tõenäosus", + "PRECIP_AMOUNT": "Sademete hulk", + + "MODULE_CONFIG_CHANGED": "Konfiguratiooni sätted {MODULE_NAME} moodulile on muutunud.\nPalun vaadake dokumentatsiooni.", + "MODULE_CONFIG_ERROR": "Error moodulis {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Ebakorrektne url.", + "MODULE_ERROR_NO_CONNECTION": "Interneti ühendus puudub.", + "MODULE_ERROR_UNAUTHORIZED": "Autoriseerimine ebaõnnestus.", + "MODULE_ERROR_UNSPECIFIED": "Lisateabe saamiseks kontrollige logifaile.", + + "NEWSFEED_NO_ITEMS": "Hetkel ei ole uudiseid.", + + "UPDATE_NOTIFICATION": "MagicMirror²'le on uuendus saadaval.", "UPDATE_NOTIFICATION_MODULE": "Uuendus saadaval {MODULE_NAME} moodulile.", - "UPDATE_INFO_SINGLE": "Praegune paigaldus on {COMMIT_COUNT} commit tagapool {BRANCH_NAME} harul.", - "UPDATE_INFO_MULTIPLE": "Praegune paigaldus on {COMMIT_COUNT} commits tagapool {BRANCH_NAME} harul." + "UPDATE_INFO_SINGLE": "Praegune paigaldus on {COMMIT_COUNT} muudatust tagapool {BRANCH_NAME} harus.", + "UPDATE_INFO_MULTIPLE": "Praegune paigaldus on {COMMIT_COUNT} muudatust tagapool {BRANCH_NAME} harus.", + "UPDATE_NOTIFICATION_DONE": "{MODULE_NAME} moodul uuendati edukalt", + "UPDATE_NOTIFICATION_ERROR": "{MODULE_NAME} mooduli uuendamine ebaõnnestus", + "UPDATE_NOTIFICATION_NEED-RESTART": "Palun taaskäivitage MagicMirror." } From db65cd60eb9b690ad4dd4a019ae022a3743c6f56 Mon Sep 17 00:00:00 2001 From: Veeck Date: Thu, 1 Feb 2024 18:57:18 +0100 Subject: [PATCH 031/418] Bundle all Dependabot updates (#3378) and also node-ical --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 +- package-lock.json | 122 ++++++++++++++++++++-------------------------- package.json | 14 +++--- 3 files changed, 62 insertions(+), 76 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95283e7b9b..1d8fb8dcc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,9 +21,9 @@ _This release is scheduled to be released on 2024-04-01._ - Removing lodash dependency by replacing merge by spread operator (#3339) - Use node prefix for build-in modules (#3340) - Rework logging colors (#3350) -- Update electron to v28 and update other dependencies (#3357) - Update pm2 to v5.3.1 with no allow-ghsas (#3364) - [chore] Update husky and let lint-staged fix ESLint issues +- [chore] Update dependencies including electron to v28 (#3357) and node-ical - Updated translations for estonian (#3371) ### Fixed diff --git a/package-lock.json b/package-lock.json index e08f44fb4c..15a1cf0d1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "ansis": "^2.0.3", + "ansis": "^2.1.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.56.0", @@ -22,7 +22,7 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "^0.17.1", + "node-ical": "^0.17.2", "pm2": "^5.3.1", "socket.io": "^4.7.4", "systeminformation": "^5.21.24" @@ -32,13 +32,13 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.3", "eslint-plugin-jsdoc": "^48.0.4", - "eslint-plugin-package-json": "^0.10.1", + "eslint-plugin-package-json": "^0.10.2", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", - "husky": "^9.0.6", + "husky": "^9.0.7", "jest": "^29.7.0", - "jsdom": "^23.2.0", - "lint-staged": "^15.2.0", + "jsdom": "^24.0.0", + "lint-staged": "^15.2.1", "playwright": "^1.41.1", "prettier": "^3.2.4", "sinon": "^17.0.1", @@ -51,7 +51,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^28.2.0" + "electron": "^28.2.1" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -75,17 +75,6 @@ "node": ">=6.0.0" } }, - "node_modules/@asamuzakjp/dom-selector": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-2.0.2.tgz", - "integrity": "sha512-x1KXOatwofR6ZAYzXRBL5wrdV0vwNxlTCK9NCuLqAzQYARqGcvFwiJA6A1ERuh+dgeA4Dxm3JBYictIes+SqUQ==", - "dev": true, - "dependencies": { - "bidi-js": "^1.0.3", - "css-tree": "^2.3.1", - "is-potential-custom-element-name": "^1.0.1" - } - }, "node_modules/@babel/code-frame": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", @@ -2424,9 +2413,9 @@ } }, "node_modules/ansis": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-2.0.3.tgz", - "integrity": "sha512-tcSGX0mhuDFHsgRrT56xnZ9v2X+TOeKhJ75YopI5OBgyT7tGaG5m6BmeC+6KHjiucfBvUHehQMecHbULIAkFPA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-2.1.0.tgz", + "integrity": "sha512-CBUGwCHnEMODCgAo1G2eAsKC8MxPm9ogOleN2KjSfVinydokX2cyGz+5M83rKEg+A4LKPN2NKX7EQQPSRwZ8Ww==", "engines": { "node": ">=12.13" }, @@ -2648,9 +2637,9 @@ } }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", + "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -2812,15 +2801,6 @@ "node": ">=10.0.0" } }, - "node_modules/bidi-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", - "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", - "dev": true, - "dependencies": { - "require-from-string": "^2.0.2" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3918,9 +3898,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "28.2.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-28.2.0.tgz", - "integrity": "sha512-22SylXQQ9IHtwLw4D+Z4Si7OUpeDtpHfJVTjy3yv53iLg5zJKKPOCWT4ZwgYGHQZ0eldyBrYBHF/P9FPd2CcVQ==", + "version": "28.2.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-28.2.1.tgz", + "integrity": "sha512-wlzXf+OvOiVlBf9dcSeMMf7Q+N6DG+wtgFbMK0sA/JpIJcdosRbLMQwLg/LTwNVKIbmayqFLDp4FmmFkEMhbYA==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -4606,9 +4586,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.10.1.tgz", - "integrity": "sha512-YEiw8Mxjt5UIwefSVW9b7NgkGU6fDFMNm51r3eTrdPMn9hY1ZEYVwrnEAlQ6s57JBk8HBFVhjkyhsQ0KsCf4Pg==", + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.10.2.tgz", + "integrity": "sha512-0NB93dcNEYtAIUa0FNEucwM9qKO27+fSlVrODkxlr0n39dKf0j8nE0w964EkySifVaIYVJN0UcSpbnkIx8D9GA==", "dev": true, "dependencies": { "package-json-validator": "^0.6.3", @@ -5852,9 +5832,9 @@ } }, "node_modules/husky": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.6.tgz", - "integrity": "sha512-EEuw/rfTiMjOfuL7pGO/i9otg1u36TXxqjIA6D9qxVjd/UXoDOsLor/BSFf5hTK50shwzCU3aVVwdXDp/lp7RA==", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.7.tgz", + "integrity": "sha512-vWdusw+y12DUEeoZqW1kplOFqk3tedGV8qlga8/SF6a3lOiWLqGZZQvfWvY0fQYdfiRi/u1DFNpudTSV9l1aCg==", "dev": true, "bin": { "husky": "bin.js" @@ -7009,12 +6989,11 @@ } }, "node_modules/jsdom": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.2.0.tgz", - "integrity": "sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA==", + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.0.0.tgz", + "integrity": "sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==", "dev": true, "dependencies": { - "@asamuzakjp/dom-selector": "^2.0.1", "cssstyle": "^4.0.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", @@ -7023,6 +7002,7 @@ "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.7", "parse5": "^7.1.2", "rrweb-cssom": "^0.6.0", "saxes": "^6.0.0", @@ -7217,9 +7197,9 @@ "dev": true }, "node_modules/lint-staged": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.0.tgz", - "integrity": "sha512-TFZzUEV00f+2YLaVPWBWGAMq7So6yQx+GG8YRMDeOEIf95Zn5RyiLMsEiX4KTNl9vq/w+NqRJkLA1kPIo15ufQ==", + "version": "15.2.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.1.tgz", + "integrity": "sha512-dhwAPnM85VdshybV9FWI/9ghTvMLoQLEXgVMx+ua2DN7mdfzd/tRfoU2yhMcBac0RHkofoxdnnJUokr8s4zKmQ==", "dev": true, "dependencies": { "chalk": "5.3.0", @@ -7227,7 +7207,7 @@ "debug": "4.3.4", "execa": "8.0.1", "lilconfig": "3.0.0", - "listr2": "8.0.0", + "listr2": "8.0.1", "micromatch": "4.0.5", "pidtree": "0.6.0", "string-argv": "0.3.2", @@ -7399,9 +7379,9 @@ } }, "node_modules/listr2": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.0.tgz", - "integrity": "sha512-u8cusxAcyqAiQ2RhYvV7kRKNLgUvtObIbhOX2NCXqvp1UU32xIg5CT22ykS2TPKJXZWJwtK3IKLiqAGlGNE+Zg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", "dev": true, "dependencies": { "cli-truncate": "^4.0.0", @@ -7953,13 +7933,13 @@ "dev": true }, "node_modules/node-ical": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.17.1.tgz", - "integrity": "sha512-2vhc/tzO9rnvok3UtQxqKCAg0N6HfLnQzcfLGIHJotKuqlrcn7aCm8AgpB10m033JpJNng/EXxaQMCKIJycMwQ==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.17.2.tgz", + "integrity": "sha512-pLfxxr4GsTYpzW8Mg4O94tD+GK4xT85jl69dgLDqia9q1IkCOrpPoq+vwLC6Wb+5IevEc+ftYLO7R00GzqOd5Q==", "dependencies": { - "axios": "1.6.2", - "moment-timezone": "^0.5.31", - "rrule": "2.7.1", + "axios": "1.6.3", + "moment-timezone": "^0.5.44", + "rrule": "2.8.1", "uuid": "^9.0.0" } }, @@ -8045,6 +8025,12 @@ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" }, + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -9422,9 +9408,9 @@ } }, "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", "dev": true }, "node_modules/rimraf": { @@ -9459,9 +9445,9 @@ } }, "node_modules/rrule": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.7.1.tgz", - "integrity": "sha512-4p20u/1U7WqR3Nb1hOUrm0u1nSI7sO93ZUVZEZ5HeF6Gr5OlJuyhwEGRvUHq8ZfrPsq5gfa5b9dqnUs/kPqpIw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.8.1.tgz", + "integrity": "sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==", "dependencies": { "tslib": "^2.4.0" } @@ -10140,9 +10126,9 @@ } }, "node_modules/string-width": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", - "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { "emoji-regex": "^10.3.0", diff --git a/package.json b/package.json index 83779166d4..107391889e 100644 --- a/package.json +++ b/package.json @@ -50,13 +50,13 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.3", "eslint-plugin-jsdoc": "^48.0.4", - "eslint-plugin-package-json": "^0.10.1", + "eslint-plugin-package-json": "^0.10.2", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", - "husky": "^9.0.6", + "husky": "^9.0.7", "jest": "^29.7.0", - "jsdom": "^23.2.0", - "lint-staged": "^15.2.0", + "jsdom": "^24.0.0", + "lint-staged": "^15.2.1", "playwright": "^1.41.1", "prettier": "^3.2.4", "sinon": "^17.0.1", @@ -66,10 +66,10 @@ "suncalc": "^1.9.0" }, "optionalDependencies": { - "electron": "^28.2.0" + "electron": "^28.2.1" }, "dependencies": { - "ansis": "^2.0.3", + "ansis": "^2.1.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.56.0", @@ -81,7 +81,7 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "^0.17.1", + "node-ical": "^0.17.2", "pm2": "^5.3.1", "socket.io": "^4.7.4", "systeminformation": "^5.21.24" From 88a96fb529e3adf83212ab4d5aa399824d019428 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:40:12 +0100 Subject: [PATCH 032/418] Bump husky from 9.0.7 to 9.0.10 (#3379) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [husky](https://github.com/typicode/husky) from 9.0.7 to 9.0.10.
Release notes

Sourced from husky's releases.

v9.0.10

v9.0.9

v9.0.8

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=husky&package-manager=npm_and_yarn&previous-version=9.0.7&new-version=9.0.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 15a1cf0d1b..0f21c2d80e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "eslint-plugin-package-json": "^0.10.2", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", - "husky": "^9.0.7", + "husky": "^9.0.10", "jest": "^29.7.0", "jsdom": "^24.0.0", "lint-staged": "^15.2.1", @@ -5832,12 +5832,12 @@ } }, "node_modules/husky": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.7.tgz", - "integrity": "sha512-vWdusw+y12DUEeoZqW1kplOFqk3tedGV8qlga8/SF6a3lOiWLqGZZQvfWvY0fQYdfiRi/u1DFNpudTSV9l1aCg==", + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.10.tgz", + "integrity": "sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA==", "dev": true, "bin": { - "husky": "bin.js" + "husky": "bin.mjs" }, "engines": { "node": ">=18" diff --git a/package.json b/package.json index 107391889e..0ecd076f6c 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "eslint-plugin-package-json": "^0.10.2", "eslint-plugin-unicorn": "^50.0.1", "express-basic-auth": "^1.2.1", - "husky": "^9.0.7", + "husky": "^9.0.10", "jest": "^29.7.0", "jsdom": "^24.0.0", "lint-staged": "^15.2.1", From 08f8a5107a675d5b16b47ad06b4ff6f83541fe83 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Tue, 13 Feb 2024 00:02:02 -0700 Subject: [PATCH 033/418] add error message if config.js appears empty after loading w require() in app.js (#3383) from forum, https://forum.magicmirror.builders/topic/18493/node_helper-js-is-not-working user created own config.js, did not copy the module exports line.. this caused the js/defaults.js list of modules to be processed for node_helpers but the physical config.js to be loaded for the web page (hard coded in index.html) so user modules needing node_helper didn't have that .. this adds a warning message in npm start output to help user resolve.. took two days to debug without message --- CHANGELOG.md | 1 + js/app.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d8fb8dcc9..d14032a9d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ _This release is scheduled to be released on 2024-04-01._ - Ignore all custom css files (#3359) - [newsfeed] Fix newsfeed stall issue introduced by #3336 (#3361) - Changed `log.debug` to `log.log` in `app.js` where logLevel is not set because config is not loaded at this time (#3353) +- added message in case where config.js is missing the module.export line PR #3383 ### Deleted diff --git a/js/app.js b/js/app.js index ec8f42f3dd..77d0dc206f 100644 --- a/js/app.js +++ b/js/app.js @@ -115,6 +115,9 @@ function App () { try { fs.accessSync(configFilename, fs.F_OK); const c = require(configFilename); + if (Object.keys(c).length === 0) { + Log.error("WARNING! Config file appears empty, maybe missing module.exports last line?"); + } checkDeprecatedOptions(c); return Object.assign(defaults, c); } catch (e) { From 73140cdf376a06c0f3e956fd5dd346c2306cc724 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 24 Feb 2024 13:04:43 +0100 Subject: [PATCH 034/418] update electron to v29 and other deps (#3386) --- CHANGELOG.md | 1 + package-lock.json | 1209 +++++++++++++++++++++++--------------- package.json | 30 +- vendor/package-lock.json | 8 +- vendor/package.json | 2 +- 5 files changed, 762 insertions(+), 488 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d14032a9d5..d8353ea0e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ _This release is scheduled to be released on 2024-04-01._ - [chore] Update husky and let lint-staged fix ESLint issues - [chore] Update dependencies including electron to v28 (#3357) and node-ical - Updated translations for estonian (#3371) +- Update electron to v29 and update other dependencies ### Fixed diff --git a/package-lock.json b/package-lock.json index 0f21c2d80e..6cb9ada913 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,12 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "ansis": "^2.1.0", + "ansis": "^2.3.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "express": "^4.18.2", - "express-ipfilter": "^1.3.1", + "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", "html-to-text": "^9.0.5", @@ -25,24 +25,24 @@ "node-ical": "^0.17.2", "pm2": "^5.3.1", "socket.io": "^4.7.4", - "systeminformation": "^5.21.24" + "systeminformation": "^5.22.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.5.4", + "@stylistic/eslint-plugin": "^1.6.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.3", - "eslint-plugin-jsdoc": "^48.0.4", - "eslint-plugin-package-json": "^0.10.2", - "eslint-plugin-unicorn": "^50.0.1", + "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jsdoc": "^48.2.0", + "eslint-plugin-package-json": "^0.10.4", + "eslint-plugin-unicorn": "^51.0.1", "express-basic-auth": "^1.2.1", - "husky": "^9.0.10", + "husky": "^9.0.11", "jest": "^29.7.0", "jsdom": "^24.0.0", - "lint-staged": "^15.2.1", - "playwright": "^1.41.1", - "prettier": "^3.2.4", + "lint-staged": "^15.2.2", + "playwright": "^1.41.2", + "prettier": "^3.2.5", "sinon": "^17.0.1", - "stylelint": "^16.2.0", + "stylelint": "^16.2.1", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0", "suncalc": "^1.9.0" @@ -51,7 +51,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^28.2.1" + "electron": "^29.0.1" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -169,9 +169,9 @@ } }, "node_modules/@babel/core": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", - "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -179,11 +179,11 @@ "@babel/generator": "^7.23.6", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.7", - "@babel/parser": "^7.23.6", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.7", - "@babel/types": "^7.23.6", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -385,14 +385,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", - "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.7", - "@babel/types": "^7.23.6" + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" @@ -484,9 +484,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -673,23 +673,23 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", - "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.23.5", @@ -698,8 +698,8 @@ "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -717,9 +717,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", - "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", @@ -737,9 +737,9 @@ "dev": true }, "node_modules/@csstools/css-parser-algorithms": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.5.0.tgz", - "integrity": "sha512-abypo6m9re3clXA00eu5syw+oaPHbJTPapu9C4pzNsJ4hdZDzushT50Zhu+iIYXgEe1CxnRMn7ngsbV+MLrlpQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.0.tgz", + "integrity": "sha512-YfEHq0eRH98ffb5/EsrrDspVWAuph6gDggAE74ZtjecsmyyWpW768hOyiONa8zwWGbIWYfa2Xp4tRTrpQQ00CQ==", "dev": true, "funding": [ { @@ -778,9 +778,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.7.tgz", - "integrity": "sha512-lHPKJDkPUECsyAvD60joYfDmp8UERYxHGkFfyLJFTVK/ERJe0sVlIFLXU5XFxdjNDTerp5L4KeaKG+Z5S94qxQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.8.tgz", + "integrity": "sha512-DiD3vG5ciNzeuTEoh74S+JMjQDs50R3zlxHnBnfd04YYfA/kh2KiBCGhzqLxlJcNq+7yNQ3stuZZYLX6wK/U2g==", "dev": true, "funding": [ { @@ -796,14 +796,14 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.5.0", + "@csstools/css-parser-algorithms": "^2.6.0", "@csstools/css-tokenizer": "^2.2.3" } }, "node_modules/@csstools/selector-specificity": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.1.tgz", - "integrity": "sha512-NPljRHkq4a14YzZ3YD406uaxh7s0g6eAq3L9aLOWywoqe8PkYamAvtsh7KNX6c++ihDrJ0RiU+/z7rGnhlZ5ww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.2.tgz", + "integrity": "sha512-RpHaZ1h9LE7aALeQXmXrJkRG84ZxIsctEN2biEUmFyKpzFM3zZ35eUMcIzZFsw/2olQE6v69+esEqU2f1MKycg==", "dev": true, "funding": [ { @@ -853,9 +853,9 @@ } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", - "integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==", + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz", + "integrity": "sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==", "dev": true, "dependencies": { "comment-parser": "1.4.1", @@ -931,9 +931,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -1492,9 +1492,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", + "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", @@ -1506,9 +1506,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" @@ -1530,9 +1530,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", - "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz", + "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1694,6 +1694,31 @@ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz", "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==" }, + "node_modules/@pm2/agent/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pm2/agent/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@pm2/agent/node_modules/ws": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", @@ -1714,6 +1739,11 @@ } } }, + "node_modules/@pm2/agent/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/@pm2/io": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@pm2/io/-/io-5.0.2.tgz", @@ -1747,6 +1777,36 @@ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" }, + "node_modules/@pm2/io/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pm2/io/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pm2/io/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/@pm2/js-api": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.8.0.tgz", @@ -1834,9 +1894,9 @@ } }, "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" @@ -1883,15 +1943,16 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.5.4.tgz", - "integrity": "sha512-zWPXr+O67GC9KDAFkbL1U9UVqE6Iv69YMKhkIECCmE0GvClUJwdfsimm4XebEDondV7kfjMrTDZaYfrI5aS0Jg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.6.2.tgz", + "integrity": "sha512-EFnVcKOE5HTiMlVwisL9hHjz8a69yBbJRscWF/z+/vl6M4ew8NVrBlY8ea7KdV8QtyCY4Yapmsbg5ZDfhWlEgg==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.5.4", - "@stylistic/eslint-plugin-jsx": "1.5.4", - "@stylistic/eslint-plugin-plus": "1.5.4", - "@stylistic/eslint-plugin-ts": "1.5.4" + "@stylistic/eslint-plugin-js": "1.6.2", + "@stylistic/eslint-plugin-jsx": "1.6.2", + "@stylistic/eslint-plugin-plus": "1.6.2", + "@stylistic/eslint-plugin-ts": "1.6.2", + "@types/eslint": "^8.56.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1901,11 +1962,12 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.5.4.tgz", - "integrity": "sha512-3ctWb3NvJNV1MsrZN91cYp2EGInLPSoZKphXIbIRx/zjZxKwLDr9z4LMOWtqjq14li/OgqUUcMq5pj8fgbLoTw==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.6.2.tgz", + "integrity": "sha512-ndT6X2KgWGxv8101pdMOxL8pihlYIHcOv3ICd70cgaJ9exwkPn8hJj4YQwslxoAlre1TFHnXd/G1/hYXgDrjIA==", "dev": true, "dependencies": { + "@types/eslint": "^8.56.2", "acorn": "^8.11.3", "escape-string-regexp": "^4.0.0", "eslint-visitor-keys": "^3.4.3", @@ -1919,13 +1981,15 @@ } }, "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.5.4.tgz", - "integrity": "sha512-JUfrpCkeBCqt1IZ4QsP4WgxGza4PhK4LPbc0VnCjHKygl+rgqoDAovqOuzFJ49wJ4Ix3r6OIHFuwiBGswZEVvg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.6.2.tgz", + "integrity": "sha512-hbbouazSJbHD/fshBIOLh9JgtSphKNoTCfHLSNBjAkXLK+GR4i2jhEZZF9P0mtXrNuy2WWInmpq/g0pfWBmSBA==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "^1.5.4", - "estraverse": "^5.3.0" + "@stylistic/eslint-plugin-js": "^1.6.2", + "@types/eslint": "^8.56.2", + "estraverse": "^5.3.0", + "picomatch": "^4.0.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1935,25 +1999,27 @@ } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.5.4.tgz", - "integrity": "sha512-dI0Cs5vYX/0uMhQDY+NK0cKQ0Pe9B6jWYxd0Ndud+mNloDaVLrsmJocK4zn+YfhGEDs1E4Nk5uAPZEumIpDuSg==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.6.2.tgz", + "integrity": "sha512-EDMwa6gzKw4bXRqdIAUvZDfIgwotbjJs8o+vYE22chAYtVAnA0Pcq+cPx0Uk35t2gvJWb5OaLDjqA6oy1tD0jg==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^6.19.0" + "@types/eslint": "^8.56.2", + "@typescript-eslint/utils": "^6.21.0" }, "peerDependencies": { "eslint": "*" } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.5.4.tgz", - "integrity": "sha512-NZDFVIlVNjuPvhT+0Cidm5IS3emtx338xbJTqs2xfOVRDGTpYwRHhNVEGa1rFOpYHmv0sAj6+OXbMDn7ul0K/g==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.6.2.tgz", + "integrity": "sha512-FizV58em0OjO/xFHRIy/LJJVqzxCNmYC/xVtKDf8aGDRgZpLo+lkaBKfBrbMkAGzhBKbYj+iLEFI4WEl6aVZGQ==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.5.4", - "@typescript-eslint/utils": "^6.19.0" + "@stylistic/eslint-plugin-js": "1.6.2", + "@types/eslint": "^8.56.2", + "@typescript-eslint/utils": "^6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2045,6 +2111,22 @@ "@types/node": "*" } }, + "node_modules/@types/eslint": { + "version": "8.56.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.3.tgz", + "integrity": "sha512-PvSf1wfv2wJpVIFUMSb+i4PvqNYkB9Rkp9ZDO3oaWzq4SKhsQk4mrMBr3ZH06I0hKrVGLBacmgl8JM4WVjb9dg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -2122,9 +2204,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.19.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.7.tgz", - "integrity": "sha512-IGRJfoNX10N/PfrReRZ1br/7SQ+2vF/tK3KXNwzXz82D32z5dMQEoOlFew18nLSN+vMNcLY4GrKfzwi/yWI8/w==", + "version": "20.11.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", + "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", "dependencies": { "undici-types": "~5.26.4" } @@ -2145,9 +2227,9 @@ } }, "node_modules/@types/semver": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", - "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", + "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", "dev": true }, "node_modules/@types/stack-utils": { @@ -2181,13 +2263,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", - "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2198,9 +2280,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", - "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2211,13 +2293,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", - "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/visitor-keys": "6.19.1", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2239,17 +2321,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", - "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.1", - "@typescript-eslint/types": "6.19.1", - "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "engines": { @@ -2264,12 +2346,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", - "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2413,9 +2495,9 @@ } }, "node_modules/ansis": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-2.1.0.tgz", - "integrity": "sha512-CBUGwCHnEMODCgAo1G2eAsKC8MxPm9ogOleN2KjSfVinydokX2cyGz+5M83rKEg+A4LKPN2NKX7EQQPSRwZ8Ww==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-2.3.0.tgz", + "integrity": "sha512-ih2ljYHaFnLc8rAHhm0yJmTBtpwT1ULyDrgFZQ2WAbWkikCiBkroPB4qJxTRqh3ocsaOstmg3aDeG+vCfPVtHg==", "engines": { "node": ">=12.13" }, @@ -2436,6 +2518,17 @@ "node": ">= 8" } }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/are-docs-informative": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", @@ -2451,12 +2544,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2495,17 +2591,36 @@ "node": ">=8" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "node_modules/array.prototype.filter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", + "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", + "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -2551,16 +2666,17 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -2626,9 +2742,12 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -2904,9 +3023,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -2923,8 +3042,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -3015,13 +3134,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3045,9 +3169,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001577", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz", - "integrity": "sha512-rs2ZygrG1PNXMfmncM0B5H1hndY5ZCC9b5TkFaVNfZ+AUlyqcMyVIQtc3fsezi0NUCk5XZfDf9WS6WxMxnfdrg==", + "version": "1.0.30001589", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz", + "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==", "dev": true, "funding": [ { @@ -3094,15 +3218,9 @@ "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==" }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -3115,6 +3233,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -3445,12 +3566,12 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/core-js-compat": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", - "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", + "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", "dev": true, "dependencies": { - "browserslist": "^4.22.2" + "browserslist": "^4.22.3" }, "funding": { "type": "opencollective", @@ -3586,9 +3707,9 @@ "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==" }, "node_modules/data-uri-to-buffer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.1.tgz", - "integrity": "sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", "engines": { "node": ">= 14" } @@ -3705,16 +3826,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -3898,14 +4022,14 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "28.2.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-28.2.1.tgz", - "integrity": "sha512-wlzXf+OvOiVlBf9dcSeMMf7Q+N6DG+wtgFbMK0sA/JpIJcdosRbLMQwLg/LTwNVKIbmayqFLDp4FmmFkEMhbYA==", + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-29.0.1.tgz", + "integrity": "sha512-hsQr9clm8NCAMv4uhHlXThHn52UAgrHgyz3ubBAxZIPuUcpKVDtg4HPmx4hbmHIbYICI5OyLN3Ztp7rS+Dn4Lw==", "hasInstallScript": true, "optional": true, "dependencies": { "@electron/get": "^2.0.0", - "@types/node": "^18.11.18", + "@types/node": "^20.9.0", "extract-zip": "^2.0.1" }, "bin": { @@ -3916,9 +4040,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.632", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.632.tgz", - "integrity": "sha512-JGmudTwg7yxMYvR/gWbalqqQiyu7WTFv2Xu3vw4cJHXPFxNgAk0oy8UHaer8nLF4lZJa+rNoj6GsrKIVJTV6Tw==", + "version": "1.4.681", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.681.tgz", + "integrity": "sha512-1PpuqJUFWoXZ1E54m8bsLPVYwIVCRzvaL+n5cjigGga4z854abDnFRc+cTa2th4S79kyGqya/1xoR7h+Y5G5lg==", "dev": true }, "node_modules/emitter-listener": { @@ -3985,9 +4109,9 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", - "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", "engines": { "node": ">=10.0.0" } @@ -4092,49 +4216,51 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", + "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.2", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", + "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.8", "string.prototype.trimend": "^1.0.7", "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", + "typed-array-buffer": "^1.0.1", "typed-array-byte-length": "^1.0.0", "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4143,14 +4269,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", - "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dependencies": { - "get-intrinsic": "^1.2.2", - "has-tostringtag": "^1.0.0", - "hasown": "^2.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -4188,9 +4339,9 @@ "optional": true }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -4233,15 +4384,15 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -4416,9 +4567,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.6.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", - "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", + "version": "27.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", + "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -4427,7 +4578,7 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", "eslint": "^7.0.0 || ^8.0.0", "jest": "*" }, @@ -4563,19 +4714,19 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.0.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.0.4.tgz", - "integrity": "sha512-A0cH+5svWPXzGZszBjXA1t0aAqVGS+/x3i02KFmb73rU0iMLnadEcVWcD/dGBZHIfAMKr3YpWh58f6wn4N909w==", + "version": "48.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.0.tgz", + "integrity": "sha512-O2B1XLBJnUCRkggFzUQ+PBYJDit8iAgXdlu8ucolqGrbmOWPvttZQZX8d1sC0MbqDMSLs8SHSQxaNPRY1RQREg==", "dev": true, "dependencies": { - "@es-joy/jsdoccomment": "~0.41.0", + "@es-joy/jsdoccomment": "~0.42.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "esquery": "^1.5.0", "is-builtin-module": "^3.2.1", - "semver": "^7.5.4", + "semver": "^7.6.0", "spdx-expression-parse": "^4.0.0" }, "engines": { @@ -4586,9 +4737,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.10.2.tgz", - "integrity": "sha512-0NB93dcNEYtAIUa0FNEucwM9qKO27+fSlVrODkxlr0n39dKf0j8nE0w964EkySifVaIYVJN0UcSpbnkIx8D9GA==", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.10.4.tgz", + "integrity": "sha512-dape6w9G7hCXDkoVWoPwrQjUK0V6636qAgUPewduXLH9RdEw/y4XGqCyvD5KujlMBQuagadMkxuGNluW0GC4vQ==", "dev": true, "dependencies": { "package-json-validator": "^0.6.3", @@ -4605,9 +4756,9 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "50.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-50.0.1.tgz", - "integrity": "sha512-KxenCZxqSYW0GWHH18okDlOQcpezcitm5aOSz6EnobyJ6BIByiPDviQRjJIUAjG/tMN11958MxaQ+qCoU6lfDA==", + "version": "51.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz", + "integrity": "sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -4879,11 +5030,11 @@ } }, "node_modules/express-ipfilter": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/express-ipfilter/-/express-ipfilter-1.3.1.tgz", - "integrity": "sha512-9WZC8wGkI6I6ygZNzuZ2MbFJiGoDXs1dM+E8LKtSP13pdgqrnkonWlgvvbxG3YZpa7Haz7Ndum9/J6qkj52OqA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/express-ipfilter/-/express-ipfilter-1.3.2.tgz", + "integrity": "sha512-yMzCWGuVMnR8CFlsIC2spHWoQYp9vtyZXUgS/JdV5GOJgrz6zmKOEZsA4eF1XrxkOIVzaVk6yzTBk65pBhliNw==", "dependencies": { - "ip": "^1.1.8", + "ip": "^2.0.1", "lodash": "^4.17.11", "proxy-addr": "^2.0.7", "range_check": "^2.0.4" @@ -4997,9 +5148,9 @@ } }, "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { "reusify": "^1.0.4" } @@ -5120,9 +5271,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==" + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/follow-redirects": { "version": "1.15.5", @@ -5212,6 +5363,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "optional": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -5303,15 +5455,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5341,12 +5497,13 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -5356,19 +5513,51 @@ } }, "node_modules/get-uri": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.2.tgz", - "integrity": "sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", "dependencies": { "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.0", + "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4", - "fs-extra": "^8.1.0" + "fs-extra": "^11.2.0" }, "engines": { "node": ">= 14" } }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/get-uri/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/get-uri/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/git-hooks-list": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", @@ -5630,20 +5819,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -5663,11 +5852,11 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -5677,9 +5866,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", "dependencies": { "function-bind": "^1.1.2" }, @@ -5786,9 +5975,9 @@ } }, "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -5811,9 +6000,9 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -5832,9 +6021,9 @@ } }, "node_modules/husky": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.10.tgz", - "integrity": "sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, "bin": { "husky": "bin.mjs" @@ -5858,9 +6047,9 @@ } }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "engines": { "node": ">= 4" } @@ -5936,11 +6125,11 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dependencies": { - "get-intrinsic": "^1.2.2", + "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" }, @@ -5949,9 +6138,26 @@ } }, "node_modules/ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, "node_modules/ip6": { "version": "0.2.10", @@ -5970,13 +6176,15 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6117,9 +6325,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "engines": { "node": ">= 0.4" }, @@ -6197,11 +6405,14 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6248,11 +6459,11 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -6292,14 +6503,14 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", "dev": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", "semver": "^7.5.4" }, @@ -6336,9 +6547,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -6873,6 +7084,18 @@ "node": ">=8" } }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/jest-validate": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", @@ -6979,6 +7202,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "node_modules/jsdoc-type-pratt-parser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", @@ -7102,6 +7330,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optional": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -7197,9 +7426,9 @@ "dev": true }, "node_modules/lint-staged": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.1.tgz", - "integrity": "sha512-dhwAPnM85VdshybV9FWI/9ghTvMLoQLEXgVMx+ua2DN7mdfzd/tRfoU2yhMcBac0RHkofoxdnnJUokr8s4zKmQ==", + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", "dev": true, "dependencies": { "chalk": "5.3.0", @@ -7313,9 +7542,9 @@ } }, "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", - "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -7634,9 +7863,9 @@ } }, "node_modules/meow": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.1.0.tgz", - "integrity": "sha512-o5R/R3Tzxq0PJ3v3qcQJtSvSE9nKOLSAaDuuoMzDVuGTwHdccMWcYomh9Xolng2tjT6O/Y83d+0coVGof6tqmA==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", "dev": true, "engines": { "node": ">=18" @@ -7686,6 +7915,18 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -7805,9 +8046,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.44", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz", - "integrity": "sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==", + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", "dependencies": { "moment": "^2.29.4" }, @@ -7905,9 +8146,9 @@ } }, "node_modules/nise": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.7.tgz", - "integrity": "sha512-wWtNUhkT7k58uvWTB/Gy26eA/EJKtPZFVAhEilN5UYVmmGRYOURbejRUyKm0Uu9XVEW7K5nBOZfR8VMB4QR2RQ==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", + "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -8090,15 +8331,16 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", + "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "array.prototype.filter": "^1.0.3", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0" } }, "node_modules/object.values": { @@ -8258,12 +8500,11 @@ } }, "node_modules/pac-resolver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.0.tgz", - "integrity": "sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "dependencies": { "degenerator": "^5.0.0", - "ip": "^1.1.8", "netmask": "^2.0.2" }, "engines": { @@ -8394,9 +8635,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -8437,11 +8678,12 @@ "dev": true }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", + "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", + "dev": true, "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -8544,12 +8786,12 @@ } }, "node_modules/playwright": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.1.tgz", - "integrity": "sha512-gdZAWG97oUnbBdRL3GuBvX3nDDmUOuqzV/D24dytqlKt+eI5KbwusluZRGljx1YoJKZ2NRPaeWiFTeGZO7SosQ==", + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", + "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", "dev": true, "dependencies": { - "playwright-core": "1.41.1" + "playwright-core": "1.41.2" }, "bin": { "playwright": "cli.js" @@ -8562,9 +8804,9 @@ } }, "node_modules/playwright-core": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.1.tgz", - "integrity": "sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg==", + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", + "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -8740,10 +8982,18 @@ "source-map": "^0.6.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "dev": true, "funding": [ { @@ -8828,9 +9078,9 @@ } }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -9219,6 +9469,17 @@ "node": ">=8.10.0" } }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/regexp-tree": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", @@ -9229,13 +9490,14 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -9541,12 +9803,12 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", - "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, "engines": { @@ -9590,9 +9852,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -9708,13 +9970,14 @@ } }, "node_modules/set-function-length": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", - "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", "dependencies": { - "define-data-property": "^1.1.1", + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.1" }, @@ -9723,13 +9986,14 @@ } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -9765,13 +10029,17 @@ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9810,9 +10078,9 @@ } }, "node_modules/sinon/node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" @@ -9888,10 +10156,11 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", "dependencies": { + "debug": "~4.3.4", "ws": "~8.11.0" } }, @@ -9928,15 +10197,15 @@ } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", + "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -9953,11 +10222,6 @@ "node": ">= 14" } }, - "node_modules/socks/node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, "node_modules/sort-object-keys": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", @@ -10048,9 +10312,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -10064,9 +10328,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, "node_modules/sprintf-js": { @@ -10326,9 +10590,9 @@ } }, "node_modules/stylelint": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.2.0.tgz", - "integrity": "sha512-gwqU5AkIb52wrAzzn+359S3NIJDMl02TXLUaV2tzA/L6jUdpTwNt+MCxHlc8+Hb2bUHlYVo92YeSIryF2gJthA==", + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.2.1.tgz", + "integrity": "sha512-SfIMGFK+4n7XVAyv50CpVfcGYWG4v41y6xG7PqOgQSY8M/PgdK0SQbjWFblxjJZlN9jNq879mB4BCZHJRIJ1hA==", "dev": true, "dependencies": { "@csstools/css-parser-algorithms": "^2.5.0", @@ -10664,9 +10928,9 @@ "dev": true }, "node_modules/systeminformation": { - "version": "5.21.24", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.21.24.tgz", - "integrity": "sha512-xQada8ByGGFoRXJaUptGgddn3i7IjtSdqNdCKzB8xkzsM7pHnfLYBWxkPdGzhZ0Z/l+W1yo+aZQZ74d2isj8kw==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.0.tgz", + "integrity": "sha512-oAP80ymt8ssrAzjX8k3frbL7ys6AotqC35oikG6/SG15wBw+tG9nCk4oPaXIhEaAOAZ8XngxUv3ORq2IuR3r4Q==", "os": [ "darwin", "linux", @@ -10884,12 +11148,12 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -11009,27 +11273,28 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -11039,15 +11304,16 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -11057,13 +11323,19 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11118,6 +11390,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "optional": true, "engines": { "node": ">= 4.0.0" } @@ -11374,15 +11647,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index 0ecd076f6c..c460606cd1 100644 --- a/package.json +++ b/package.json @@ -46,35 +46,35 @@ }, "homepage": "https://magicmirror.builders", "devDependencies": { - "@stylistic/eslint-plugin": "^1.5.4", + "@stylistic/eslint-plugin": "^1.6.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.3", - "eslint-plugin-jsdoc": "^48.0.4", - "eslint-plugin-package-json": "^0.10.2", - "eslint-plugin-unicorn": "^50.0.1", + "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jsdoc": "^48.2.0", + "eslint-plugin-package-json": "^0.10.4", + "eslint-plugin-unicorn": "^51.0.1", "express-basic-auth": "^1.2.1", - "husky": "^9.0.10", + "husky": "^9.0.11", "jest": "^29.7.0", "jsdom": "^24.0.0", - "lint-staged": "^15.2.1", - "playwright": "^1.41.1", - "prettier": "^3.2.4", + "lint-staged": "^15.2.2", + "playwright": "^1.41.2", + "prettier": "^3.2.5", "sinon": "^17.0.1", - "stylelint": "^16.2.0", + "stylelint": "^16.2.1", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0", "suncalc": "^1.9.0" }, "optionalDependencies": { - "electron": "^28.2.1" + "electron": "^29.0.1" }, "dependencies": { - "ansis": "^2.1.0", + "ansis": "^2.3.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "express": "^4.18.2", - "express-ipfilter": "^1.3.1", + "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", "html-to-text": "^9.0.5", @@ -84,7 +84,7 @@ "node-ical": "^0.17.2", "pm2": "^5.3.1", "socket.io": "^4.7.4", - "systeminformation": "^5.21.24" + "systeminformation": "^5.22.0" }, "lint-staged": { "*": "prettier --write", diff --git a/vendor/package-lock.json b/vendor/package-lock.json index e5b2476e85..d21806b676 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -12,7 +12,7 @@ "@fortawesome/fontawesome-free": "^6.5.1", "animate.css": "^4.1.1", "moment": "^2.30.1", - "moment-timezone": "^0.5.44", + "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" @@ -59,9 +59,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.44", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz", - "integrity": "sha512-nv3YpzI/8lkQn0U6RkLd+f0W/zy/JnoR5/EyPz/dNkPTBjA2jNLCVxaiQ8QpeLymhSZvX0wCL5s27NQWdOPwAw==", + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", "dependencies": { "moment": "^2.29.4" }, diff --git a/vendor/package.json b/vendor/package.json index 468321d6c2..2fe0d6711e 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -11,7 +11,7 @@ "@fortawesome/fontawesome-free": "^6.5.1", "animate.css": "^4.1.1", "moment": "^2.30.1", - "moment-timezone": "^0.5.44", + "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" From 313531d623083cbdc856fea38d90cb2c0a194015 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 20:04:42 +0100 Subject: [PATCH 035/418] Bump @stylistic/eslint-plugin from 1.6.2 to 1.6.3 (#3391) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@stylistic/eslint-plugin](https://github.com/eslint-stylistic/eslint-stylistic/tree/HEAD/packages/eslint-plugin) from 1.6.2 to 1.6.3.
Release notes

Sourced from @​stylistic/eslint-plugin's releases.

v1.6.3

   🐞 Bug Fixes

    View changes on GitHub
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@stylistic/eslint-plugin&package-manager=npm_and_yarn&previous-version=1.6.2&new-version=1.6.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 50 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6cb9ada913..913e2ecaec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "systeminformation": "^5.22.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.6.2", + "@stylistic/eslint-plugin": "^1.6.3", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsdoc": "^48.2.0", @@ -1943,15 +1943,15 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.6.2.tgz", - "integrity": "sha512-EFnVcKOE5HTiMlVwisL9hHjz8a69yBbJRscWF/z+/vl6M4ew8NVrBlY8ea7KdV8QtyCY4Yapmsbg5ZDfhWlEgg==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.6.3.tgz", + "integrity": "sha512-WDa4FjhImp7YcztRaMG09svhKYYhi2Hc4p9ltQRSqyB4fsUUFm+GKzStqqH7xfjHnxacMJaOnaMGRTUqIIZDLA==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.6.2", - "@stylistic/eslint-plugin-jsx": "1.6.2", - "@stylistic/eslint-plugin-plus": "1.6.2", - "@stylistic/eslint-plugin-ts": "1.6.2", + "@stylistic/eslint-plugin-js": "1.6.3", + "@stylistic/eslint-plugin-jsx": "1.6.3", + "@stylistic/eslint-plugin-plus": "1.6.3", + "@stylistic/eslint-plugin-ts": "1.6.3", "@types/eslint": "^8.56.2" }, "engines": { @@ -1962,9 +1962,9 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.6.2.tgz", - "integrity": "sha512-ndT6X2KgWGxv8101pdMOxL8pihlYIHcOv3ICd70cgaJ9exwkPn8hJj4YQwslxoAlre1TFHnXd/G1/hYXgDrjIA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.6.3.tgz", + "integrity": "sha512-ckdz51oHxD2FaxgY2piJWJVJiwgp8Uu96s+as2yB3RMwavn3nHBrpliVukXY9S/DmMicPRB2+H8nBk23GDG+qA==", "dev": true, "dependencies": { "@types/eslint": "^8.56.2", @@ -1981,12 +1981,12 @@ } }, "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.6.2.tgz", - "integrity": "sha512-hbbouazSJbHD/fshBIOLh9JgtSphKNoTCfHLSNBjAkXLK+GR4i2jhEZZF9P0mtXrNuy2WWInmpq/g0pfWBmSBA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.6.3.tgz", + "integrity": "sha512-SRysCIg59Zvn3dJPqHziiHwuni4NNj1et5stAmivmyQ3Cdp2ULCB7tGxCF1OxpkwRlZQue3ZgdiM7EXfJKaf9w==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "^1.6.2", + "@stylistic/eslint-plugin-js": "^1.6.3", "@types/eslint": "^8.56.2", "estraverse": "^5.3.0", "picomatch": "^4.0.1" @@ -1999,9 +1999,9 @@ } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.6.2.tgz", - "integrity": "sha512-EDMwa6gzKw4bXRqdIAUvZDfIgwotbjJs8o+vYE22chAYtVAnA0Pcq+cPx0Uk35t2gvJWb5OaLDjqA6oy1tD0jg==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.6.3.tgz", + "integrity": "sha512-TuwQOdyVGycDPw5XeF7W4f3ZonAVzOAzORSaD2yGAJ0fRAbJ+l/v3CkKzIAqBBwWkc+c2aRMsWtLP2+viBnmlQ==", "dev": true, "dependencies": { "@types/eslint": "^8.56.2", @@ -2012,12 +2012,12 @@ } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.6.2.tgz", - "integrity": "sha512-FizV58em0OjO/xFHRIy/LJJVqzxCNmYC/xVtKDf8aGDRgZpLo+lkaBKfBrbMkAGzhBKbYj+iLEFI4WEl6aVZGQ==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.6.3.tgz", + "integrity": "sha512-v5GwZsPLblWM9uAIdaSi31Sed3XBWlTFQJ3b5upEmj6QsKYivA5nmIYutwqqL133QdVWjmC86pINlx2Muq3uNQ==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.6.2", + "@stylistic/eslint-plugin-js": "1.6.3", "@types/eslint": "^8.56.2", "@typescript-eslint/utils": "^6.21.0" }, @@ -2112,9 +2112,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.3.tgz", - "integrity": "sha512-PvSf1wfv2wJpVIFUMSb+i4PvqNYkB9Rkp9ZDO3oaWzq4SKhsQk4mrMBr3ZH06I0hKrVGLBacmgl8JM4WVjb9dg==", + "version": "8.56.5", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.5.tgz", + "integrity": "sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==", "dev": true, "dependencies": { "@types/estree": "*", diff --git a/package.json b/package.json index c460606cd1..7f12a7d618 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ }, "homepage": "https://magicmirror.builders", "devDependencies": { - "@stylistic/eslint-plugin": "^1.6.2", + "@stylistic/eslint-plugin": "^1.6.3", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsdoc": "^48.2.0", From 2f2d84bb5c70ae4d3144bf69f17fb8a8da6ed017 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 20:04:56 +0100 Subject: [PATCH 036/418] Bump electron from 29.0.1 to 29.1.0 (#3390) Bumps [electron](https://github.com/electron/electron) from 29.0.1 to 29.1.0.
Release notes

Sourced from electron's releases.

electron v29.1.0

Release Notes for v29.1.0

Features

  • Added proxy configuring support for requests made with net module from utility process. #41416 (Also in 30)

Fixes

  • Ensured ScreenCaptureKit is used exclusively on macOS 14.4 and higher to avoid permission prompts. #41403 (Also in 30)

Other Changes

  • Updated Chromium to 122.0.6261.70. #41446
Commits
  • 2d9c5a6 chore: bump chromium to 122.0.6261.70 (29-x-y) (#41446)
  • 23f690f chore: bump chromium to 122.0.6261.69 (29-x-y) (#41425)
  • 8f4e946 chore: fix import from patches.py in script/lib/git.py (#41437)
  • af47434 feat: add support for configuring system network context proxies (#41416)
  • 8ab99e2 refactor: prefer using base::NoDestructor to `base::{Singleton,LazyInstance...
  • ffcccdc perf: omit unnecessary work from `ElectronRenderFrameObserver::ShouldNotifyCl...
  • ce2ac1c fix: use ScreenCaptureKit exclusively on macOS 14.4 and higher (#41403)
  • 1c3fedd docs: update breaking changes language (#41398)
  • See full diff in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=electron&package-manager=npm_and_yarn&previous-version=29.0.1&new-version=29.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 9 +++++---- package.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 913e2ecaec..c62950eb51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "dependencies": { "ansis": "^2.3.0", "console-stamp": "^3.1.2", + "electron": "^29.1.0", "envsub": "^4.1.0", "eslint": "^8.57.0", "express": "^4.18.2", @@ -51,7 +52,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^29.0.1" + "electron": "^29.1.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -4022,9 +4023,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "29.0.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-29.0.1.tgz", - "integrity": "sha512-hsQr9clm8NCAMv4uhHlXThHn52UAgrHgyz3ubBAxZIPuUcpKVDtg4HPmx4hbmHIbYICI5OyLN3Ztp7rS+Dn4Lw==", + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-29.1.0.tgz", + "integrity": "sha512-giJVIm0sWVp+8V1GXrKqKTb+h7no0P3ooYqEd34AD9wMJzGnAeL+usj+R0155/0pdvvP1mgydnA7lcaFA2M9lw==", "hasInstallScript": true, "optional": true, "dependencies": { diff --git a/package.json b/package.json index 7f12a7d618..5f9404bb18 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "suncalc": "^1.9.0" }, "optionalDependencies": { - "electron": "^29.0.1" + "electron": "^29.1.0" }, "dependencies": { "ansis": "^2.3.0", From c7d94a069e89f4211effe139d8245ddf6fdad94d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 20:05:12 +0100 Subject: [PATCH 037/418] Bump express from 4.18.2 to 4.18.3 (#3389) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.18.3.
Release notes

Sourced from express's releases.

4.18.3

Main Changes

  • Fix routing requests without method
  • deps: body-parser@1.20.2
    • Fix strict json error message on Node.js 19+
    • deps: content-type@~1.0.5
    • deps: raw-body@2.5.2

Other Changes

New Contributors

Full Changelog: https://github.com/expressjs/express/compare/4.18.2...4.18.3

Changelog

Sourced from express's changelog.

4.18.3 / 2024-02-26

  • Fix routing requests without method
  • deps: body-parser@1.20.2
    • Fix strict json error message on Node.js 19+
    • deps: content-type@~1.0.5
    • deps: raw-body@2.5.2
Commits
  • 1b51eda 4.18.3
  • b625132 build: pin Node 21.x to minor
  • e3eca80 build: pin Node 21.x to minor
  • 23b44b3 build: support Node.js 21.6.2
  • b9fea12 build: support Node.js 21.x in appveyor
  • c259c34 build: support Node.js 21.x
  • fdeb1d3 build: support Node.js 20.x in appveyor
  • 734b281 build: support Node.js 20.x
  • 0e3ab6e examples: improve view count in cookie-sessions
  • 59af63a build: Node.js@18.19
  • Additional commits viewable in compare view
Maintainer changes

This version was pushed to npm by ulisesgascon, a new releaser for express since your current version.


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=express&package-manager=npm_and_yarn&previous-version=4.18.2&new-version=4.18.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 26 +++++++++++++------------- package.json | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index c62950eb51..614b22fdb2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "electron": "^29.1.0", "envsub": "^4.1.0", "eslint": "^8.57.0", - "express": "^4.18.2", + "express": "^4.18.3", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", @@ -2951,12 +2951,12 @@ "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==" }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -2964,7 +2964,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -4981,13 +4981,13 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.5.0", @@ -9316,9 +9316,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", diff --git a/package.json b/package.json index 5f9404bb18..b387c064a2 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", - "express": "^4.18.2", + "express": "^4.18.3", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", From e5678f02914965589682907f4046d6b78d5e73ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 20:05:23 +0100 Subject: [PATCH 038/418] Bump playwright from 1.41.2 to 1.42.0 (#3388) Bumps [playwright](https://github.com/microsoft/playwright) from 1.41.2 to 1.42.0.
Release notes

Sourced from playwright's releases.

v1.42.0

New APIs

  • Test tags

    New tag syntax for adding tags to the tests (@-tokens in the test title are still supported).

    test('test customer login', { tag: ['@fast',
    '@login'] }, async ({ page }) => {
      // ...
    });
    

    Use --grep command line option to run only tests with certain tags.

    npx playwright test --grep @fast
    
  • Annotating skipped tests

    New annotation syntax for test annotations allows annotating the tests that do not run.

    test('test full report', {
      annotation: [
    { type: 'issue', description:
    'https://github.com/microsoft/playwright/issues/23180' },
    { type: 'docs', description:
    'https://playwright.dev/docs/test-annotations#tag-tests' },
      ],
    }, async ({ page }) => {
      // ...
    });
    
  • page.addLocatorHandler()

    New method page.addLocatorHandler() registers a callback that will be invoked when specified element becomes visible and may block Playwright actions. The callback can get rid of the overlay. Here is an example that closes a cookie dialog when it appears.

    // Setup the handler.
    await page.addLocatorHandler(
    page.getByRole('heading', { name: 'Hej! You are in control of your
    cookies.' }),
        async () => {
          await page.getByRole('button', { name: 'Accept all' }).click();
        });
    // Write the test as usual.
    await page.goto('https://www.ikea.com/');
    await page.getByRole('link', { name: 'Collection of blue and white'
    }).click();
    await expect(page.getByRole('heading', { name: 'Light and easy'
    })).toBeVisible();
    

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=playwright&package-manager=npm_and_yarn&previous-version=1.41.2&new-version=1.42.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 614b22fdb2..f908b249c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,7 @@ "jest": "^29.7.0", "jsdom": "^24.0.0", "lint-staged": "^15.2.2", - "playwright": "^1.41.2", + "playwright": "^1.42.0", "prettier": "^3.2.5", "sinon": "^17.0.1", "stylelint": "^16.2.1", @@ -8787,12 +8787,12 @@ } }, "node_modules/playwright": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", - "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0.tgz", + "integrity": "sha512-Ko7YRUgj5xBHbntrgt4EIw/nE//XBHOKVKnBjO1KuZkmkhlbgyggTe5s9hjqQ1LpN+Xg+kHsQyt5Pa0Bw5XpvQ==", "dev": true, "dependencies": { - "playwright-core": "1.41.2" + "playwright-core": "1.42.0" }, "bin": { "playwright": "cli.js" @@ -8805,9 +8805,9 @@ } }, "node_modules/playwright-core": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", - "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0.tgz", + "integrity": "sha512-0HD9y8qEVlcbsAjdpBaFjmaTHf+1FeIddy8VJLeiqwhcNqGCBe4Wp2e8knpqiYbzxtxarxiXyNDw2cG8sCaNMQ==", "dev": true, "bin": { "playwright-core": "cli.js" diff --git a/package.json b/package.json index b387c064a2..a75fee43ce 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "jest": "^29.7.0", "jsdom": "^24.0.0", "lint-staged": "^15.2.2", - "playwright": "^1.41.2", + "playwright": "^1.42.0", "prettier": "^3.2.5", "sinon": "^17.0.1", "stylelint": "^16.2.1", From 90ff3402cbf653ab90b6e97afbcda3877a27eddb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 20:05:37 +0100 Subject: [PATCH 039/418] Bump node-ical from 0.17.2 to 0.18.0 (#3387) Bumps [node-ical](https://github.com/jens-maus/node-ical) from 0.17.2 to 0.18.0.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=node-ical&package-manager=npm_and_yarn&previous-version=0.17.2&new-version=0.18.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index f908b249c8..ae35c66422 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "^0.17.2", + "node-ical": "^0.18.0", "pm2": "^5.3.1", "socket.io": "^4.7.4", "systeminformation": "^5.22.0" @@ -2757,11 +2757,11 @@ } }, "node_modules/axios": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", - "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -8175,11 +8175,11 @@ "dev": true }, "node_modules/node-ical": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.17.2.tgz", - "integrity": "sha512-pLfxxr4GsTYpzW8Mg4O94tD+GK4xT85jl69dgLDqia9q1IkCOrpPoq+vwLC6Wb+5IevEc+ftYLO7R00GzqOd5Q==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.18.0.tgz", + "integrity": "sha512-FrOUPztjw9OUgSB9o/ffhl86BiVClQTut97C2NqCwKIgOAcKPEw5UQMuSuNJO/Y4hqTyJdKZh2TCqNHQnE9YFg==", "dependencies": { - "axios": "1.6.3", + "axios": "1.6.7", "moment-timezone": "^0.5.44", "rrule": "2.8.1", "uuid": "^9.0.0" diff --git a/package.json b/package.json index a75fee43ce..a823b3ecd9 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "^0.17.2", + "node-ical": "^0.18.0", "pm2": "^5.3.1", "socket.io": "^4.7.4", "systeminformation": "^5.22.0" From 1a745cfb9275eee070dc36e3caf098ec786b4892 Mon Sep 17 00:00:00 2001 From: jkriegshauser Date: Wed, 13 Mar 2024 12:59:21 -0700 Subject: [PATCH 040/418] Fix issue 3393 (#3395) Fix for #3393 --- CHANGELOG.md | 1 + .../default/calendar/calendarfetcherutils.js | 6 ++++ tests/configs/modules/calendar/rrule_until.js | 30 +++++++++++++++++++ tests/electron/modules/calendar_spec.js | 16 ++++++++++ tests/mocks/rrule_until.ics | 24 +++++++++++++++ 5 files changed, 77 insertions(+) create mode 100644 tests/configs/modules/calendar/rrule_until.js create mode 100644 tests/mocks/rrule_until.ics diff --git a/CHANGELOG.md b/CHANGELOG.md index d8353ea0e3..1bb0524901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ _This release is scheduled to be released on 2024-04-01._ - [newsfeed] Fix newsfeed stall issue introduced by #3336 (#3361) - Changed `log.debug` to `log.log` in `app.js` where logLevel is not set because config is not loaded at this time (#3353) - added message in case where config.js is missing the module.export line PR #3383 +- Fixed an issue where recurring events could extend past their recurrence end date (#3393) ### Deleted diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index 4be451eb51..eec3540f29 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -311,6 +311,12 @@ const CalendarFetcherUtils = { arr[index] = new Date(date.valueOf() + oneDayInMs); } }); + // Adjusting the dates could push it beyond the 'until' date, so filter those out here. + if (rule.options.until !== null) { + dates = dates.filter((date) => { + return date.valueOf() <= rule.options.until.valueOf(); + }); + } } // The dates array from rrule can be confused by DST. If the event was created during DST and we diff --git a/tests/configs/modules/calendar/rrule_until.js b/tests/configs/modules/calendar/rrule_until.js new file mode 100644 index 0000000000..e553ebd194 --- /dev/null +++ b/tests/configs/modules/calendar/rrule_until.js @@ -0,0 +1,30 @@ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + hideDuplicates: false, + maximumEntries: 100, + calendars: [ + { + maximumEntries: 100, + maximumNumberOfDays: 1, // Just today + url: "http://localhost:8080/tests/mocks/rrule_until.ics" + } + ] + } + } + ] +}; + +Date.now = () => { + return new Date("07 Mar 2024 10:38:00 GMT-07:00").valueOf(); +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 3dcbd36f68..4e6aee17a2 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -44,6 +44,22 @@ describe("Calendar module", () => { }); }); + /****************************/ + // RRULE TESTS: + // Add any tests that check rrule functionality here. + describe("rrule", () => { + it("Issue #3393 recurrence dates past rrule until date", async () => { + await helpers.startApplication("tests/configs/modules/calendar/rrule_until.js", "07 Mar 2024 10:38:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + const cnt = await loc.count(); + expect(cnt).toBe(1); + }); + }); + /****************************/ // LOS ANGELES TESTS: // In 2023, DST (GMT-7) was until 5 Nov, after which is standard (STD) (GMT-8) time. diff --git a/tests/mocks/rrule_until.ics b/tests/mocks/rrule_until.ics new file mode 100644 index 0000000000..cdb34e26e8 --- /dev/null +++ b/tests/mocks/rrule_until.ics @@ -0,0 +1,24 @@ +BEGIN:VEVENT +DTSTART;TZID=America/Los_Angeles:20240229T160000 +DTEND;TZID=America/Los_Angeles:20240229T190000 +RRULE:FREQ=WEEKLY;WKST=MO;UNTIL=20240307T075959Z;BYDAY=TH +DTSTAMP:20240307T180618Z +CREATED:20231231T000501Z +LAST-MODIFIED:20231231T005623Z +SEQUENCE:2 +STATUS:CONFIRMED +SUMMARY:My event +TRANSP:OPAQUE +END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=America/Los_Angeles:20240307T160000 +DTEND;TZID=America/Los_Angeles:20240307T190000 +RRULE:FREQ=WEEKLY;WKST=MO;UNTIL=20240316T065959Z;BYDAY=TH +DTSTAMP:20240307T180618Z +CREATED:20231231T000501Z +LAST-MODIFIED:20231231T005623Z +SEQUENCE:3 +STATUS:CONFIRMED +SUMMARY:My event +TRANSP:OPAQUE +END:VEVENT \ No newline at end of file From 16af809559c9a57c6cc5c9059a9f062ed70a0f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Sat, 16 Mar 2024 13:06:27 +0100 Subject: [PATCH 041/418] Update .npmrc (#3399) Don't display `npm WARN <....>` on install Only Error will be displayed --- .npmrc | 1 + CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.npmrc b/.npmrc index 386ea9aec8..7d713a90a1 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1,3 @@ engine-strict=true audit=false +loglevel="error" diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bb0524901..37c7ef5cae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ _This release is scheduled to be released on 2024-04-01._ - Changed `log.debug` to `log.log` in `app.js` where logLevel is not set because config is not loaded at this time (#3353) - added message in case where config.js is missing the module.export line PR #3383 - Fixed an issue where recurring events could extend past their recurrence end date (#3393) +- Don't display any `npm WARN <....>` on install (#3399) ### Deleted From c5f90501ef9e5c7d2eedb504769b0d59264eb7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Thu, 21 Mar 2024 13:43:04 +0100 Subject: [PATCH 042/418] [calendar] deny fetch interval < 60000 and set 60000 in this case (prevent fetch loop failed) (#3382) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi, I had the case of some users who set a very small fetchinterval (10 sec for example) in some cases, it may be that the request did not have time to complete correctly and that the next one has already been sent (generally on start of MM²) I think that lock min fetchInterval to 60000 is a good idea --- CHANGELOG.md | 1 + modules/default/calendar/node_helper.js | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37c7ef5cae..8e1196592f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ _This release is scheduled to be released on 2024-04-01._ - Ignore all custom css files (#3359) - [newsfeed] Fix newsfeed stall issue introduced by #3336 (#3361) - Changed `log.debug` to `log.log` in `app.js` where logLevel is not set because config is not loaded at this time (#3353) +- [calandar] deny fetch interval < 60000 and set 60000 in this case (prevent fetch loop failed) (#3382) - added message in case where config.js is missing the module.export line PR #3383 - Fixed an issue where recurring events could extend past their recurrence end date (#3393) - Don't display any `npm WARN <....>` on install (#3399) diff --git a/modules/default/calendar/node_helper.js b/modules/default/calendar/node_helper.js index e485926099..7901abf099 100644 --- a/modules/default/calendar/node_helper.js +++ b/modules/default/calendar/node_helper.js @@ -47,9 +47,14 @@ module.exports = NodeHelper.create({ } let fetcher; + let fetchIntervalCorrected; if (typeof this.fetchers[identifier + url] === "undefined") { - Log.log(`Create new calendarfetcher for url: ${url} - Interval: ${fetchInterval}`); - fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, selfSignedCert); + if (fetchInterval < 60000) { + Log.warn(`fetchInterval for url ${url} must be >= 60000`); + fetchIntervalCorrected = 60000; + } + Log.log(`Create new calendarfetcher for url: ${url} - Interval: ${fetchIntervalCorrected || fetchInterval}`); + fetcher = new CalendarFetcher(url, fetchIntervalCorrected || fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, selfSignedCert); fetcher.onReceive((fetcher) => { this.broadcastEvents(fetcher, identifier); From d970214a0e438bbcfcfcfcd17b4c2457af51a83b Mon Sep 17 00:00:00 2001 From: vppencilsharpener Date: Thu, 21 Mar 2024 09:11:23 -0400 Subject: [PATCH 043/418] Fix for #3345 - precipitation probability not displayed when it is 0% (#3346) Fixes issue #3345. I think I submitted this correctly, but don't do this often so let me know if anything needs to be corrected. --------- Co-authored-by: Veeck --- CHANGELOG.md | 1 + modules/default/weather/weather.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e1196592f..2134e2b465 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ _This release is scheduled to be released on 2024-04-01._ - Worked around several issues in the RRULE library that were causing deleted calender events to still show, some initial and recurring events to not show, and some event times to be off an hour. (#3291) - Skip changelog requirement when running tests for dependency updates (#3320) +- Display precipitation probability when it is 0% instead of blank/empty (#3345) - [newsfeed] Suppress unsightly animation cases when there are 0 or 1 active news items (#3336) - [newsfeed] Always compute the feed item URL using the same helper function (#3336) - Ignore all custom css files (#3359) diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index f692562567..224aba0647 100644 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -233,7 +233,7 @@ Module.register("weather", { } } } else if (type === "precip") { - if (value === null || isNaN(value) || value === 0 || value.toFixed(2) === "0.00") { + if (value === null || isNaN(value)) { formattedValue = ""; } else { formattedValue = WeatherUtils.convertPrecipitationUnit(value, valueUnit, this.config.units); From 6de578edb30c534a2ac715f0ebdc74f470358934 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Fri, 22 Mar 2024 11:49:40 -0700 Subject: [PATCH 044/418] move suncalc dependency out of dev, as it is used by the clock module (#3401) user reported problem with clock module, checking code found dependency on suncalc library, but it is not loaded in production mode.. move dependency --------- Co-authored-by: veeck --- CHANGELOG.md | 1 + fonts/package-lock.json | 16 ++--- fonts/package.json | 4 +- package-lock.json | 128 ++++++++++++++++++++-------------------- package.json | 18 +++--- 5 files changed, 83 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2134e2b465..2df1540c8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ _This release is scheduled to be released on 2024-04-01._ - added message in case where config.js is missing the module.export line PR #3383 - Fixed an issue where recurring events could extend past their recurrence end date (#3393) - Don't display any `npm WARN <....>` on install (#3399) +- Fixed move suncalc dependency to production from dev, as it is used by clock module ### Deleted diff --git a/fonts/package-lock.json b/fonts/package-lock.json index fb2f9ebad3..09ee878124 100644 --- a/fonts/package-lock.json +++ b/fonts/package-lock.json @@ -9,19 +9,19 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.0.8", - "@fontsource/roboto-condensed": "^5.0.14" + "@fontsource/roboto": "^5.0.12", + "@fontsource/roboto-condensed": "^5.0.15" } }, "node_modules/@fontsource/roboto": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.8.tgz", - "integrity": "sha512-XxPltXs5R31D6UZeLIV1td3wTXU3jzd3f2DLsXI8tytMGBkIsGcc9sIyiupRtA8y73HAhuSCeweOoBqf6DbWCA==" + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.12.tgz", + "integrity": "sha512-x0o17jvgoSSbS9OZnUX2+xJmVRvVCfeaYJjkS7w62iN7CuJWtMf5vJj8LqgC7ibqIkitOHVW+XssRjgrcHn62g==" }, "node_modules/@fontsource/roboto-condensed": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.14.tgz", - "integrity": "sha512-ZNBHUhE5/3z9efMIjpBblFsfLHgGotJjlzKd5Q8DODbkRRWy6Yh+JnbiaJZ8zwQyHyYBNOolk57BG4BcjSzrRg==" + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.15.tgz", + "integrity": "sha512-0AFvcI/8JQ5+FZE12hdaE1W/1ooJUzd5XP7jD74+SP+PArsswJ+6OV/oKTasgeQeZlvGrcD3chO6yr5K4JGwzA==" } } } diff --git a/fonts/package.json b/fonts/package.json index 3b5714d166..9c166c60ca 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -8,7 +8,7 @@ "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" }, "dependencies": { - "@fontsource/roboto": "^5.0.8", - "@fontsource/roboto-condensed": "^5.0.14" + "@fontsource/roboto": "^5.0.12", + "@fontsource/roboto-condensed": "^5.0.15" } } diff --git a/package-lock.json b/package-lock.json index ae35c66422..bf9bf5a48b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,9 @@ "dependencies": { "ansis": "^2.3.0", "console-stamp": "^3.1.2", - "electron": "^29.1.0", "envsub": "^4.1.0", "eslint": "^8.57.0", - "express": "^4.18.3", + "express": "^4.19.1", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", @@ -25,14 +24,15 @@ "moment": "^2.30.1", "node-ical": "^0.18.0", "pm2": "^5.3.1", - "socket.io": "^4.7.4", - "systeminformation": "^5.22.0" + "socket.io": "^4.7.5", + "suncalc": "^1.9.0", + "systeminformation": "^5.22.6" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.6.3", + "@stylistic/eslint-plugin": "^1.7.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-jsdoc": "^48.2.0", + "eslint-plugin-jsdoc": "^48.2.1", "eslint-plugin-package-json": "^0.10.4", "eslint-plugin-unicorn": "^51.0.1", "express-basic-auth": "^1.2.1", @@ -40,19 +40,18 @@ "jest": "^29.7.0", "jsdom": "^24.0.0", "lint-staged": "^15.2.2", - "playwright": "^1.42.0", + "playwright": "^1.42.1", "prettier": "^3.2.5", "sinon": "^17.0.1", "stylelint": "^16.2.1", "stylelint-config-standard": "^36.0.0", - "stylelint-prettier": "^5.0.0", - "suncalc": "^1.9.0" + "stylelint-prettier": "^5.0.0" }, "engines": { "node": ">=18" }, "optionalDependencies": { - "electron": "^29.1.0" + "electron": "^29.1.5" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -1944,15 +1943,15 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.6.3.tgz", - "integrity": "sha512-WDa4FjhImp7YcztRaMG09svhKYYhi2Hc4p9ltQRSqyB4fsUUFm+GKzStqqH7xfjHnxacMJaOnaMGRTUqIIZDLA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.7.0.tgz", + "integrity": "sha512-ThMUjGIi/jeWYNvOdjZkoLw1EOVs0tEuKXDgWvTn8uWaEz55HuPlajKxjKLpv19C+qRDbKczJfzUODfCdME53A==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.6.3", - "@stylistic/eslint-plugin-jsx": "1.6.3", - "@stylistic/eslint-plugin-plus": "1.6.3", - "@stylistic/eslint-plugin-ts": "1.6.3", + "@stylistic/eslint-plugin-js": "1.7.0", + "@stylistic/eslint-plugin-jsx": "1.7.0", + "@stylistic/eslint-plugin-plus": "1.7.0", + "@stylistic/eslint-plugin-ts": "1.7.0", "@types/eslint": "^8.56.2" }, "engines": { @@ -1963,9 +1962,9 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.6.3.tgz", - "integrity": "sha512-ckdz51oHxD2FaxgY2piJWJVJiwgp8Uu96s+as2yB3RMwavn3nHBrpliVukXY9S/DmMicPRB2+H8nBk23GDG+qA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.7.0.tgz", + "integrity": "sha512-PN6On/+or63FGnhhMKSQfYcWutRlzOiYlVdLM6yN7lquoBTqUJHYnl4TA4MHwiAt46X5gRxDr1+xPZ1lOLcL+Q==", "dev": true, "dependencies": { "@types/eslint": "^8.56.2", @@ -1982,12 +1981,12 @@ } }, "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.6.3.tgz", - "integrity": "sha512-SRysCIg59Zvn3dJPqHziiHwuni4NNj1et5stAmivmyQ3Cdp2ULCB7tGxCF1OxpkwRlZQue3ZgdiM7EXfJKaf9w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.7.0.tgz", + "integrity": "sha512-BACdBwXakQvjYIST5N2WWhRbvhRsIxa/F59BiZol+0IH4FSmDXhie7v/yaxDIIA9CbfElzOmIA5nWNYTVXcnwQ==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "^1.6.3", + "@stylistic/eslint-plugin-js": "^1.7.0", "@types/eslint": "^8.56.2", "estraverse": "^5.3.0", "picomatch": "^4.0.1" @@ -2000,9 +1999,9 @@ } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.6.3.tgz", - "integrity": "sha512-TuwQOdyVGycDPw5XeF7W4f3ZonAVzOAzORSaD2yGAJ0fRAbJ+l/v3CkKzIAqBBwWkc+c2aRMsWtLP2+viBnmlQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.7.0.tgz", + "integrity": "sha512-AabDw8sXsc70Ydx3qnbeTlRHZnIwY6UKEenBPURPhY3bfYWX+/pDpZH40HkOu94v8D0DUrocPkeeEUxl4e0JDg==", "dev": true, "dependencies": { "@types/eslint": "^8.56.2", @@ -2013,12 +2012,12 @@ } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.6.3.tgz", - "integrity": "sha512-v5GwZsPLblWM9uAIdaSi31Sed3XBWlTFQJ3b5upEmj6QsKYivA5nmIYutwqqL133QdVWjmC86pINlx2Muq3uNQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.7.0.tgz", + "integrity": "sha512-QsHv98mmW1xaucVYQTyLDgEpybPJ/6jPPxVBrIchntWWwj74xCWKUiw79hu+TpYj/Pbhd9rkqJYLNq3pQGYuyA==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.6.3", + "@stylistic/eslint-plugin-js": "1.7.0", "@types/eslint": "^8.56.2", "@typescript-eslint/utils": "^6.21.0" }, @@ -2113,9 +2112,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.5.tgz", - "integrity": "sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==", + "version": "8.56.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.6.tgz", + "integrity": "sha512-ymwc+qb1XkjT/gfoQwxIeHZ6ixH23A+tCT2ADSA/DPVKzAjwYkTXBMCQ/f6fe4wEa85Lhp26VPeUxI7wMhAi7A==", "dev": true, "dependencies": { "@types/estree": "*", @@ -3554,9 +3553,9 @@ "dev": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -4023,9 +4022,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-29.1.0.tgz", - "integrity": "sha512-giJVIm0sWVp+8V1GXrKqKTb+h7no0P3ooYqEd34AD9wMJzGnAeL+usj+R0155/0pdvvP1mgydnA7lcaFA2M9lw==", + "version": "29.1.5", + "resolved": "https://registry.npmjs.org/electron/-/electron-29.1.5.tgz", + "integrity": "sha512-1uWGRw/ffA62lcrklxGUgVxVtOHojsg/nwsYr+/F9cVjipZJn8iPv/ABGIIexhmUqWcho8BqfTJ4osCBa29gBg==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -4715,9 +4714,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.0.tgz", - "integrity": "sha512-O2B1XLBJnUCRkggFzUQ+PBYJDit8iAgXdlu8ucolqGrbmOWPvttZQZX8d1sC0MbqDMSLs8SHSQxaNPRY1RQREg==", + "version": "48.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.1.tgz", + "integrity": "sha512-iUvbcyDZSO/9xSuRv2HQBw++8VkV/pt3UWtX9cpPH0l7GKPq78QC/6+PmyQHHvNZaTjAce6QVciEbnc6J/zH5g==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.42.0", @@ -4981,16 +4980,16 @@ } }, "node_modules/express": { - "version": "4.18.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", - "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.1.tgz", + "integrity": "sha512-K4w1/Bp7y8iSiVObmCrtq8Cs79XjJc/RU2YYkZQ7wpUu5ZyZ7MtPHkqoMz4pf+mgXfNvo2qft8D9OnrH2ABk9w==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -8787,12 +8786,12 @@ } }, "node_modules/playwright": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0.tgz", - "integrity": "sha512-Ko7YRUgj5xBHbntrgt4EIw/nE//XBHOKVKnBjO1KuZkmkhlbgyggTe5s9hjqQ1LpN+Xg+kHsQyt5Pa0Bw5XpvQ==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", + "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==", "dev": true, "dependencies": { - "playwright-core": "1.42.0" + "playwright-core": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -8805,9 +8804,9 @@ } }, "node_modules/playwright-core": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0.tgz", - "integrity": "sha512-0HD9y8qEVlcbsAjdpBaFjmaTHf+1FeIddy8VJLeiqwhcNqGCBe4Wp2e8knpqiYbzxtxarxiXyNDw2cG8sCaNMQ==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz", + "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -10140,9 +10139,9 @@ } }, "node_modules/socket.io": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz", - "integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -10878,8 +10877,7 @@ "node_modules/suncalc": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/suncalc/-/suncalc-1.9.0.tgz", - "integrity": "sha512-vMJ8Byp1uIPoj+wb9c1AdK4jpkSKVAywgHX0lqY7zt6+EWRRC3Z+0Ucfjy/0yxTVO1hwwchZe4uoFNqrIC24+A==", - "dev": true + "integrity": "sha512-vMJ8Byp1uIPoj+wb9c1AdK4jpkSKVAywgHX0lqY7zt6+EWRRC3Z+0Ucfjy/0yxTVO1hwwchZe4uoFNqrIC24+A==" }, "node_modules/supports-color": { "version": "7.2.0", @@ -10929,9 +10927,9 @@ "dev": true }, "node_modules/systeminformation": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.0.tgz", - "integrity": "sha512-oAP80ymt8ssrAzjX8k3frbL7ys6AotqC35oikG6/SG15wBw+tG9nCk4oPaXIhEaAOAZ8XngxUv3ORq2IuR3r4Q==", + "version": "5.22.6", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.6.tgz", + "integrity": "sha512-hUTQX+bRgIFbv1T/z251NtwGwNIeSyWURnT2BGnsYu6dQNbkiBl4oAwk50acVfITFq1Zvb8KDNgibQK9uGlUGg==", "os": [ "darwin", "linux", @@ -11149,9 +11147,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { "node": ">=16" diff --git a/package.json b/package.json index a823b3ecd9..2e22c476b1 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,10 @@ }, "homepage": "https://magicmirror.builders", "devDependencies": { - "@stylistic/eslint-plugin": "^1.6.3", + "@stylistic/eslint-plugin": "^1.7.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-jsdoc": "^48.2.0", + "eslint-plugin-jsdoc": "^48.2.1", "eslint-plugin-package-json": "^0.10.4", "eslint-plugin-unicorn": "^51.0.1", "express-basic-auth": "^1.2.1", @@ -57,23 +57,22 @@ "jest": "^29.7.0", "jsdom": "^24.0.0", "lint-staged": "^15.2.2", - "playwright": "^1.42.0", + "playwright": "^1.42.1", "prettier": "^3.2.5", "sinon": "^17.0.1", "stylelint": "^16.2.1", "stylelint-config-standard": "^36.0.0", - "stylelint-prettier": "^5.0.0", - "suncalc": "^1.9.0" + "stylelint-prettier": "^5.0.0" }, "optionalDependencies": { - "electron": "^29.1.0" + "electron": "^29.1.5" }, "dependencies": { "ansis": "^2.3.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", - "express": "^4.18.3", + "express": "^4.19.1", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", @@ -83,8 +82,9 @@ "moment": "^2.30.1", "node-ical": "^0.18.0", "pm2": "^5.3.1", - "socket.io": "^4.7.4", - "systeminformation": "^5.22.0" + "socket.io": "^4.7.5", + "suncalc": "^1.9.0", + "systeminformation": "^5.22.6" }, "lint-staged": { "*": "prettier --write", From 52cfbacd4d2aee5c055745b06c0815e5790152ae Mon Sep 17 00:00:00 2001 From: Paranoid93 <6515818+Paranoid93@users.noreply.github.com> Date: Sat, 23 Mar 2024 10:53:42 +0100 Subject: [PATCH 045/418] Changes the layout of the current weather module, targetting indoor values (#3397) Hi, this PR should change the layout of the indoor values in the current_weather module. Since the Indoor values are being passed into the module via a notification, I sadly do not know exactly how to write a test for this. Can you link me an example or tell me, how I can mock indoor values into this test? Before: ![grafik](https://github.com/MagicMirrorOrg/MagicMirror/assets/6515818/b1b2afcc-0a35-48c3-9cf8-3e7b041c7727) After: ![grafik](https://github.com/MagicMirrorOrg/MagicMirror/assets/6515818/311d3051-45e9-450d-afd5-c90a4d4ffd63) --- CHANGELOG.md | 1 + modules/default/weather/current.njk | 42 +++++++++++++---------- tests/e2e/modules/weather_current_spec.js | 6 ++-- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2df1540c8c..fdee404917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ _This release is scheduled to be released on 2024-04-01._ - [chore] Update dependencies including electron to v28 (#3357) and node-ical - Updated translations for estonian (#3371) - Update electron to v29 and update other dependencies +- Updated layout of current weather indoor values ### Fixed diff --git a/modules/default/weather/current.njk b/modules/default/weather/current.njk index e7a7e3f1b6..d19848954e 100644 --- a/modules/default/weather/current.njk +++ b/modules/default/weather/current.njk @@ -12,8 +12,7 @@ {% if config.showWindDirection %} {% if config.showWindDirectionAsArrow %} - + {% else %} {{ current.cardinalWindDirection() | translate }} {% endif %} @@ -42,27 +41,32 @@ {% endif %}
{% endif %} -
- - {{ current.temperature | roundValue | unit("temperature") | decimalSymbol }} +
+ {% if config.showIndoorTemperature and indoor.temperature or config.showIndoorHumidity and indoor.humidity %} + + + {% if config.showIndoorTemperature and indoor.temperature %} + + + {{ indoor.temperature | roundValue | unit("temperature") | decimalSymbol }} + + + {% endif %} + {% if config.showIndoorHumidity and indoor.humidity %} + + + {{ indoor.humidity | roundValue | unit("humidity") | decimalSymbol }} + + + {% endif %} + + {% endif %} + + {{ current.temperature | roundValue | unit("temperature") | decimalSymbol }} {% if config.showHumidity === "temp" %} {{ humidity() }} {% endif %}
-
- {% if config.showIndoorTemperature and indoor.temperature %} -
- - {{ indoor.temperature | roundValue | unit("temperature") | decimalSymbol }} -
- {% endif %} - {% if config.showIndoorHumidity and indoor.humidity %} -
- - {{ indoor.humidity | roundValue | unit("humidity") | decimalSymbol }} -
- {% endif %} -
{% if (config.showFeelsLike or config.showPrecipitationAmount or config.showPrecipitationProbability) and not config.onlyTemp %}
{% if config.showFeelsLike %} diff --git a/tests/e2e/modules/weather_current_spec.js b/tests/e2e/modules/weather_current_spec.js index ac66873b90..d24ea1b133 100644 --- a/tests/e2e/modules/weather_current_spec.js +++ b/tests/e2e/modules/weather_current_spec.js @@ -19,7 +19,7 @@ describe("Weather module", () => { }); it("should render temperature with icon", async () => { - await expect(weatherFunc.getText(".weather .large.light span.bright", "1.5°")).resolves.toBe(true); + await expect(weatherFunc.getText(".weather .large span.light.bright", "1.5°")).resolves.toBe(true); }); it("should render feels like temperature", async () => { @@ -62,7 +62,7 @@ describe("Weather module", () => { }); it("should render degreeLabel for temp", async () => { - await expect(weatherFunc.getText(".weather .large.light span.bright", "1°C")).resolves.toBe(true); + await expect(weatherFunc.getText(".weather .large span.bright.light", "1°C")).resolves.toBe(true); }); it("should render degreeLabel for feels like", async () => { @@ -80,7 +80,7 @@ describe("Weather module", () => { }); it("should render temperatures in fahrenheit", async () => { - await expect(weatherFunc.getText(".weather .large.light span.bright", "34,7°")).resolves.toBe(true); + await expect(weatherFunc.getText(".weather .large span.bright.light", "34,7°")).resolves.toBe(true); }); it("should render 'feels like' in fahrenheit", async () => { From 57549fa19ccd096c1800fb8446e37627b44bb6b5 Mon Sep 17 00:00:00 2001 From: Veeck Date: Sat, 23 Mar 2024 12:16:57 +0100 Subject: [PATCH 046/418] Fix compliments module bringing mirror to a halt (#3402) ... when no compliments are to be displayed. We shouldnt even try to randomize when the array has no elements... Fixes #3385 --- CHANGELOG.md | 9 +++++---- modules/default/compliments/compliments.js | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdee404917..5d08638958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,11 +40,12 @@ _This release is scheduled to be released on 2024-04-01._ - Ignore all custom css files (#3359) - [newsfeed] Fix newsfeed stall issue introduced by #3336 (#3361) - Changed `log.debug` to `log.log` in `app.js` where logLevel is not set because config is not loaded at this time (#3353) -- [calandar] deny fetch interval < 60000 and set 60000 in this case (prevent fetch loop failed) (#3382) +- [calendar] deny fetch interval < 60000 and set 60000 in this case (prevent fetch loop failed) (#3382) - added message in case where config.js is missing the module.export line PR #3383 - Fixed an issue where recurring events could extend past their recurrence end date (#3393) - Don't display any `npm WARN <....>` on install (#3399) - Fixed move suncalc dependency to production from dev, as it is used by clock module +- [compliments] Fix mirror not responding anymore when no compliments are to be shown (#3385) ### Deleted @@ -94,7 +95,7 @@ This release also marks the latest release by Michael Teeuw. For more info, plea - Fix #3256 filter out bad results from rrule.between - Fix calendar events sometimes not respecting deleted events (#3250) - Fix electron loadurl locally on Windows when address "0.0.0.0" (#2550) -- Fix updatanotification (update_helper.js): catch error if reponse is not an JSON format (check PM2) +- Fix updatanotification (update_helper.js): catch error if response is not an JSON format (check PM2) - Fix missing typeof in calendar module - Fix style issues after prettier update - Fix calendar test (#3291) by moving "Exdate check" from e2e to electron to run on a Thursday @@ -169,8 +170,8 @@ Special thanks to @khassel, @rejas and @sdetweil for taking over most (if not al - Added tests for serveronly - Set Timezone `Europe/Berlin` in unit tests (needed for new formatTime tests) - Added no-param-reassign eslint rule and fix warnings -- updatenotification: Added `sendUpdatesNotifications` feature. Broadcast update with `UPDATES` notification to other modules -- updatenotification: allow force scanning with `SCAN_UPDATES` notification from other modules +- [updatenotification] Added `sendUpdatesNotifications` feature. Broadcast update with `UPDATES` notification to other modules +- [updatenotification] Allow force scanning with `SCAN_UPDATES` notification from other modules - Added per-calendar fetchInterval ### Removed diff --git a/modules/default/compliments/compliments.js b/modules/default/compliments/compliments.js index 10e54afd40..39e6c34d49 100644 --- a/modules/default/compliments/compliments.js +++ b/modules/default/compliments/compliments.js @@ -50,7 +50,7 @@ Module.register("compliments", { * @returns {number} a random index of given array */ randomIndex (compliments) { - if (compliments.length === 1) { + if (compliments.length <= 1) { return 0; } From be63e365bd011108d8f25d6df975f157cb87204b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Wed, 27 Mar 2024 22:45:01 +0100 Subject: [PATCH 047/418] Add electron-rebuild to suite test (#3392) because actually i'm not able to rebuild any libraries to works with electron v29.x I write a suite test to check `electron-rebuild` Note: works with [v28.x](https://github.com/MagicMirrorOrg/MagicMirror/actions/runs/8122468177/job/22201931385) --- .github/workflows/electronRebuild.yaml | 20 ++++++++++++++++++++ CHANGELOG.md | 1 + 2 files changed, 21 insertions(+) create mode 100644 .github/workflows/electronRebuild.yaml diff --git a/.github/workflows/electronRebuild.yaml b/.github/workflows/electronRebuild.yaml new file mode 100644 index 0000000000..5c6e3f7db3 --- /dev/null +++ b/.github/workflows/electronRebuild.yaml @@ -0,0 +1,20 @@ +name: "Electron Rebuild Testing" + +on: [pull_request] + +jobs: + rebuild: + name: Run electron-rebuild + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Install MagicMirror + run: npm run install-mm + - name: Install @electron/rebuild + run: npm install @electron/rebuild + - name: Install some test library to be rebuilded + run: npm install onoff node-pty drivelist + - name: Run electron-rebuild + run: npx electron-rebuild + continue-on-error: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d08638958..455c1b5ab5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ _This release is scheduled to be released on 2024-04-01._ - Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 (#3349) - [chore] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368) - weather: `showHumidity` config is now a string describing where to show this element. Supported values: "wind", "temp", "feelslike", "below", "none". (#3330) +- electron-rebuild test suite for electron and 3rd party modules compatibility (#3392) ### Updated From fd44445ec30988f2708fd1be928112ccbdc7a6f6 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 27 Mar 2024 23:13:01 +0100 Subject: [PATCH 048/418] update deps and package.json's (eslint) (#3406) --- CHANGELOG.md | 2 +- fonts/package.json | 5 +- package-lock.json | 1260 ++++++++++++++++--------------------------- package.json | 13 +- vendor/package.json | 5 +- 5 files changed, 491 insertions(+), 794 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 455c1b5ab5..1b924f09aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ _This release is scheduled to be released on 2024-04-01._ - Rework logging colors (#3350) - Update pm2 to v5.3.1 with no allow-ghsas (#3364) - [chore] Update husky and let lint-staged fix ESLint issues -- [chore] Update dependencies including electron to v28 (#3357) and node-ical +- [chore] Update dependencies including electron to v29 (#3357) and node-ical - Updated translations for estonian (#3371) - Update electron to v29 and update other dependencies - Updated layout of current weather indoor values diff --git a/fonts/package.json b/fonts/package.json index 9c166c60ca..da67752914 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -2,7 +2,10 @@ "name": "magicmirror-fonts", "version": "1.0.0", "description": "Package for fonts use by MagicMirror² core.", - "repository": "MagicMirrorOrg/MagicMirror", + "repository": { + "type": "git", + "url": "https://github.com/MagicMirrorOrg/MagicMirror" + }, "license": "MIT", "bugs": { "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" diff --git a/package-lock.json b/package-lock.json index bf9bf5a48b..08d66d8f0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", - "express": "^4.19.1", + "express": "^4.19.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", @@ -33,7 +33,7 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsdoc": "^48.2.1", - "eslint-plugin-package-json": "^0.10.4", + "eslint-plugin-package-json": "^0.12.0", "eslint-plugin-unicorn": "^51.0.1", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", @@ -43,7 +43,7 @@ "playwright": "^1.42.1", "prettier": "^3.2.5", "sinon": "^17.0.1", - "stylelint": "^16.2.1", + "stylelint": "^16.3.1", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0" }, @@ -51,7 +51,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^29.1.5" + "electron": "^29.1.6" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -63,127 +63,56 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -208,14 +137,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -294,12 +223,12 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -325,9 +254,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -358,9 +287,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -385,28 +314,29 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", "dev": true, "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -484,9 +414,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -556,12 +486,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", - "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -658,12 +588,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -673,33 +603,33 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -717,9 +647,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", @@ -737,9 +667,9 @@ "dev": true }, "node_modules/@csstools/css-parser-algorithms": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.0.tgz", - "integrity": "sha512-YfEHq0eRH98ffb5/EsrrDspVWAuph6gDggAE74ZtjecsmyyWpW768hOyiONa8zwWGbIWYfa2Xp4tRTrpQQ00CQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz", + "integrity": "sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==", "dev": true, "funding": [ { @@ -755,13 +685,13 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^2.2.3" + "@csstools/css-tokenizer": "^2.2.4" } }, "node_modules/@csstools/css-tokenizer": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.3.tgz", - "integrity": "sha512-pp//EvZ9dUmGuGtG1p+n17gTHEOqu9jO+FiCUjNN3BDmyhdA2Jq9QsVeR7K8/2QCK17HSsioPlTW9ZkzoWb3Lg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz", + "integrity": "sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==", "dev": true, "funding": [ { @@ -778,9 +708,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.8.tgz", - "integrity": "sha512-DiD3vG5ciNzeuTEoh74S+JMjQDs50R3zlxHnBnfd04YYfA/kh2KiBCGhzqLxlJcNq+7yNQ3stuZZYLX6wK/U2g==", + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz", + "integrity": "sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==", "dev": true, "funding": [ { @@ -796,8 +726,8 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.6.0", - "@csstools/css-tokenizer": "^2.2.3" + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4" } }, "node_modules/@csstools/selector-specificity": { @@ -822,6 +752,16 @@ "postcss-selector-parser": "^6.0.13" } }, + "node_modules/@dual-bundle/import-meta-resolve": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", + "integrity": "sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/@electron/get": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", @@ -843,6 +783,29 @@ "global-agent": "^3.0.0" } }, + "node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "optional": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@electron/get/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optional": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/@electron/get/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -852,6 +815,15 @@ "semver": "bin/semver.js" } }, + "node_modules/@electron/get/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "optional": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/@es-joy/jsdoccomment": { "version": "0.42.0", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz", @@ -988,102 +960,6 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1492,14 +1368,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz", - "integrity": "sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -1515,9 +1391,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" @@ -1530,9 +1406,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz", - "integrity": "sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1647,16 +1523,6 @@ "uuid": "bin/uuid" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@pm2/agent": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.3.tgz", @@ -2204,9 +2070,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", - "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", "dependencies": { "undici-types": "~5.26.4" } @@ -2227,9 +2093,9 @@ } }, "node_modules/@types/semver": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/stack-utils": { @@ -2564,15 +2430,16 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -2591,35 +2458,17 @@ "node": ">=8" } }, - "node_modules/array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", - "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", + "es-abstract": "^1.23.2", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" }, "engines": { @@ -2913,19 +2762,22 @@ "dev": true }, "node_modules/basic-ftp": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.4.tgz", - "integrity": "sha512-8PzkB0arJFV4jJWSGOYR+OEic6aeKMu/osRhBULN6RY0ykby6LKhbmuQ5ublvaas5BOwboah5D87nrHyuh8PPA==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", "engines": { "node": ">=10.0.0" } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/blessed": { @@ -3133,6 +2985,21 @@ "node": ">=8" } }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -3169,9 +3036,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001589", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz", - "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==", + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", "dev": true, "funding": [ { @@ -3566,12 +3433,12 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/core-js-compat": { - "version": "3.36.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", - "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", + "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", "dev": true, "dependencies": { - "browserslist": "^4.22.3" + "browserslist": "^4.23.0" }, "funding": { "type": "opencollective", @@ -3727,6 +3594,54 @@ "node": ">=18" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/dateformat": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", @@ -4010,21 +3925,15 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "29.1.5", - "resolved": "https://registry.npmjs.org/electron/-/electron-29.1.5.tgz", - "integrity": "sha512-1uWGRw/ffA62lcrklxGUgVxVtOHojsg/nwsYr+/F9cVjipZJn8iPv/ABGIIexhmUqWcho8BqfTJ4osCBa29gBg==", + "version": "29.1.6", + "resolved": "https://registry.npmjs.org/electron/-/electron-29.1.6.tgz", + "integrity": "sha512-UIYfpHR9gRBFKHyejHuXUVQ7nNzZRnoPVOHlijkvqR+DSLwgJ2ZcVVt0LNduNeO8PhPkY1+6kHonL52OTC1cOw==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -4040,9 +3949,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.681", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.681.tgz", - "integrity": "sha512-1PpuqJUFWoXZ1E54m8bsLPVYwIVCRzvaL+n5cjigGga4z854abDnFRc+cTa2th4S79kyGqya/1xoR7h+Y5G5lg==", + "version": "1.4.718", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.718.tgz", + "integrity": "sha512-6FpOapKxHuRNUoNQEP54sAacMod/XX68/Oaau+UoTEC8yxy5lR8jAvTlyrb60oZ9OtuUuAEtKvCQOJm6S4MtBQ==", "dev": true }, "node_modules/emitter-listener": { @@ -4216,17 +4125,21 @@ } }, "node_modules/es-abstract": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.4.tgz", - "integrity": "sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg==", + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.6", + "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", @@ -4234,15 +4147,16 @@ "globalthis": "^1.0.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.1", + "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", @@ -4250,17 +4164,17 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", + "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.1", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -4269,12 +4183,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -4294,6 +4202,17 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", @@ -4458,9 +4377,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -4737,9 +4656,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.10.4.tgz", - "integrity": "sha512-dape6w9G7hCXDkoVWoPwrQjUK0V6636qAgUPewduXLH9RdEw/y4XGqCyvD5KujlMBQuagadMkxuGNluW0GC4vQ==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.12.0.tgz", + "integrity": "sha512-BtzhiA/7x7hqY+0fLXcgiN8wXGFyABJS93q/gns6MsAAPrbGFH3N7MYuCrNUEP60NPHQ4kAW04sPQarQBvJqHg==", "dev": true, "dependencies": { "package-json-validator": "^0.6.3", @@ -4942,18 +4861,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -4980,9 +4887,9 @@ } }, "node_modules/express": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.1.tgz", - "integrity": "sha512-K4w1/Bp7y8iSiVObmCrtq8Cs79XjJc/RU2YYkZQ7wpUu5ZyZ7MtPHkqoMz4pf+mgXfNvo2qft8D9OnrH2ABk9w==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -5076,6 +4983,21 @@ "@types/yauzl": "^2.9.1" } }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/extrareqp2": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz", @@ -5276,9 +5198,9 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -5302,34 +5224,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -5360,17 +5254,16 @@ } }, "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "optional": true, + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dependencies": { "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=14.14" } }, "node_modules/fs.realpath": { @@ -5482,15 +5375,12 @@ } }, "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5526,38 +5416,6 @@ "node": ">= 14" } }, - "node_modules/get-uri/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/get-uri/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/get-uri/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/git-hooks-list": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", @@ -5866,9 +5724,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -6270,6 +6128,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -6559,24 +6431,6 @@ "node": ">=8" } }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -7327,10 +7181,12 @@ } }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optional": true, + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -7368,9 +7224,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", - "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz", + "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", "dev": true }, "node_modules/lazy": { @@ -7688,13 +7544,10 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", - "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", "dev": true, - "dependencies": { - "type-fest": "^3.0.0" - }, "engines": { "node": ">=14.16" }, @@ -7772,18 +7625,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/log-update/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -8007,15 +7848,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -8314,14 +8146,15 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -8331,27 +8164,28 @@ } }, "node_modules/object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "dependencies": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -8618,31 +8452,6 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -8991,9 +8800,9 @@ } }, "node_modules/postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { @@ -9012,7 +8821,7 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -9051,9 +8860,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -9228,9 +9037,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -9767,12 +9576,12 @@ ] }, "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -9970,16 +9779,16 @@ } }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10029,11 +9838,11 @@ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -10273,9 +10082,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -10406,36 +10215,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width-cjs": { - "name": "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, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width-cjs/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, - "engines": { - "node": ">=8" - } - }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -10464,32 +10243,39 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", - "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "regexp.prototype.flags": "^1.5.0", - "set-function-name": "^2.0.0", - "side-channel": "^1.0.4" + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -10499,26 +10285,29 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10535,19 +10324,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "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, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -10590,15 +10366,16 @@ } }, "node_modules/stylelint": { - "version": "16.2.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.2.1.tgz", - "integrity": "sha512-SfIMGFK+4n7XVAyv50CpVfcGYWG4v41y6xG7PqOgQSY8M/PgdK0SQbjWFblxjJZlN9jNq879mB4BCZHJRIJ1hA==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.3.1.tgz", + "integrity": "sha512-/JOwQnBvxEKOT2RtNgGpBVXnCSMBgKOL2k7w0K52htwCyJls4+cHvc4YZgXlVoAZS9QJd2DgYAiRnja96pTgxw==", "dev": true, "dependencies": { - "@csstools/css-parser-algorithms": "^2.5.0", - "@csstools/css-tokenizer": "^2.2.3", - "@csstools/media-query-list-parser": "^2.1.7", - "@csstools/selector-specificity": "^3.0.1", + "@csstools/css-parser-algorithms": "^2.6.1", + "@csstools/css-tokenizer": "^2.2.4", + "@csstools/media-query-list-parser": "^2.1.9", + "@csstools/selector-specificity": "^3.0.2", + "@dual-bundle/import-meta-resolve": "^4.0.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", @@ -10612,19 +10389,19 @@ "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", - "ignore": "^5.3.0", + "ignore": "^5.3.1", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.29.0", + "known-css-properties": "^0.30.0", "mathml-tag-names": "^2.1.3", - "meow": "^13.1.0", + "meow": "^13.2.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.33", + "postcss": "^8.4.38", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^7.0.0", - "postcss-selector-parser": "^6.0.15", + "postcss-selector-parser": "^6.0.16", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", @@ -10713,41 +10490,18 @@ } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.0.tgz", - "integrity": "sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.4", - "rimraf": "^5.0.5" + "keyv": "^4.5.4" }, "engines": { "node": ">=16" } }, - "node_modules/stylelint/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/stylelint/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", @@ -10766,24 +10520,6 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/stylelint/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -10952,9 +10688,9 @@ } }, "node_modules/table": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", - "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", + "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "dev": true, "dependencies": { "ajv": "^8.0.1", @@ -11322,9 +11058,9 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -11341,9 +11077,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "dev": true, "peer": true, "bin": { @@ -11386,12 +11122,11 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "optional": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { @@ -11646,15 +11381,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11685,53 +11420,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi-cjs/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/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, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", diff --git a/package.json b/package.json index 2e22c476b1..65b745df8b 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,10 @@ "lint:staged": "lint-staged", "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed." }, - "repository": "MagicMirrorOrg/MagicMirror", + "repository": { + "type": "git", + "url": "https://github.com/MagicMirrorOrg/MagicMirror" + }, "keywords": [ "magic mirror", "magicmirror", @@ -50,7 +53,7 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsdoc": "^48.2.1", - "eslint-plugin-package-json": "^0.10.4", + "eslint-plugin-package-json": "^0.12.0", "eslint-plugin-unicorn": "^51.0.1", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", @@ -60,19 +63,19 @@ "playwright": "^1.42.1", "prettier": "^3.2.5", "sinon": "^17.0.1", - "stylelint": "^16.2.1", + "stylelint": "^16.3.1", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0" }, "optionalDependencies": { - "electron": "^29.1.5" + "electron": "^29.1.6" }, "dependencies": { "ansis": "^2.3.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", - "express": "^4.19.1", + "express": "^4.19.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", diff --git a/vendor/package.json b/vendor/package.json index 2fe0d6711e..4758f9498e 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -2,7 +2,10 @@ "name": "magicmirror-vendors", "version": "1.0.0", "description": "Package for vendors use by MagicMirror² core.", - "repository": "MagicMirrorOrg/MagicMirror", + "repository": { + "type": "git", + "url": "https://github.com/MagicMirrorOrg/MagicMirror" + }, "license": "MIT", "bugs": { "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" From d9926fad79e761e8a9d0d2d1060bbf80012615fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Thu, 28 Mar 2024 12:37:18 +0100 Subject: [PATCH 049/418] =?UTF-8?q?MM=C2=B2=20Icon=20(#3407)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create `MM²` icon * Allow to change default electron icon to this icon --- CHANGELOG.md | 1 + js/electron.js | 1 + mm2.png | Bin 0 -> 6947 bytes 3 files changed, 2 insertions(+) create mode 100644 mm2.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b924f09aa..709d6bc95b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ _This release is scheduled to be released on 2024-04-01._ - [chore] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368) - weather: `showHumidity` config is now a string describing where to show this element. Supported values: "wind", "temp", "feelslike", "below", "none". (#3330) - electron-rebuild test suite for electron and 3rd party modules compatibility (#3392) +- Create MM² icon and attach it to electron process (#3407) ### Updated diff --git a/js/electron.js b/js/electron.js index 7eae34c544..2dfde6728a 100644 --- a/js/electron.js +++ b/js/electron.js @@ -40,6 +40,7 @@ function createWindow () { let electronOptionsDefaults = { width: electronSize.width, height: electronSize.height, + icon: "mm2.png", x: 0, y: 0, darkTheme: true, diff --git a/mm2.png b/mm2.png new file mode 100644 index 0000000000000000000000000000000000000000..5be0b24be20b833c9f3cde48161f11d774cfda10 GIT binary patch literal 6947 zcmeHKdpy(o|DR|?H>JYJOq4XcZ!Dv-p)&WP63zCR#%8lkL!2DCP+2kZZ3}V zH1#zh5XiiZPE-#FLoWc0RRWWIcx|d zygkv~y`U1VF*UBUS50lT(BRe|X2a0o3I63`9!b&H6py~gsJ#C1L+S51FmIQeK1e^! zik8+A;|q8$CCZF4<@7Lq)X=rO${4!h5peFokHf!dKdYgn^lh_C=t|em?w@LEr&Y}M zk4t*F(tTBu4Y_%#daRR`&hwhgtP9~cI$DcXKE9H%`CjoF)6_c_C$@!Fp4vEXtn;Q@ zVGiZIf-?)3d44Xvbo0{KWldQglOCK$vop?{>9C_HdR@|r#Tknht$P(WvBdk2yQL2X z(wdgNZ@BTh(YteDeUDH3?FG5m&#||6+h}k9rF5|1wCLj$r@QM6?)iJ(SiMAjZM?X~ zE&WwC;%4h=ovaNPmTV70m%PzR!LLACN@Ig7DvsT|6n8{cFux!cKB4mTRnNIWgy{#A z`StkMJ;g@DLzJN|l?^%d__o;d18C)1AAuVK3U^wWre|M^0k&G;#dp;rskFt@&Cu zI99IbSfz15VPnN6by@aBZC7naFM3{-aqqRdh$FJC1%(eO@3i8qqk%Io@pqkeX>U$~ zZ&*Li^rSoO+T z-3@Hfa1PjtK6Ga?lh3ncu=oLhWjId&_9z5mV;3%9FoOXxJOBvfgisK}w{9cg92N!P zO`xOc0()RL$0ct*N-F(ZSS)+~gbt)@*l83f<~Vg@{%#|;sY!zqXvTrzmA6r&LE z8540Z1>r+?gWL0k032_Lw?rdp;ha5KgsmprM#y55J*W7dX)<4?x5Z6EXqX z9w0<)@+}05`PE+#CgjeP!(yTUF2Dm#MPO9S-$FWWq`Q6fP*M=c;R$BEK(ha4Ddw>M zBI|FtDK#_Ye47a9{uTFc)?aF$F$S&ZbTXCC3{$4JkxD@*uE3iSa*uRXn0zwhkiAqci+7gGK(I}UN z3>E_t%TV?y2rwfDYa!bU0fv|_^y2fm6ofJ*xYF~hnhuT=iy>xE8DangMPu<~G>(k5 z^1@)qSnxx#Kx4@0Z|wOj4m;xivQ`cc+~(7gJ8?u{{D>LRr-||eLOQmJ*$pUH0VE8G z#v%Vn80vGuDCM56dyGDqOFO$32xEmnS2ASr3Opio`Bkxo+|R5j3C0_%9G^)o2a6VrUe z_I#f5R1TRrECMXJgd^S!R~{C#WAkC_S!GWe`MiZm=Hayckx`?^~p$!0qD(&Bv^d_dCT%O7mYkNzp%UAZMH>I z<+y9qq+kB~8yaBnf4=(euKb_{8D-q=K1O3reMrWz4=Erq3q)rUYEH#F2m3|p98Zrg zO{jUOE2`u|)&*m`sjQ}+Od}f01hK%Dt}at?YS=w=rRjSADnwgVGLo$d8K$#WAW%iz z(b_o7z;c;NjK9N}J=Kh04y;7%>#*C0S$Z7x@NCsi{rPOwq=Sl5r*{+e?$iugUoGLo zweI0O#AsR7FXct%7tyeoiNt}2DV65x!3z&K_D*(+8z*L6gk%#_3QsP88d3X>i4q;C zmAWG2M@k|Y@L~id&sztLl9`QU+|j4^RzG|w*kiiy#xK40pqza%_i|^+TfE)C&8HKy zWGXdBQh#Eu^}oM>J7?=w7dZwNQ@U!i?t%=v-Yb2N)IfdS{*+C%K8eG$Q*YhJ3!jdG z7IRmZJ^P05hos3r;4bf`iv5*DVRR9ZZgq zQrsUl6gN5dA5n3^I}Xh86AUJ+dz)7K+2d0qhPkc zB73!jM_g>-@!(vNW+SFS?ENt0P091rop6t5og+;9Y9~+m)4q|b>DV|zD%WHps3gs4 z+Rx^s$Dr<(OB~sUOABPR*0FhSRB6>w9`bXDR+}3U-Q{L~K4wK8&)ph%mbpA?JUwU< zpZe;>G&P4r&dm%8>F+hToXxxRyqR0I6`w8XJj-l%!2LX0n6lQWOlY|y#qPK9Ur`y6JZ1MZ@E=3!mAS)PV% zuVcLQxUT#{c2v7QlW1%Aa@Olo$Kf;hM+31&#^m{xq<6&w_k-WzPb!XHi8mLW50_&` zhvTJl28+9g0};XnlqF_yr*B!UEcOGu~_|qN2y6r zd9!GZKNLiHUAfz#D2fd9zQ;)XYaKira&;@N+DzTv4<+Yj^`b6SafT)*Mhfc9@-+&M zb{*1?tXfx%7oVK|VIQi0ZIGDk(p;jjDQMe4Q}g!;6(w{HtLs!B2Uij7nmuW`LDn1i zOxK+*FYZ5oeQ{u@JmC)nt$HHtvR*l-#i28-uoa`%|rWiub`f7ove1q+f968#3GY?@Q zD?B!LXZAgviW4CP`=zf3eQ=q%vbPyoD`C9Hu+3_&MJ0>K4tY$4mApb%w5&bB@2x?F zzm6m&FX_}4hv7btd1UCBpt>p!l{&xZJk_6z@88a6j}`kFdEf8P%`S>Es#y7BHyz)! z_r#^jS< zpcT3**>y$gq(=E-8ZOr^CEnjCcTgPV z)U1740+T=6zA4K@Et8868%@&gY@NHd-)!5UM(r7TQZ#RI_odl}O&B{_lf#J0o*gZn z2Qp!$!z=D-%`r4S$jZ5L`n|NL;MPdile!-FJ8g@}8y>N9xK%A3&2xb_>~-3P#&=jb z7gOIK?ZGX0mTEDmQISe_+OfYl!_NR4^wR-p($9)V8bgc9$21B$pZ1>FtZvBICF3Z< zZ1-!}jterH;-m}huW>}jgP<>$sWVE(u+O8WEWV0_= z1x426JGb1#YMRreEyTfK6_RM0px-jV8Dj6~gjRs#bQSnepm${^^ds&hw~7kF*0gdb zUj*kL?YeHf&e6$A5npWNKKZCPV=z&gbW8E*irdZ;SM?nQw{!(h!u3=S4{GSGfYH+* zo5d<)s>q(3#@@;%$xk(E3o$Top=HXUr9yR@w6U9rh#^|^5$Le>*hoo?G$~mjE(|TR zh?HS<4UI`McOuhc{KkzVAAOe*EaE_WXCmTsws_|Ao8ppF0o zaAtvO-a|h*DRWk)sjf?qP}_ocgX0yWuzJa-t7ZN=H5aVmF}MBg4R8lF*+qQTqrdBN z2QT!=#ILiPU?8sb%H<95AaTj`4vhj%m3YgdGQzDD*A7CJy8Pv+BVZ30E2}}L{+|3Q zBHDp^V-&@R;#|Gv>;1_pXHAm0rPRP|5_uLoCtH3Nu3R&8stgg{ ztd|4M6BuLc*3+gCEiGlLd4G}#wxFeGj~Ys!Dwy$Vj!?_9LxRHQWV++k*`UY3K5buF zY;o;la4^xS4u7uwRK`Otr3?y6V1a6q*4GU+QfZ^z>A-To#XAmV5I?MLecX8%vK6`v qam}+dcXK0Vo}tP=4}+j&R= Date: Thu, 28 Mar 2024 22:02:22 +0100 Subject: [PATCH 050/418] Change multiday fullDay Event behaviour (#3396) Hey! This PR should change the behaviour of starting fullDay events that last several days. The goal was to change the behavior of the "Starting today, ends T" (T=Tomorrow) event, so it should show how many days it will occur from the first day on Before situation: a fullDay event that started 'today' and ends several days later showed Today on the first day. The rest of the days it showed X days left. ![grafik](https://github.com/MagicMirrorOrg/MagicMirror/assets/6515818/da4e06cf-3122-44d9-b78a-88f9970c57d4) Y => Yesterday T => Tomorrow Target situation with this commit: a fullDay event that started 'today' shows 'X days left' from the first day on and 'Today' on the last day. ![grafik](https://github.com/MagicMirrorOrg/MagicMirror/assets/6515818/c42b9a27-35cf-47b7-9a8f-937a6009f904) --------- Co-authored-by: Veeck --- CHANGELOG.md | 1 + modules/default/calendar/calendar.js | 9 +++-- .../modules/calendar/long-fullday-event.js | 28 ++++++++++++++++ .../modules/calendar/single-fullday-event.js | 28 ++++++++++++++++ tests/e2e/modules/calendar_spec.js | 31 +++++++++++++++++ tests/mocks/calendar_test_full_day_events.ics | 33 +++++++++++++++++++ ...calendar_test_multi_day_starting_today.ics | 33 +++++++++++++++++++ 7 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 tests/configs/modules/calendar/long-fullday-event.js create mode 100644 tests/configs/modules/calendar/single-fullday-event.js create mode 100644 tests/mocks/calendar_test_full_day_events.ics create mode 100644 tests/mocks/calendar_test_multi_day_starting_today.ics diff --git a/CHANGELOG.md b/CHANGELOG.md index 709d6bc95b..c897536eaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ _This release is scheduled to be released on 2024-04-01._ - [chore] Update dependencies including electron to v29 (#3357) and node-ical - Updated translations for estonian (#3371) - Update electron to v29 and update other dependencies +- [calendar] fullDay events over several days now show the left days from the first day on and 'today' on the last day - Updated layout of current weather indoor values ### Fixed diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 0ce41cc050..a3f597592f 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -204,6 +204,11 @@ Module.register("calendar", { this.updateDom(this.config.animationSpeed); }, + eventEndingWithinNextFullTimeUnit (event, ONE_DAY) { + const now = new Date(); + return event.endDate - now <= ONE_DAY; + }, + // Override dom generator. getDom () { const ONE_SECOND = 1000; // 1,000 milliseconds @@ -438,7 +443,7 @@ Module.register("calendar", { } } else { // Show relative times - if (event.startDate >= now || (event.fullDayEvent && event.today)) { + if (event.startDate >= now || (event.fullDayEvent && this.eventEndingWithinNextFullTimeUnit(event, ONE_DAY))) { // Use relative time if (!this.config.hideTime && !event.fullDayEvent) { timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").calendar(null, { sameElse: this.config.dateFormat })); @@ -454,7 +459,7 @@ Module.register("calendar", { } if (event.fullDayEvent) { // Full days events within the next two days - if (event.today) { + if (event.today || (event.fullDayEvent && this.eventEndingWithinNextFullTimeUnit(event, ONE_DAY))) { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TODAY")); } else if (event.dayBeforeYesterday) { if (this.translate("DAYBEFOREYESTERDAY") !== "DAYBEFOREYESTERDAY") { diff --git a/tests/configs/modules/calendar/long-fullday-event.js b/tests/configs/modules/calendar/long-fullday-event.js new file mode 100644 index 0000000000..efbc244886 --- /dev/null +++ b/tests/configs/modules/calendar/long-fullday-event.js @@ -0,0 +1,28 @@ +/* MagicMirror² Test config for fullday calendar entries over multiple days + * + * By Paranoid93 https://github.com/Paranoid93/ + * MIT Licensed. + */ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + calendars: [ + { + maximumNumberOfDays: 2, + url: "http://localhost:8080/tests/mocks/calendar_test_multi_day_starting_today.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/single-fullday-event.js b/tests/configs/modules/calendar/single-fullday-event.js new file mode 100644 index 0000000000..9149d2d9ab --- /dev/null +++ b/tests/configs/modules/calendar/single-fullday-event.js @@ -0,0 +1,28 @@ +/* MagicMirror² Test config for fullday calendar entries over multiple days + * + * By Paranoid93 https://github.com/Paranoid93/ + * MIT Licensed. + */ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + calendars: [ + { + maximumNumberOfDays: 2, + url: "http://localhost:8080/tests/mocks/calendar_test_full_day_events.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/e2e/modules/calendar_spec.js b/tests/e2e/modules/calendar_spec.js index e72917820f..0dcd562cd1 100644 --- a/tests/e2e/modules/calendar_spec.js +++ b/tests/e2e/modules/calendar_spec.js @@ -99,6 +99,37 @@ describe("Calendar module", () => { }); }); + //Will contain everyday an fullDayEvent that starts today and ends tomorrow, and one starting tomorrow and ending the day after tomorrow + describe("FullDayEvent over several days should show how many days are left from the from the starting date on", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/calendar/long-fullday-event.js"); + await helpers.getDocument(); + }); + + it("should contain text 'Ends in' with the left days", async () => { + await expect(testTextContain(".calendar .today .time", "Ends in")).resolves.toBe(true); + await expect(testTextContain(".calendar .yesterday .time", "Today")).resolves.toBe(true); + await expect(testTextContain(".calendar .tomorrow .time", "Tomorrow")).resolves.toBe(true); + }); + it("should contain in total three events", async () => { + await expect(testElementLength(".calendar .event", 3)).resolves.toBe(true); + }); + }); + + describe("FullDayEvent Single day, should show Today", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/calendar/single-fullday-event.js"); + await helpers.getDocument(); + }); + + it("should contain text 'Today'", async () => { + await expect(testTextContain(".calendar .time", "Today")).resolves.toBe(true); + }); + it("should contain in total two events", async () => { + await expect(testElementLength(".calendar .event", 2)).resolves.toBe(true); + }); + }); + process.setMaxListeners(0); for (let i = -12; i < 12; i++) { describe("Recurring event per timezone", () => { diff --git a/tests/mocks/calendar_test_full_day_events.ics b/tests/mocks/calendar_test_full_day_events.ics new file mode 100644 index 0000000000..a3c48719c8 --- /dev/null +++ b/tests/mocks/calendar_test_full_day_events.ics @@ -0,0 +1,33 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//ical.marudot.com//iCal Event Maker +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:Europe/Berlin +LAST-MODIFIED:20231222T233358Z +TZURL:https://www.tzurl.org/zoneinfo-outlook/Europe/Berlin +X-LIC-LOCATION:Europe/Berlin +BEGIN:DAYLIGHT +TZNAME:CEST +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +DTSTART:19700329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +BEGIN:STANDARD +TZNAME:CET +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +DTSTART:19701025T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTAMP:20240306T225415Z +UID:1709765647426-75770@ical.marudot.com +DTSTART;VALUE=DATE:20240306 +RRULE:FREQ=DAILY +DTEND;VALUE=DATE:20240307 +SUMMARY:daily full days +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/calendar_test_multi_day_starting_today.ics b/tests/mocks/calendar_test_multi_day_starting_today.ics new file mode 100644 index 0000000000..7a9151175b --- /dev/null +++ b/tests/mocks/calendar_test_multi_day_starting_today.ics @@ -0,0 +1,33 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//ical.marudot.com//iCal Event Maker +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:Europe/Berlin +LAST-MODIFIED:20231222T233358Z +TZURL:https://www.tzurl.org/zoneinfo-outlook/Europe/Berlin +X-LIC-LOCATION:Europe/Berlin +BEGIN:DAYLIGHT +TZNAME:CEST +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +DTSTART:19700329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +BEGIN:STANDARD +TZNAME:CET +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +DTSTART:19701025T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTAMP:20240306T222634Z +UID:1709763965312-82782@ical.marudot.com +DTSTART;VALUE=DATE:20240301 +RRULE:FREQ=DAILY +DTEND;VALUE=DATE:20240303 +SUMMARY:2 day events +END:VEVENT +END:VCALENDAR From 72ef8235b198b0854983a1118cbefd8fed92e9c6 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 30 Mar 2024 23:29:57 +0100 Subject: [PATCH 051/418] update Collaboration.md (added infos from discord) (#3408) --- CHANGELOG.md | 4 ++-- Collaboration.md | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c897536eaf..062257e7b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,10 +26,10 @@ _This release is scheduled to be released on 2024-04-01._ - Update pm2 to v5.3.1 with no allow-ghsas (#3364) - [chore] Update husky and let lint-staged fix ESLint issues - [chore] Update dependencies including electron to v29 (#3357) and node-ical -- Updated translations for estonian (#3371) +- Update translations for estonian (#3371) - Update electron to v29 and update other dependencies - [calendar] fullDay events over several days now show the left days from the first day on and 'today' on the last day -- Updated layout of current weather indoor values +- Update layout of current weather indoor values ### Fixed diff --git a/Collaboration.md b/Collaboration.md index 100bbf95cb..6d2da4d6a3 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -5,7 +5,7 @@ This document describes how collaborators of this repository should work togethe - never merge your own PR's - never merge without someone having approved (approving and merging from same person is allowed) - wait for all approvals requested (or the author decides something different in the comments) -- never merge to `master`, except for releases (because of update notification) +- merge to `master` only for releases or other urgent issues (update notification is only triggered by tags) - merges to master should be tagged with the "mastermerge" label so that the test runs through ## Issues @@ -16,3 +16,23 @@ This document describes how collaborators of this repository should work togethe ## Releases Are done by @rejas or @khassel. + +### Deployment steps + +- pull latest `develop` branch +- update `package.json` to reflect correct version number +- run `npm install` to generate new `package-lock.json` +- test `develop` branch +- update `CHANGELOG.md` (don't forget to add all contributor names) +- commit and push all changes +- after successful test run via github actions: create pull request to `master` branch +- after PR tests run without issues, merge PR +- create new release with corresponding version tag +- publish release notes with link to github release on forum in new locked topic + +### Draft new development release + +- checkout `develop` branch +- update `package.json` to reflect correct version number `2.xx.0-develop` +- draft new section in `CHANGELOG.md` +- commit and publish `develop` branch From b262bf61441496ddadb79e8bf2deac778f3c4b10 Mon Sep 17 00:00:00 2001 From: veeck Date: Mon, 1 Apr 2024 12:01:44 +0200 Subject: [PATCH 052/418] Release 2.27.0 --- CHANGELOG.md | 12 ++++++++---- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 062257e7b2..708b05ba3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,19 @@ This project adheres to [Semantic Versioning](https://semver.org/). ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². -## [2.27.0] - Develop Branch (unreleased) +## [2.27.0] - 2024-04-01 -_This release is scheduled to be released on 2024-04-01._ +Thanks to: @bugsounet, @crazyscot, @illimarkangur, @jkriegshauser, @khassel, @KristjanESPERANTO, @Paranoid93, @rejas, @sdetweil and @vppencilsharpener. + +This release marks the first release without Michael Teeuw (@michmich). A very special thanks to him for creating MagicMirror and leading the project for so many years. + +For more info, please read the following post: [A New Chapter for MagicMirror: The Community Takes the Lead](https://forum.magicmirror.builders/topic/18329/a-new-chapter-for-magicmirror-the-community-takes-the-lead). ### Added - Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 (#3349) - [chore] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368) -- weather: `showHumidity` config is now a string describing where to show this element. Supported values: "wind", "temp", "feelslike", "below", "none". (#3330) +- [weather] `showHumidity` config is now a string describing where to show this element. Supported values: "wind", "temp", "feelslike", "below", "none". (#3330) - electron-rebuild test suite for electron and 3rd party modules compatibility (#3392) - Create MM² icon and attach it to electron process (#3407) @@ -54,7 +58,7 @@ _This release is scheduled to be released on 2024-04-01._ - Unneeded file headers (#3358) -## [2.26.0] - 01-01-2024 +## [2.26.0] - 2024-01-01 Thanks to: @bnitkin, @bugsounet, @dependabot, @jkriegshauser, @kaennchenstruggle, @KristjanESPERANTO and @Ybbet. diff --git a/package-lock.json b/package-lock.json index 08d66d8f0b..713e594e5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.27.0-develop", + "version": "2.27.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.27.0-develop", + "version": "2.27.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 65b745df8b..85d547c20d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.27.0-develop", + "version": "2.27.0", "description": "The open source modular smart mirror platform.", "main": "js/electron.js", "scripts": { From 53420f5be9214f955b1e3e598e13623fd378e49d Mon Sep 17 00:00:00 2001 From: Veeck Date: Mon, 1 Apr 2024 18:16:20 +0200 Subject: [PATCH 053/418] Fix check for mastermerge label (#3415) Mastermerge label wasnt checked correctly, this PR should hopefully fixes it for good --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/enforce-pullrequest-rules.yaml | 2 +- CHANGELOG.md | 1 + package-lock.json | 16 ++++++++-------- package.json | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/enforce-pullrequest-rules.yaml b/.github/workflows/enforce-pullrequest-rules.yaml index 22d9c212ea..30c0d0ca08 100644 --- a/.github/workflows/enforce-pullrequest-rules.yaml +++ b/.github/workflows/enforce-pullrequest-rules.yaml @@ -19,7 +19,7 @@ jobs: changeLogPath: "CHANGELOG.md" skipLabels: "Skip Changelog" - name: "Enforce develop branch" - if: ${{ github.base_ref == 'master' && !contains(github.event.pull_request.labels.*.name, 'mastermerge') }} + if: ${{ github.event.pull_request.base.ref == 'master' && !contains(github.event.pull_request.labels.*.name, 'mastermerge') }} run: | echo "This PR is based against the master branch and not a release or hotfix." echo "Please don't do this. Switch the branch to 'develop'." diff --git a/CHANGELOG.md b/CHANGELOG.md index 708b05ba3b..9669d7e6c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T - Don't display any `npm WARN <....>` on install (#3399) - Fixed move suncalc dependency to production from dev, as it is used by clock module - [compliments] Fix mirror not responding anymore when no compliments are to be shown (#3385) +- [chore] Fixed mastermerge workflow (#3415) ### Deleted diff --git a/package-lock.json b/package-lock.json index 713e594e5c..f116244dd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,8 +32,8 @@ "@stylistic/eslint-plugin": "^1.7.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-jsdoc": "^48.2.1", - "eslint-plugin-package-json": "^0.12.0", + "eslint-plugin-jsdoc": "^48.2.2", + "eslint-plugin-package-json": "^0.12.1", "eslint-plugin-unicorn": "^51.0.1", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", @@ -4633,9 +4633,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.1.tgz", - "integrity": "sha512-iUvbcyDZSO/9xSuRv2HQBw++8VkV/pt3UWtX9cpPH0l7GKPq78QC/6+PmyQHHvNZaTjAce6QVciEbnc6J/zH5g==", + "version": "48.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.2.tgz", + "integrity": "sha512-S0Gk+rpT5w/ephKCncUY7kUsix9uE4B9XI8D/fS1/26d8okE+vZsuG1IvIt4B6sJUdQqsnzi+YXfmh+HJG11CA==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.42.0", @@ -4656,9 +4656,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.12.0.tgz", - "integrity": "sha512-BtzhiA/7x7hqY+0fLXcgiN8wXGFyABJS93q/gns6MsAAPrbGFH3N7MYuCrNUEP60NPHQ4kAW04sPQarQBvJqHg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.12.1.tgz", + "integrity": "sha512-Z70ddt7tvZrdLZv4V1OkoDqGnnFakVRmAAeP+y/18ZvpgoPJXkqa+JRJNh+tWQ2PMZU4CqleZ6tZOEoq47AY2g==", "dev": true, "dependencies": { "package-json-validator": "^0.6.3", diff --git a/package.json b/package.json index 85d547c20d..949306ca8e 100644 --- a/package.json +++ b/package.json @@ -52,8 +52,8 @@ "@stylistic/eslint-plugin": "^1.7.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-jsdoc": "^48.2.1", - "eslint-plugin-package-json": "^0.12.0", + "eslint-plugin-jsdoc": "^48.2.2", + "eslint-plugin-package-json": "^0.12.1", "eslint-plugin-unicorn": "^51.0.1", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", From 2a883c393cddaee3073c71caef3a143ec0645480 Mon Sep 17 00:00:00 2001 From: Veeck Date: Mon, 1 Apr 2024 20:08:31 +0200 Subject: [PATCH 054/418] Remove codecov yaml (#3416) CodeCov isnt used at the moment and MAYBE this blocks our release --- .github/codecov.yaml | 10 ---------- CHANGELOG.md | 1 + 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 .github/codecov.yaml diff --git a/.github/codecov.yaml b/.github/codecov.yaml deleted file mode 100644 index 3c73437547..0000000000 --- a/.github/codecov.yaml +++ /dev/null @@ -1,10 +0,0 @@ -coverage: - status: - project: - default: - # advanced settings - informational: true - patch: - default: - threshold: 0% - target: 0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9669d7e6c2..23da33577f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T ### Deleted - Unneeded file headers (#3358) +- Removed codecov.yaml ## [2.26.0] - 2024-01-01 From 8aaad8e7ec896fb025210a294e9b9824bb9f7c65 Mon Sep 17 00:00:00 2001 From: veeck Date: Mon, 1 Apr 2024 22:05:54 +0200 Subject: [PATCH 055/418] Prepare v2.28.0-develop --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23da33577f..d73f2b2a80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ This project adheres to [Semantic Versioning](https://semver.org/). ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². +## [2.28.0] - Unreleased (`develop` branch) + +_This release is scheduled to be released on 2024-07-01._ + +### Added + +### Removed + +### Updated + +### Fixed + ## [2.27.0] - 2024-04-01 Thanks to: @bugsounet, @crazyscot, @illimarkangur, @jkriegshauser, @khassel, @KristjanESPERANTO, @Paranoid93, @rejas, @sdetweil and @vppencilsharpener. diff --git a/package-lock.json b/package-lock.json index f116244dd5..2717e6ae29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.27.0", + "version": "2.28.0-develop", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.27.0", + "version": "2.28.0-develop", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 949306ca8e..f0f417e27c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.27.0", + "version": "2.28.0-develop", "description": "The open source modular smart mirror platform.", "main": "js/electron.js", "scripts": { From 1fa17883bce86762b0dd32e0a2e599d6c9f9560e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:11:52 +0200 Subject: [PATCH 056/418] Bump ansis from 2.3.0 to 3.0.1 (#3417) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [ansis](https://github.com/webdiscus/ansis) from 2.3.0 to 3.0.1.
Release notes

Sourced from ansis's releases.

v3.0.0

Features

  • Added detection of color spaces support: TrueColor, 256 colors, 16 colors, no color (black & white).
  • Added fallback for supported color space: truecolor —> 256 colors —> 16 colors —> no colors.
  • Improved performance for the hex() function.

BREAKING CHANGE

In the new major version 3.x are removed unused styles and methods.

⚠️ Warning

Before update, please check your code whether is used deleted styles and methods.

Support Node.js

Drop supports for Node <= 14. Minimal supported version is 15.0.0 (Released 2020-10-20). In the theory the v3 can works with Node12, but we can't test it.

Deleted styles

The not widely supported styles are deleted:

  • faint (alias for dim), replace in your code with dim
  • doubleUnderline, replace in your code with underline
  • frame, replace in your code with underline
  • encircle, replace in your code with underline
  • overline, replace in your code with underline

Deleted methods

The methods are deleted:

  • ansi, replace in your code with ansi256 or fg
  • bgAnsi, replace in your code with bgAnsi256 or bg

Deleted clamp in functions

The clamp (0, 255) for the ANSI 256 codes and RGB values is removed, because is unused. You should self check the function arguments.

The affected functions:

  • ansi256 and fg (alias to ansi256) - expected a code in the range 0 - 255
  • bgAnsi256 and bg (alias to bgAnsi256) - expected a code in the range0 - 255
  • rgb - expected r, g, b values in the range 0 - 255
  • bgRgb - expected r, g, b values in the range 0 - 255
Changelog

Sourced from ansis's changelog.

3.0.1 (2024-04-01)

  • refactor: improve code
  • chore: reduce code bundle size from 3.8 KB to 3.4 KB
  • chore: update benchmark
  • chore: update compare tests
  • test: add more tests
  • docs: improve readme

3.0.0 (2024-03-29)

  • feat: add detection of color spaces support: TrueColor, 256 colors, 16 colors, no color
  • feat: add fallback for supported color space: truecolor —> 256 colors —> 16 colors —> no colors
  • perform: improve performance for hex() function
  • chore: size increased from 3.2 KB to 3.8 KB as new features were added
  • test: switch from jest to vitest
  • test: add tests for new features
  • docs: update readme for color spaces support

BREAKING CHANGE

In the new major version 3.x are removed unused styles and methods.

⚠️ Warning

Before update, please check your code whether is used deleted styles and methods.

Support Node.js

Drop supports for Node <= 14. Minimal supported version is 15.0.0 (Released 2020-10-20). In the theory the v3 can works with Node12, but we can't test it.

Deleted styles

The not widely supported styles are deleted:

  • faint (alias for dim), replace in your code with dim
  • doubleUnderline, replace in your code with underline
  • frame, replace in your code with underline
  • encircle, replace in your code with underline
  • overline, replace in your code with underline

Deleted methods

The methods are deleted:

  • ansi, replace in your code with ansi256 or fg
  • bgAnsi, replace in your code with bgAnsi256 or bg

Deleted clamp in functions

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ansis&package-manager=npm_and_yarn&previous-version=2.3.0&new-version=3.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2717e6ae29..08836b462a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "ansis": "^2.3.0", + "ansis": "^3.0.1", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", @@ -2361,11 +2361,11 @@ } }, "node_modules/ansis": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-2.3.0.tgz", - "integrity": "sha512-ih2ljYHaFnLc8rAHhm0yJmTBtpwT1ULyDrgFZQ2WAbWkikCiBkroPB4qJxTRqh3ocsaOstmg3aDeG+vCfPVtHg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.0.1.tgz", + "integrity": "sha512-NMqcJGNewJ+tVAK5fJFY7kBo698ViFSH8ceUfEwBHGZb4SNxHnbJPDBW0wNQU6rYjnBGBwBfUSmeIab/KrA5/A==", "engines": { - "node": ">=12.13" + "node": ">=15" }, "funding": { "type": "patreon", diff --git a/package.json b/package.json index f0f417e27c..b29b700b6a 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "electron": "^29.1.6" }, "dependencies": { - "ansis": "^2.3.0", + "ansis": "^3.0.1", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", From 3b0035760d729afaa03556d2b94ab4c4cc4f2687 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 1 May 2024 19:54:38 +0200 Subject: [PATCH 057/418] Update deps (#3439) - update dependencies including electron to v30 - replace node v21 with v22 in tests --- .github/workflows/automated-tests.yaml | 2 +- CHANGELOG.md | 2 + fonts/package-lock.json | 16 +- fonts/package.json | 10 +- package-lock.json | 778 ++++++++++--------------- package.json | 100 ++-- vendor/package-lock.json | 8 +- vendor/package.json | 8 +- 8 files changed, 387 insertions(+), 537 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index fd3e1e898b..18795146b6 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -18,7 +18,7 @@ jobs: timeout-minutes: 30 strategy: matrix: - node-version: [18.x, 20.x, 21.x] + node-version: [18.x, 20.x, 22.x] steps: - name: "Checkout code" uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index d73f2b2a80..cfa896f6dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ _This release is scheduled to be released on 2024-07-01._ ### Updated +- [chore] Update dependencies including electron to v30 + ### Fixed ## [2.27.0] - 2024-04-01 diff --git a/fonts/package-lock.json b/fonts/package-lock.json index 09ee878124..287cd90e62 100644 --- a/fonts/package-lock.json +++ b/fonts/package-lock.json @@ -9,19 +9,19 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.0.12", - "@fontsource/roboto-condensed": "^5.0.15" + "@fontsource/roboto": "^5.0.13", + "@fontsource/roboto-condensed": "^5.0.16" } }, "node_modules/@fontsource/roboto": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.12.tgz", - "integrity": "sha512-x0o17jvgoSSbS9OZnUX2+xJmVRvVCfeaYJjkS7w62iN7CuJWtMf5vJj8LqgC7ibqIkitOHVW+XssRjgrcHn62g==" + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.13.tgz", + "integrity": "sha512-j61DHjsdUCKMXSdNLTOxcG701FWnF0jcqNNQi2iPCDxU8seN/sMxeh62dC++UiagCWq9ghTypX+Pcy7kX+QOeQ==" }, "node_modules/@fontsource/roboto-condensed": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.15.tgz", - "integrity": "sha512-0AFvcI/8JQ5+FZE12hdaE1W/1ooJUzd5XP7jD74+SP+PArsswJ+6OV/oKTasgeQeZlvGrcD3chO6yr5K4JGwzA==" + "version": "5.0.16", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.16.tgz", + "integrity": "sha512-pjO80g5x/hkqzWCIafvkS3JrkBDxSiTjEy4LdqQKJYrmoGx8x2AlhSUMgzIzG/ge4kT98bA7+gmm7yquzrrZ/w==" } } } diff --git a/fonts/package.json b/fonts/package.json index da67752914..09d7c153e6 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -2,16 +2,16 @@ "name": "magicmirror-fonts", "version": "1.0.0", "description": "Package for fonts use by MagicMirror² core.", + "bugs": { + "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" + }, "repository": { "type": "git", "url": "https://github.com/MagicMirrorOrg/MagicMirror" }, "license": "MIT", - "bugs": { - "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" - }, "dependencies": { - "@fontsource/roboto": "^5.0.12", - "@fontsource/roboto-condensed": "^5.0.15" + "@fontsource/roboto": "^5.0.13", + "@fontsource/roboto-condensed": "^5.0.16" } } diff --git a/package-lock.json b/package-lock.json index 08836b462a..9be0e71cf5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "ansis": "^3.0.1", + "ansis": "^3.2.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", @@ -26,24 +26,24 @@ "pm2": "^5.3.1", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.22.6" + "systeminformation": "^5.22.7" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.7.0", + "@stylistic/eslint-plugin": "^1.8.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-jsdoc": "^48.2.2", - "eslint-plugin-package-json": "^0.12.1", - "eslint-plugin-unicorn": "^51.0.1", + "eslint-plugin-jest": "^28.3.0", + "eslint-plugin-jsdoc": "^48.2.3", + "eslint-plugin-package-json": "^0.13.1", + "eslint-plugin-unicorn": "^52.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", "jest": "^29.7.0", "jsdom": "^24.0.0", "lint-staged": "^15.2.2", - "playwright": "^1.42.1", + "playwright": "^1.43.1", "prettier": "^3.2.5", "sinon": "^17.0.1", - "stylelint": "^16.3.1", + "stylelint": "^16.4.0", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0" }, @@ -51,15 +51,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^29.1.6" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "engines": { - "node": ">=0.10.0" + "electron": "^30.0.1" } }, "node_modules/@ampproject/remapping": { @@ -89,30 +81,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", - "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", - "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.1", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.1", - "@babel/parser": "^7.24.1", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -137,12 +129,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", - "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.0", + "@babel/types": "^7.24.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -235,16 +227,16 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -254,33 +246,33 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -296,9 +288,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -314,26 +306,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", - "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", "dev": true, "dependencies": { "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", + "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.5", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -414,9 +406,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", - "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -617,19 +609,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -647,13 +639,13 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -731,9 +723,9 @@ } }, "node_modules/@csstools/selector-specificity": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.2.tgz", - "integrity": "sha512-RpHaZ1h9LE7aALeQXmXrJkRG84ZxIsctEN2biEUmFyKpzFM3zZ35eUMcIzZFsw/2olQE6v69+esEqU2f1MKycg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.3.tgz", + "integrity": "sha512-KEPNw4+WW5AVEIyzC80rTbWEUatTW2lXpN8+8ILC8PiPeWPjwUzrPZDIOZ2wwqDmeqOYTdSGyL3+vE5GC3FB3Q==", "dev": true, "funding": [ { @@ -783,29 +775,6 @@ "global-agent": "^3.0.0" } }, - "node_modules/@electron/get/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "optional": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@electron/get/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optional": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/@electron/get/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -815,15 +784,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@electron/get/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "optional": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/@es-joy/jsdoccomment": { "version": "0.42.0", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz", @@ -956,9 +916,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -1804,21 +1764,21 @@ "dev": true }, "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.7.0.tgz", - "integrity": "sha512-ThMUjGIi/jeWYNvOdjZkoLw1EOVs0tEuKXDgWvTn8uWaEz55HuPlajKxjKLpv19C+qRDbKczJfzUODfCdME53A==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.8.0.tgz", + "integrity": "sha512-JRR0lCDU97AiE0X6qTc/uf8Hv0yETUdyJgoNzTLUIWdhVJVe/KGPnFmEsO1iXfNUIS6vhv3JJ5vaZ2qtXhZe1g==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.7.0", - "@stylistic/eslint-plugin-jsx": "1.7.0", - "@stylistic/eslint-plugin-plus": "1.7.0", - "@stylistic/eslint-plugin-ts": "1.7.0", - "@types/eslint": "^8.56.2" + "@stylistic/eslint-plugin-js": "1.8.0", + "@stylistic/eslint-plugin-jsx": "1.8.0", + "@stylistic/eslint-plugin-plus": "1.8.0", + "@stylistic/eslint-plugin-ts": "1.8.0", + "@types/eslint": "^8.56.10" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1828,12 +1788,12 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.7.0.tgz", - "integrity": "sha512-PN6On/+or63FGnhhMKSQfYcWutRlzOiYlVdLM6yN7lquoBTqUJHYnl4TA4MHwiAt46X5gRxDr1+xPZ1lOLcL+Q==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.0.tgz", + "integrity": "sha512-jdvnzt+pZPg8TfclZlTZPiUbbima93ylvQ+wNgHLNmup3obY6heQvgewSu9i2CfS61BnRByv+F9fxQLPoNeHag==", "dev": true, "dependencies": { - "@types/eslint": "^8.56.2", + "@types/eslint": "^8.56.10", "acorn": "^8.11.3", "escape-string-regexp": "^4.0.0", "eslint-visitor-keys": "^3.4.3", @@ -1847,15 +1807,15 @@ } }, "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.7.0.tgz", - "integrity": "sha512-BACdBwXakQvjYIST5N2WWhRbvhRsIxa/F59BiZol+0IH4FSmDXhie7v/yaxDIIA9CbfElzOmIA5nWNYTVXcnwQ==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.8.0.tgz", + "integrity": "sha512-PC7tYXipF03TTilGJva1amAham7qOAFXT5r5jLTY6iIxkFqyb6H7Ljx5pv8d7n98VyIVidOEKY/AP8vNzAFNKg==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "^1.7.0", - "@types/eslint": "^8.56.2", + "@stylistic/eslint-plugin-js": "^1.8.0", + "@types/eslint": "^8.56.10", "estraverse": "^5.3.0", - "picomatch": "^4.0.1" + "picomatch": "^4.0.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1865,12 +1825,12 @@ } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.7.0.tgz", - "integrity": "sha512-AabDw8sXsc70Ydx3qnbeTlRHZnIwY6UKEenBPURPhY3bfYWX+/pDpZH40HkOu94v8D0DUrocPkeeEUxl4e0JDg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.8.0.tgz", + "integrity": "sha512-TkrjzzYmTuAaLvFwtxomsgMUD8g8PREOQOQzTfKmiJ6oc4XOyFW4q/L9ES1J3UFSLybNCwbhu36lhXJut1w2Sg==", "dev": true, "dependencies": { - "@types/eslint": "^8.56.2", + "@types/eslint": "^8.56.10", "@typescript-eslint/utils": "^6.21.0" }, "peerDependencies": { @@ -1878,13 +1838,13 @@ } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.7.0.tgz", - "integrity": "sha512-QsHv98mmW1xaucVYQTyLDgEpybPJ/6jPPxVBrIchntWWwj74xCWKUiw79hu+TpYj/Pbhd9rkqJYLNq3pQGYuyA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.8.0.tgz", + "integrity": "sha512-WuCIhz4JEHxzhAWjrBASMGj6Or1wAjDqTsRIck3DRRrw/FJ8C/8AAuHPk8ECHNSDI5PZ0OT72nF2uSUn0aQq1w==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.7.0", - "@types/eslint": "^8.56.2", + "@stylistic/eslint-plugin-js": "1.8.0", + "@types/eslint": "^8.56.10", "@typescript-eslint/utils": "^6.21.0" }, "engines": { @@ -1978,9 +1938,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.6.tgz", - "integrity": "sha512-ymwc+qb1XkjT/gfoQwxIeHZ6ixH23A+tCT2ADSA/DPVKzAjwYkTXBMCQ/f6fe4wEa85Lhp26VPeUxI7wMhAi7A==", + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", "dev": true, "dependencies": { "@types/estree": "*", @@ -2070,9 +2030,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", - "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dependencies": { "undici-types": "~5.26.4" } @@ -2265,9 +2225,9 @@ } }, "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dependencies": { "debug": "^4.3.4" }, @@ -2361,15 +2321,11 @@ } }, "node_modules/ansis": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.0.1.tgz", - "integrity": "sha512-NMqcJGNewJ+tVAK5fJFY7kBo698ViFSH8ceUfEwBHGZb4SNxHnbJPDBW0wNQU6rYjnBGBwBfUSmeIab/KrA5/A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.2.0.tgz", + "integrity": "sha512-Yk3BkHH9U7oPyCN3gL5Tc7CpahG/+UFv/6UG03C311Vy9lzRmA5uoxDTpU9CO3rGHL6KzJz/pdDeXZCZ5Mu/Sg==", "engines": { "node": ">=15" - }, - "funding": { - "type": "patreon", - "url": "https://patreon.com/biodiscus" } }, "node_modules/anymatch": { @@ -2942,9 +2898,9 @@ } }, "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", + "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", "dev": true, "dependencies": { "semver": "^7.0.0" @@ -2985,21 +2941,6 @@ "node": ">=8" } }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -3036,9 +2977,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001600", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", - "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", + "version": "1.0.30001614", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz", + "integrity": "sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==", "dev": true, "funding": [ { @@ -3134,9 +3075,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", "dev": true }, "node_modules/clarinet": { @@ -3433,9 +3374,9 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/core-js-compat": { - "version": "3.36.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", - "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.0.tgz", + "integrity": "sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==", "dev": true, "dependencies": { "browserslist": "^4.23.0" @@ -3523,9 +3464,9 @@ } }, "node_modules/css-functions-list": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", - "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", + "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", "dev": true, "engines": { "node": ">=12 || >=16" @@ -3651,9 +3592,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" }, "node_modules/debug": { "version": "4.3.4", @@ -3705,9 +3646,9 @@ } }, "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" @@ -3931,9 +3872,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "29.1.6", - "resolved": "https://registry.npmjs.org/electron/-/electron-29.1.6.tgz", - "integrity": "sha512-UIYfpHR9gRBFKHyejHuXUVQ7nNzZRnoPVOHlijkvqR+DSLwgJ2ZcVVt0LNduNeO8PhPkY1+6kHonL52OTC1cOw==", + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-30.0.1.tgz", + "integrity": "sha512-iwxkI/n2wBd29NH7TH0ZY8aWGzCoKpzJz+D10u7aGSJi1TV6d4MSM3rWyKvT/UkAHkTKOEgYfUyCa2vWQm8L0g==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -3949,9 +3890,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.718", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.718.tgz", - "integrity": "sha512-6FpOapKxHuRNUoNQEP54sAacMod/XX68/Oaau+UoTEC8yxy5lR8jAvTlyrb60oZ9OtuUuAEtKvCQOJm6S4MtBQ==", + "version": "1.4.752", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.752.tgz", + "integrity": "sha512-P3QJreYI/AUTcfBVrC4zy9KvnZWekViThgQMX/VpJ+IsOBbcX5JFpORM4qWapwWQ+agb2nYAOyn/4PMXOk0m2Q==", "dev": true }, "node_modules/emitter-listener": { @@ -4125,9 +4066,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", - "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -4168,11 +4109,11 @@ "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.9", "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.7", + "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.15" }, @@ -4486,19 +4427,19 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "version": "28.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.3.0.tgz", + "integrity": "sha512-5LjCSSno8E+IUCOX4hJiIb/upPIgpkaDEcaN/40gOcw26t/5UTLHFc4JdxKjOOvGTh0XdCu+fNr0fpOVNvcxMA==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^5.10.0" + "@typescript-eslint/utils": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "jest": "*" }, "peerDependenciesMeta": { @@ -4510,132 +4451,10 @@ } } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-jest/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-plugin-jest/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.2.tgz", - "integrity": "sha512-S0Gk+rpT5w/ephKCncUY7kUsix9uE4B9XI8D/fS1/26d8okE+vZsuG1IvIt4B6sJUdQqsnzi+YXfmh+HJG11CA==", + "version": "48.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.3.tgz", + "integrity": "sha512-r9DMAmFs66VNvNqRLLjHejdnJtILrt3xGi+Qx0op0oRfFGVpOR1Hb3BC++MacseHx93d8SKYPhyrC9BS7Os2QA==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.42.0", @@ -4656,13 +4475,16 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.12.1.tgz", - "integrity": "sha512-Z70ddt7tvZrdLZv4V1OkoDqGnnFakVRmAAeP+y/18ZvpgoPJXkqa+JRJNh+tWQ2PMZU4CqleZ6tZOEoq47AY2g==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.13.1.tgz", + "integrity": "sha512-aZkSvyJZRW4JKFhdoBhuPgc8sM/UAQN993uh956Yb8dSFCAV0Vkwrw09cuPL5onZ6ygF5pCqSs57wZRqGIwDQQ==", "dev": true, "dependencies": { + "detect-indent": "6.1.0", + "detect-newline": "3.1.0", "package-json-validator": "^0.6.3", "semver": "^7.5.4", + "sort-object-keys": "^1.1.3", "sort-package-json": "^1.57.0", "validate-npm-package-name": "^5.0.0" }, @@ -4675,9 +4497,9 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "51.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz", - "integrity": "sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==", + "version": "52.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-52.0.0.tgz", + "integrity": "sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -4861,6 +4683,18 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -4983,21 +4817,6 @@ "@types/yauzl": "^2.9.1" } }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "optional": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/extrareqp2": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz", @@ -5254,16 +5073,17 @@ } }, "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "optional": true, "dependencies": { "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">=14.14" + "node": ">=6 <7 || >=8" } }, "node_modules/fs.realpath": { @@ -5375,12 +5195,15 @@ } }, "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5416,6 +5239,38 @@ "node": ">= 14" } }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/get-uri/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/get-uri/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/git-hooks-list": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", @@ -5555,11 +5410,12 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -7181,12 +7037,10 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optional": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -8000,9 +7854,9 @@ } }, "node_modules/nise/node_modules/path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", "dev": true }, "node_modules/node-ical": { @@ -8099,9 +7953,9 @@ "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" }, "node_modules/nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz", + "integrity": "sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==", "dev": true }, "node_modules/object-assign": { @@ -8254,16 +8108,16 @@ } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -8346,9 +8200,9 @@ } }, "node_modules/package-json-validator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.3.tgz", - "integrity": "sha512-juKiFboV4UKUvWQ+OSxstnyukhuluyuEoFmgZw1Rx21XzmwlgDWLcbl3qzjA3789IRORYhVFs7cmAO0YFGwHCg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.4.tgz", + "integrity": "sha512-sp5bWr5eUoVgNV50vsJyil0XCluM+qMvtba8X4ug5Z/0YtYZsePka+tZgqiZnAyFyf5pwXaSDwYncFdSEzX7PA==", "dev": true, "dependencies": { "optimist": "~0.6.0" @@ -8487,9 +8341,9 @@ "dev": true }, "node_modules/picomatch": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", - "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, "engines": { "node": ">=12" @@ -8595,12 +8449,12 @@ } }, "node_modules/playwright": { - "version": "1.42.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", - "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==", + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz", + "integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==", "dev": true, "dependencies": { - "playwright-core": "1.42.1" + "playwright-core": "1.43.1" }, "bin": { "playwright": "cli.js" @@ -8613,9 +8467,9 @@ } }, "node_modules/playwright-core": { - "version": "1.42.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz", - "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==", + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz", + "integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -9149,9 +9003,9 @@ } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, "node_modules/read": { @@ -10006,9 +9860,9 @@ } }, "node_modules/socks": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", - "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" @@ -10019,11 +9873,11 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", + "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.1", "debug": "^4.3.4", "socks": "^2.7.1" }, @@ -10366,20 +10220,20 @@ } }, "node_modules/stylelint": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.3.1.tgz", - "integrity": "sha512-/JOwQnBvxEKOT2RtNgGpBVXnCSMBgKOL2k7w0K52htwCyJls4+cHvc4YZgXlVoAZS9QJd2DgYAiRnja96pTgxw==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.4.0.tgz", + "integrity": "sha512-uSx7VMuXwLuYcNSIg+0/fFNv0WinsfLAqsVVy7h7p80clKOHiGE8pfY6UjqwylTHiJrRIahTl6a8FPxGezhWoA==", "dev": true, "dependencies": { "@csstools/css-parser-algorithms": "^2.6.1", "@csstools/css-tokenizer": "^2.2.4", "@csstools/media-query-list-parser": "^2.1.9", - "@csstools/selector-specificity": "^3.0.2", + "@csstools/selector-specificity": "^3.0.3", "@dual-bundle/import-meta-resolve": "^4.0.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.1", + "css-functions-list": "^3.2.2", "css-tree": "^2.3.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", @@ -10408,7 +10262,7 @@ "strip-ansi": "^7.1.0", "supports-hyperlinks": "^3.0.0", "svg-tags": "^1.0.0", - "table": "^6.8.1", + "table": "^6.8.2", "write-file-atomic": "^5.0.1" }, "bin": { @@ -10663,9 +10517,9 @@ "dev": true }, "node_modules/systeminformation": { - "version": "5.22.6", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.6.tgz", - "integrity": "sha512-hUTQX+bRgIFbv1T/z251NtwGwNIeSyWURnT2BGnsYu6dQNbkiBl4oAwk50acVfITFq1Zvb8KDNgibQK9uGlUGg==", + "version": "5.22.7", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.7.tgz", + "integrity": "sha512-AWxlP05KeHbpGdgvZkcudJpsmChc2Y5Eo/GvxG/iUA/Aws5LZKHAMSeAo+V+nD+nxWZaxrwpWcnx4SH3oxNL3A==", "os": [ "darwin", "linux", @@ -10704,15 +10558,15 @@ } }, "node_modules/table/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -10847,9 +10701,9 @@ } }, "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "dev": true, "dependencies": { "psl": "^1.1.33", @@ -10932,21 +10786,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, "node_modules/tv4": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", @@ -11077,9 +10916,9 @@ } }, "node_modules/typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "peer": true, "bin": { @@ -11122,11 +10961,12 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "optional": true, "engines": { - "node": ">= 10.0.0" + "node": ">= 4.0.0" } }, "node_modules/unpipe": { @@ -11138,9 +10978,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.14.tgz", + "integrity": "sha512-JixKH8GR2pWYshIPUg/NujK3JO7JiqEEUiNArE86NQyrgUuZeTlZQN3xuS/yiV5Kb48ev9K6RqNkaJjXsdg7Jw==", "dev": true, "funding": [ { @@ -11157,7 +10997,7 @@ } ], "dependencies": { - "escalade": "^3.1.1", + "escalade": "^3.1.2", "picocolors": "^1.0.0" }, "bin": { @@ -11398,6 +11238,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -11478,9 +11326,9 @@ } }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index b29b700b6a..da54181ef6 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,26 @@ "name": "magicmirror", "version": "2.28.0-develop", "description": "The open source modular smart mirror platform.", + "keywords": [ + "magic mirror", + "magicmirror", + "smart mirror", + "mirror UI", + "modular" + ], + "homepage": "https://magicmirror.builders", + "bugs": { + "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/MagicMirrorOrg/MagicMirror" + }, + "license": "MIT", + "author": "Michael Teeuw", + "contributors": [ + "https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors" + ], "main": "js/electron.js", "scripts": { "start": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js", @@ -28,50 +48,13 @@ "lint:staged": "lint-staged", "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed." }, - "repository": { - "type": "git", - "url": "https://github.com/MagicMirrorOrg/MagicMirror" - }, - "keywords": [ - "magic mirror", - "magicmirror", - "smart mirror", - "mirror UI", - "modular" - ], - "author": "Michael Teeuw", - "contributors": [ - "https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors" - ], - "license": "MIT", - "bugs": { - "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" - }, - "homepage": "https://magicmirror.builders", - "devDependencies": { - "@stylistic/eslint-plugin": "^1.7.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.9.0", - "eslint-plugin-jsdoc": "^48.2.2", - "eslint-plugin-package-json": "^0.12.1", - "eslint-plugin-unicorn": "^51.0.1", - "express-basic-auth": "^1.2.1", - "husky": "^9.0.11", - "jest": "^29.7.0", - "jsdom": "^24.0.0", - "lint-staged": "^15.2.2", - "playwright": "^1.42.1", - "prettier": "^3.2.5", - "sinon": "^17.0.1", - "stylelint": "^16.3.1", - "stylelint-config-standard": "^36.0.0", - "stylelint-prettier": "^5.0.0" - }, - "optionalDependencies": { - "electron": "^29.1.6" + "lint-staged": { + "*": "prettier --write", + "*.js": "eslint --fix", + "*.css": "stylelint --fix" }, "dependencies": { - "ansis": "^3.0.1", + "ansis": "^3.2.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", @@ -87,18 +70,35 @@ "pm2": "^5.3.1", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.22.6" + "systeminformation": "^5.22.7" }, - "lint-staged": { - "*": "prettier --write", - "*.js": "eslint --fix", - "*.css": "stylelint --fix" + "devDependencies": { + "@stylistic/eslint-plugin": "^1.8.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jest": "^28.3.0", + "eslint-plugin-jsdoc": "^48.2.3", + "eslint-plugin-package-json": "^0.13.1", + "eslint-plugin-unicorn": "^52.0.0", + "express-basic-auth": "^1.2.1", + "husky": "^9.0.11", + "jest": "^29.7.0", + "jsdom": "^24.0.0", + "lint-staged": "^15.2.2", + "playwright": "^1.43.1", + "prettier": "^3.2.5", + "sinon": "^17.0.1", + "stylelint": "^16.4.0", + "stylelint-config-standard": "^36.0.0", + "stylelint-prettier": "^5.0.0" }, - "_moduleAliases": { - "node_helper": "js/node_helper.js", - "logger": "js/logger.js" + "optionalDependencies": { + "electron": "^30.0.1" }, "engines": { "node": ">=18" + }, + "_moduleAliases": { + "node_helper": "js/node_helper.js", + "logger": "js/logger.js" } } diff --git a/vendor/package-lock.json b/vendor/package-lock.json index d21806b676..2df570b22a 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-free": "^6.5.1", + "@fortawesome/fontawesome-free": "^6.5.2", "animate.css": "^4.1.1", "moment": "^2.30.1", "moment-timezone": "^0.5.45", @@ -19,9 +19,9 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz", - "integrity": "sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.2.tgz", + "integrity": "sha512-hRILoInAx8GNT5IMkrtIt9blOdrqHOnPBH+k70aWUAqPZPgopb9G5EQJFpaBx/S8zp2fC+mPW349Bziuk1o28Q==", "hasInstallScript": true, "engines": { "node": ">=6" diff --git a/vendor/package.json b/vendor/package.json index 4758f9498e..efaa4f151e 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -2,16 +2,16 @@ "name": "magicmirror-vendors", "version": "1.0.0", "description": "Package for vendors use by MagicMirror² core.", + "bugs": { + "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" + }, "repository": { "type": "git", "url": "https://github.com/MagicMirrorOrg/MagicMirror" }, "license": "MIT", - "bugs": { - "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" - }, "dependencies": { - "@fortawesome/fontawesome-free": "^6.5.1", + "@fortawesome/fontawesome-free": "^6.5.2", "animate.css": "^4.1.1", "moment": "^2.30.1", "moment-timezone": "^0.5.45", From d1c17e7fc01e12f585532a72f79820900a6f397b Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 13 May 2024 22:36:35 +0200 Subject: [PATCH 058/418] =?UTF-8?q?weather=20module:=20Fixed=20precipitati?= =?UTF-8?q?onProbability=20in=20forecast=20=E2=80=A6=20(#3448)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …for provider openmeteo, fixed #3446 --- CHANGELOG.md | 2 ++ modules/default/weather/providers/openmeteo.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfa896f6dc..eceb4719fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ _This release is scheduled to be released on 2024-07-01._ ### Fixed +- [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) + ## [2.27.0] - 2024-04-01 Thanks to: @bugsounet, @crazyscot, @illimarkangur, @jkriegshauser, @khassel, @KristjanESPERANTO, @Paranoid93, @rejas, @sdetweil and @vppencilsharpener. diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index 5c4b232200..2e3a9d1814 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -405,7 +405,7 @@ WeatherProvider.register("openmeteo", { currentWeather.rain = parseFloat(weather.rain_sum); currentWeather.snow = parseFloat(weather.snowfall_sum * 10); currentWeather.precipitationAmount = parseFloat(weather.precipitation_sum); - currentWeather.precipitationProbability = parseFloat(weather.precipitation_probability); + currentWeather.precipitationProbability = parseFloat(weather.precipitation_hours * 100 / 24); currentWeather.uv_index = parseFloat(weather.uv_index_max); days.push(currentWeather); From cd0bc5b160a3de563577e951300620a5eec3eabf Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 20 May 2024 09:36:03 +0200 Subject: [PATCH 059/418] =?UTF-8?q?fixed=20type=3Ddaily=20for=20provider?= =?UTF-8?q?=20openmeteo=20having=20no=20data=20=E2=80=A6=20(#3451)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … when running after 23:00 Fixes #3449 --- CHANGELOG.md | 1 + modules/default/weather/providers/openmeteo.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eceb4719fe..825c539454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ _This release is scheduled to be released on 2024-07-01._ ### Fixed - [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) +- [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) ## [2.27.0] - 2024-04-01 diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index 2e3a9d1814..f223a33168 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -420,7 +420,7 @@ WeatherProvider.register("openmeteo", { const now = moment(); weathers.hourly.forEach((weather, i) => { - if ((hours.length === 0 && weather.time.hour() <= now.hour()) || hours.length >= this.config.maxEntries) { + if ((hours.length === 0 && weather.time <= now) || hours.length >= this.config.maxEntries) { return; } From 4bd66cb121c00f91a07900f3886c8d4c2b346f0c Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 8 Jun 2024 11:48:31 +0200 Subject: [PATCH 060/418] fixed type=daily for provider openmeteo showing nightly icons (#3459) in forecast when current time is "nightly" Fixes #3458 --- CHANGELOG.md | 1 + modules/default/weather/providers/openmeteo.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 825c539454..463828410f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ _This release is scheduled to be released on 2024-07-01._ - [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) - [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) +- [weather] Fixed type=daily for provider openmeteo showing nightly icons in forecast when current time is "nightly" (#3458) ## [2.27.0] - 2024-04-01 diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index f223a33168..e199caff65 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -401,7 +401,7 @@ WeatherProvider.register("openmeteo", { currentWeather.temperature = parseFloat((weather.apparent_temperature_max + weather.apparent_temperature_min) / 2); currentWeather.minTemperature = parseFloat(weather.apparent_temperature_min); currentWeather.maxTemperature = parseFloat(weather.apparent_temperature_max); - currentWeather.weatherType = this.convertWeatherType(weather.weathercode, currentWeather.isDayTime()); + currentWeather.weatherType = this.convertWeatherType(weather.weathercode, true); currentWeather.rain = parseFloat(weather.rain_sum); currentWeather.snow = parseFloat(weather.snowfall_sum * 10); currentWeather.precipitationAmount = parseFloat(weather.precipitation_sum); From 63324454a9c936de1b9ea09bd053b8f664bc284d Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 11 Jun 2024 06:54:17 +0200 Subject: [PATCH 061/418] update dependencies (#3460) see https://github.com/MagicMirrorOrg/MagicMirror/pull/3457#issuecomment-2159316713 --- CHANGELOG.md | 4 +- package-lock.json | 1040 +++++++++++++++++++++------------------------ package.json | 26 +- 3 files changed, 509 insertions(+), 561 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 463828410f..10edb8aaa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,7 +69,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T - added message in case where config.js is missing the module.export line PR #3383 - Fixed an issue where recurring events could extend past their recurrence end date (#3393) - Don't display any `npm WARN <....>` on install (#3399) -- Fixed move suncalc dependency to production from dev, as it is used by clock module +- [chore] Moved suncalc dependency to production from dev, as it is used by clock module - [compliments] Fix mirror not responding anymore when no compliments are to be shown (#3385) - [chore] Fixed mastermerge workflow (#3415) @@ -105,7 +105,7 @@ This release also marks the latest release by Michael Teeuw. For more info, plea - Update electron to v27 and update other dependencies as well as github actions - Update newsfeed: Use `html-to-text` instead of regex for transform description - Review ESLint config (#3269) -- Updated dependencies +- Update dependencies - Clock module: optionally display current moon phase in addition to rise/set times - electron is now per default started without gpu, if needed it must be enabled with new env var `ELECTRON_ENABLE_GPU=1` on startup (#3226) - Replace prettier by stylistic in ESLint config to lint JavaScript (and disable some rules for `config/config.js*` files) diff --git a/package-lock.json b/package-lock.json index 9be0e71cf5..5b6eaf2976 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,27 +23,27 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.18.0", - "pm2": "^5.3.1", + "pm2": "^5.4.0", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.22.7" + "systeminformation": "^5.22.11" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.8.0", + "@stylistic/eslint-plugin": "^1.8.1", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.3.0", - "eslint-plugin-jsdoc": "^48.2.3", - "eslint-plugin-package-json": "^0.13.1", - "eslint-plugin-unicorn": "^52.0.0", + "eslint-plugin-jest": "^28.6.0", + "eslint-plugin-jsdoc": "^48.2.9", + "eslint-plugin-package-json": "^0.14.0", + "eslint-plugin-unicorn": "^53.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", "jest": "^29.7.0", - "jsdom": "^24.0.0", - "lint-staged": "^15.2.2", - "playwright": "^1.43.1", - "prettier": "^3.2.5", + "jsdom": "^24.1.0", + "lint-staged": "^15.2.5", + "playwright": "^1.44.1", + "prettier": "^3.3.1", "sinon": "^17.0.1", - "stylelint": "^16.4.0", + "stylelint": "^16.6.1", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0" }, @@ -51,7 +51,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^30.0.1" + "electron": "^30.1.0" } }, "node_modules/@ampproject/remapping": { @@ -68,12 +68,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.24.2", + "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" }, "engines": { @@ -81,30 +81,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -129,12 +129,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", - "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.5", + "@babel/types": "^7.24.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -156,13 +156,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -181,62 +181,66 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", - "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-simple-access": "^7.24.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/helper-validator-identifier": "^7.24.5" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -246,86 +250,86 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", - "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", - "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "dependencies": { - "@babel/types": "^7.24.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", - "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, "dependencies": { - "@babel/types": "^7.24.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", - "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dev": true, "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", - "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -406,9 +410,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -478,12 +482,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -580,12 +584,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", - "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -595,33 +599,33 @@ } }, "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", - "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/types": "^7.24.5", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -639,13 +643,13 @@ } }, "node_modules/@babel/types": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", - "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.24.1", - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -659,9 +663,9 @@ "dev": true }, "node_modules/@csstools/css-parser-algorithms": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz", - "integrity": "sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.3.tgz", + "integrity": "sha512-xI/tL2zxzEbESvnSxwFgwvy5HS00oCXxL4MLs6HUiDcYfwowsoQaABKxUElp1ARITrINzBnsECOc1q0eg2GOrA==", "dev": true, "funding": [ { @@ -677,13 +681,13 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^2.2.4" + "@csstools/css-tokenizer": "^2.3.1" } }, "node_modules/@csstools/css-tokenizer": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz", - "integrity": "sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.3.1.tgz", + "integrity": "sha512-iMNHTyxLbBlWIfGtabT157LH9DUx9X8+Y3oymFEuMj8HNc+rpE3dPFGFgHjpKfjeFDjLjYIAIhXPGvS2lKxL9g==", "dev": true, "funding": [ { @@ -700,9 +704,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz", - "integrity": "sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==", + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.11.tgz", + "integrity": "sha512-uox5MVhvNHqitPP+SynrB1o8oPxPMt2JLgp5ghJOWf54WGQ5OKu47efne49r1SWqs3wRP8xSWjnO9MBKxhB1dA==", "dev": true, "funding": [ { @@ -718,14 +722,14 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.6.1", - "@csstools/css-tokenizer": "^2.2.4" + "@csstools/css-parser-algorithms": "^2.6.3", + "@csstools/css-tokenizer": "^2.3.1" } }, "node_modules/@csstools/selector-specificity": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.3.tgz", - "integrity": "sha512-KEPNw4+WW5AVEIyzC80rTbWEUatTW2lXpN8+8ILC8PiPeWPjwUzrPZDIOZ2wwqDmeqOYTdSGyL3+vE5GC3FB3Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.1.tgz", + "integrity": "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==", "dev": true, "funding": [ { @@ -745,9 +749,9 @@ } }, "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", - "integrity": "sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", "dev": true, "funding": { "type": "github", @@ -785,11 +789,14 @@ } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz", - "integrity": "sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==", + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz", + "integrity": "sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==", "dev": true, "dependencies": { + "@types/eslint": "^8.56.5", + "@types/estree": "^1.0.5", + "@typescript-eslint/types": "^7.2.0", "comment-parser": "1.4.1", "esquery": "^1.5.0", "jsdoc-type-pratt-parser": "~4.0.0" @@ -798,6 +805,19 @@ "node": ">=16" } }, + "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", + "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -813,9 +833,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -874,6 +894,7 @@ "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", "debug": "^4.3.1", @@ -918,7 +939,8 @@ "node_modules/@humanwhocodes/object-schema": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==" + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -1407,82 +1429,6 @@ "node": ">= 8" } }, - "node_modules/@opencensus/core": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.9.tgz", - "integrity": "sha512-31Q4VWtbzXpVUd2m9JS6HEaPjlKvNMOiF7lWKNmXF84yUcgfAFL5re7/hjDmdyQbOp32oGc+RFV78jXIldVz6Q==", - "dependencies": { - "continuation-local-storage": "^3.2.1", - "log-driver": "^1.2.7", - "semver": "^5.5.0", - "shimmer": "^1.2.0", - "uuid": "^3.2.1" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/@opencensus/core/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@opencensus/core/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/@opencensus/propagation-b3": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@opencensus/propagation-b3/-/propagation-b3-0.0.8.tgz", - "integrity": "sha512-PffXX2AL8Sh0VHQ52jJC4u3T0H6wDK6N/4bg7xh4ngMYOIi13aR1kzVvX1sVDBgfGwDOkMbl4c54Xm3tlPx/+A==", - "dependencies": { - "@opencensus/core": "^0.0.8", - "uuid": "^3.2.1" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/@opencensus/propagation-b3/node_modules/@opencensus/core": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@opencensus/core/-/core-0.0.8.tgz", - "integrity": "sha512-yUFT59SFhGMYQgX0PhoTR0LBff2BEhPrD9io1jWfF/VDbakRfs6Pq60rjv0Z7iaTav5gQlttJCX2+VPxFWCuoQ==", - "dependencies": { - "continuation-local-storage": "^3.2.1", - "log-driver": "^1.2.7", - "semver": "^5.5.0", - "shimmer": "^1.2.0", - "uuid": "^3.2.1" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/@opencensus/propagation-b3/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@opencensus/propagation-b3/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/@pm2/agent": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.3.tgz", @@ -1571,12 +1517,10 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/@pm2/io": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@pm2/io/-/io-5.0.2.tgz", - "integrity": "sha512-XAvrNoQPKOyO/jJyCu8jPhLzlyp35MEf7w/carHXmWKddPzeNOFSEpSEqMzPDawsvpxbE+i918cNN+MwgVsStA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.0.tgz", + "integrity": "sha512-sKUEgZoQ5/jRwTyMB1I7u2wXL6dG0j/F/M4ANJ7dJCApfW8nWC0RElMW2siEKvZ79iplIPAaWV27oyBoerEflw==", "dependencies": { - "@opencensus/core": "0.0.9", - "@opencensus/propagation-b3": "0.0.8", "async": "~2.6.1", "debug": "~4.3.1", "eventemitter2": "^6.3.1", @@ -1769,15 +1713,15 @@ "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.8.0.tgz", - "integrity": "sha512-JRR0lCDU97AiE0X6qTc/uf8Hv0yETUdyJgoNzTLUIWdhVJVe/KGPnFmEsO1iXfNUIS6vhv3JJ5vaZ2qtXhZe1g==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.8.1.tgz", + "integrity": "sha512-64My6I7uCcmSQ//427Pfg2vjSf9SDzfsGIWohNFgISMLYdC5BzJqDo647iDDJzSxINh3WTC0Ql46ifiKuOoTyA==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.8.0", - "@stylistic/eslint-plugin-jsx": "1.8.0", - "@stylistic/eslint-plugin-plus": "1.8.0", - "@stylistic/eslint-plugin-ts": "1.8.0", + "@stylistic/eslint-plugin-js": "1.8.1", + "@stylistic/eslint-plugin-jsx": "1.8.1", + "@stylistic/eslint-plugin-plus": "1.8.1", + "@stylistic/eslint-plugin-ts": "1.8.1", "@types/eslint": "^8.56.10" }, "engines": { @@ -1788,9 +1732,9 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.0.tgz", - "integrity": "sha512-jdvnzt+pZPg8TfclZlTZPiUbbima93ylvQ+wNgHLNmup3obY6heQvgewSu9i2CfS61BnRByv+F9fxQLPoNeHag==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.1.tgz", + "integrity": "sha512-c5c2C8Mos5tTQd+NWpqwEu7VT6SSRooAguFPMj1cp2RkTYl1ynKoXo8MWy3k4rkbzoeYHrqC2UlUzsroAN7wtQ==", "dev": true, "dependencies": { "@types/eslint": "^8.56.10", @@ -1807,12 +1751,12 @@ } }, "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.8.0.tgz", - "integrity": "sha512-PC7tYXipF03TTilGJva1amAham7qOAFXT5r5jLTY6iIxkFqyb6H7Ljx5pv8d7n98VyIVidOEKY/AP8vNzAFNKg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.8.1.tgz", + "integrity": "sha512-k1Eb6rcjMP+mmjvj+vd9y5KUdWn1OBkkPLHXhsrHt5lCDFZxJEs0aVQzE5lpYrtVZVkpc5esTtss/cPJux0lfA==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "^1.8.0", + "@stylistic/eslint-plugin-js": "^1.8.1", "@types/eslint": "^8.56.10", "estraverse": "^5.3.0", "picomatch": "^4.0.2" @@ -1825,9 +1769,9 @@ } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.8.0.tgz", - "integrity": "sha512-TkrjzzYmTuAaLvFwtxomsgMUD8g8PREOQOQzTfKmiJ6oc4XOyFW4q/L9ES1J3UFSLybNCwbhu36lhXJut1w2Sg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.8.1.tgz", + "integrity": "sha512-4+40H3lHYTN8OWz+US8CamVkO+2hxNLp9+CAjorI7top/lHqemhpJvKA1LD9Uh+WMY9DYWiWpL2+SZ2wAXY9fQ==", "dev": true, "dependencies": { "@types/eslint": "^8.56.10", @@ -1838,12 +1782,12 @@ } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.8.0.tgz", - "integrity": "sha512-WuCIhz4JEHxzhAWjrBASMGj6Or1wAjDqTsRIck3DRRrw/FJ8C/8AAuHPk8ECHNSDI5PZ0OT72nF2uSUn0aQq1w==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.8.1.tgz", + "integrity": "sha512-/q1m+ZuO1JHfiSF16EATFzv7XSJkc5W6DocfvH5o9oB6WWYFMF77fVoBWnKT3wGptPOc2hkRupRKhmeFROdfWA==", "dev": true, "dependencies": { - "@stylistic/eslint-plugin-js": "1.8.0", + "@stylistic/eslint-plugin-js": "1.8.1", "@types/eslint": "^8.56.10", "@typescript-eslint/utils": "^6.21.0" }, @@ -1904,9 +1848,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" @@ -2030,9 +1974,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", "dependencies": { "undici-types": "~5.26.4" } @@ -2503,9 +2447,9 @@ } }, "node_modules/ast-types/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/astral-regex": { "version": "2.0.0", @@ -2521,26 +2465,6 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, - "node_modules/async-listener": { - "version": "0.6.10", - "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", - "integrity": "sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw==", - "dependencies": { - "semver": "^5.3.0", - "shimmer": "^1.1.0" - }, - "engines": { - "node": "<=0.11.8 || >0.11.10" - } - }, - "node_modules/async-listener/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2820,20 +2744,20 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "dev": true, "funding": [ { @@ -2850,10 +2774,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -2897,15 +2821,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/builtins": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", - "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -2977,9 +2892,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001614", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz", - "integrity": "sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==", + "version": "1.0.30001632", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001632.tgz", + "integrity": "sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg==", "dev": true, "funding": [ { @@ -3345,15 +3260,6 @@ "node": ">= 0.6" } }, - "node_modules/continuation-local-storage": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", - "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", - "dependencies": { - "async-listener": "^0.6.0", - "emitter-listener": "^1.1.1" - } - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -3374,9 +3280,9 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/core-js-compat": { - "version": "3.37.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.0.tgz", - "integrity": "sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "dev": true, "dependencies": { "browserslist": "^4.23.0" @@ -3509,6 +3415,12 @@ "node": ">=18" } }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "dev": true + }, "node_modules/culvert": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", @@ -3597,9 +3509,9 @@ "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -3872,9 +3784,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-30.0.1.tgz", - "integrity": "sha512-iwxkI/n2wBd29NH7TH0ZY8aWGzCoKpzJz+D10u7aGSJi1TV6d4MSM3rWyKvT/UkAHkTKOEgYfUyCa2vWQm8L0g==", + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-30.1.0.tgz", + "integrity": "sha512-9O8m7kinjwMH5Df0hpXbwUaqI6pk3aJm1sKQUkQGCF7NDbNkGhu2BXgqaicPU6oe26zQPc5vtwWnHmiKlh1hYA==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -3890,19 +3802,11 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.752", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.752.tgz", - "integrity": "sha512-P3QJreYI/AUTcfBVrC4zy9KvnZWekViThgQMX/VpJ+IsOBbcX5JFpORM4qWapwWQ+agb2nYAOyn/4PMXOk0m2Q==", + "version": "1.4.796", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.796.tgz", + "integrity": "sha512-NglN/xprcM+SHD2XCli4oC6bWe6kHoytcyLKCWXmRL854F0qhPhaYgUswUsglnPxYaNQIg2uMY4BvaomIf3kLA==", "dev": true }, - "node_modules/emitter-listener": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", - "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", - "dependencies": { - "shimmer": "^1.2.0" - } - }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", @@ -4427,12 +4331,12 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.3.0.tgz", - "integrity": "sha512-5LjCSSno8E+IUCOX4hJiIb/upPIgpkaDEcaN/40gOcw26t/5UTLHFc4JdxKjOOvGTh0XdCu+fNr0fpOVNvcxMA==", + "version": "28.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", + "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^6.0.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" }, "engines": { "node": "^16.10.0 || ^18.12.0 || >=20.0.0" @@ -4452,19 +4356,18 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.3.tgz", - "integrity": "sha512-r9DMAmFs66VNvNqRLLjHejdnJtILrt3xGi+Qx0op0oRfFGVpOR1Hb3BC++MacseHx93d8SKYPhyrC9BS7Os2QA==", + "version": "48.2.9", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.9.tgz", + "integrity": "sha512-ErpKyr2mEUEkcdZ4nwW/cvDjClvAcvJMEXkGGll0wf8sro8h6qeQ3qlZyp1vM1dRk8Ap6rMdke8FnP94QBIaVQ==", "dev": true, "dependencies": { - "@es-joy/jsdoccomment": "~0.42.0", + "@es-joy/jsdoccomment": "~0.43.1", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.6.0", + "semver": "^7.6.2", "spdx-expression-parse": "^4.0.0" }, "engines": { @@ -4475,9 +4378,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.13.1.tgz", - "integrity": "sha512-aZkSvyJZRW4JKFhdoBhuPgc8sM/UAQN993uh956Yb8dSFCAV0Vkwrw09cuPL5onZ6ygF5pCqSs57wZRqGIwDQQ==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.14.0.tgz", + "integrity": "sha512-/Ls/KMVAEy4n5fXSEyj3GpfzLm9R1ErI9PrIBJwvuLRNbW3+1m7JWvkjgsBy2tmNfhtMhCGodhRDK2CN7Y4ADw==", "dev": true, "dependencies": { "detect-indent": "6.1.0", @@ -4497,17 +4400,17 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "52.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-52.0.0.tgz", - "integrity": "sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==", + "version": "53.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-53.0.0.tgz", + "integrity": "sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.5", "@eslint-community/eslint-utils": "^4.4.0", - "@eslint/eslintrc": "^2.1.4", + "@eslint/eslintrc": "^3.0.2", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", - "core-js-compat": "^3.34.0", + "core-js-compat": "^3.37.0", "esquery": "^1.5.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", @@ -4516,11 +4419,11 @@ "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", - "semver": "^7.5.4", + "semver": "^7.6.1", "strip-indent": "^3.0.0" }, "engines": { - "node": ">=16" + "node": ">=18.18" }, "funding": { "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" @@ -4529,6 +4432,92 @@ "eslint": ">=8.56.0" } }, + "node_modules/eslint-plugin-unicorn/node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/espree": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", + "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -4943,9 +4932,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5294,6 +5283,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5823,6 +5813,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -6927,9 +6918,9 @@ } }, "node_modules/jsdom": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.0.0.tgz", - "integrity": "sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==", + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz", + "integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==", "dev": true, "dependencies": { "cssstyle": "^4.0.1", @@ -6937,21 +6928,21 @@ "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.4", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.7", + "nwsapi": "^2.2.10", "parse5": "^7.1.2", - "rrweb-cssom": "^0.6.0", + "rrweb-cssom": "^0.7.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.3", + "tough-cookie": "^4.1.4", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.16.0", + "ws": "^8.17.0", "xml-name-validator": "^5.0.0" }, "engines": { @@ -7078,9 +7069,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz", - "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.31.0.tgz", + "integrity": "sha512-sBPIUGTNF0czz0mwGGUoKKJC8Q7On1GPbCSFPfyEsfHb2DyBG0Y4QtV+EVWpINSaiGKZblDNuF5AezxSgOhesQ==", "dev": true }, "node_modules/lazy": { @@ -7121,12 +7112,15 @@ } }, "node_modules/lilconfig": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", - "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lines-and-columns": { @@ -7136,21 +7130,21 @@ "dev": true }, "node_modules/lint-staged": { - "version": "15.2.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", - "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", - "dev": true, - "dependencies": { - "chalk": "5.3.0", - "commander": "11.1.0", - "debug": "4.3.4", - "execa": "8.0.1", - "lilconfig": "3.0.0", - "listr2": "8.0.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.4" + "version": "15.2.5", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.5.tgz", + "integrity": "sha512-j+DfX7W9YUvdzEZl3Rk47FhDF6xwDBV5wwsCPw6BwWZVPYJemusQmvb9bRsW23Sqsaa+vRloAWogbK4BUuU2zA==", + "dev": true, + "dependencies": { + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.4", + "execa": "~8.0.1", + "lilconfig": "~3.1.1", + "listr2": "~8.2.1", + "micromatch": "~4.0.7", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.4.2" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -7175,12 +7169,12 @@ } }, "node_modules/lint-staged/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/lint-staged/node_modules/execa": { @@ -7318,16 +7312,16 @@ } }, "node_modules/listr2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", - "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz", + "integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==", "dev": true, "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.0.0", - "rfdc": "^1.3.0", + "rfdc": "^1.3.1", "wrap-ansi": "^9.0.0" }, "engines": { @@ -7370,14 +7364,6 @@ "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true }, - "node_modules/log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "engines": { - "node": ">=0.8.6" - } - }, "node_modules/log-update": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", @@ -7598,12 +7584,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -7953,9 +7939,9 @@ "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" }, "node_modules/nwsapi": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz", - "integrity": "sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==", + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz", + "integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==", "dev": true }, "node_modules/object-assign": { @@ -8335,9 +8321,9 @@ "optional": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "node_modules/picomatch": { @@ -8449,12 +8435,12 @@ } }, "node_modules/playwright": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz", - "integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==", + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", + "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", "dev": true, "dependencies": { - "playwright-core": "1.43.1" + "playwright-core": "1.44.1" }, "bin": { "playwright": "cli.js" @@ -8467,9 +8453,9 @@ } }, "node_modules/playwright-core": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz", - "integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==", + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", + "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -8502,12 +8488,12 @@ } }, "node_modules/pm2": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.3.1.tgz", - "integrity": "sha512-DLVQHpSR1EegaTaRH3KbRXxpPVaqYwAp3uHSCtCsS++LSErvk07WSxuUnntFblBRqNU/w2KQyqs12mSq5wurkg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.0.tgz", + "integrity": "sha512-9TrDuckcSEnINoURygr3yfruK20qXuOUPOPQyIh4FIskQduyDNst9ys1XAt9YPY3RyGxVr2+x8Irsdma3klVQw==", "dependencies": { "@pm2/agent": "~2.0.0", - "@pm2/io": "~5.0.0", + "@pm2/io": "~6.0.0", "@pm2/js-api": "~0.8.0", "@pm2/pm2-version-check": "latest", "async": "~3.2.0", @@ -8522,6 +8508,7 @@ "enquirer": "2.3.6", "eventemitter2": "5.0.1", "fclone": "1.0.11", + "js-yaml": "~4.1.0", "mkdirp": "1.0.4", "needle": "2.4.0", "pidusage": "~3.0", @@ -8533,8 +8520,7 @@ "semver": "^7.2", "source-map-support": "0.5.21", "sprintf-js": "1.1.2", - "vizion": "~2.2.1", - "yamljs": "0.3.0" + "vizion": "~2.2.1" }, "bin": { "pm2": "bin/pm2", @@ -8543,7 +8529,7 @@ "pm2-runtime": "bin/pm2-runtime" }, "engines": { - "node": ">=10.0.0" + "node": ">=12.0.0" }, "optionalDependencies": { "pm2-sysmonit": "^1.2.8" @@ -8714,9 +8700,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", + "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -8741,9 +8727,9 @@ } }, "node_modules/prettier": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", + "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -9342,6 +9328,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dependencies": { "glob": "^7.1.3" }, @@ -9378,14 +9365,14 @@ } }, "node_modules/rrule/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.0.tgz", + "integrity": "sha512-KlSv0pm9kgQSRxXEMgtivPJ4h826YHsuob8pSHcfSZsSXGtvpEAie8S0AnXuObEJ7nhikOb4ahwxDm0H2yW17g==", "dev": true }, "node_modules/run-parallel": { @@ -9487,9 +9474,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" }, "node_modules/saxes": { "version": "6.0.0", @@ -9515,12 +9502,9 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "bin": { "semver": "bin/semver.js" }, @@ -9534,22 +9518,6 @@ "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "optional": true }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -9991,9 +9959,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", - "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", "dev": true }, "node_modules/sprintf-js": { @@ -10220,16 +10188,26 @@ } }, "node_modules/stylelint": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.4.0.tgz", - "integrity": "sha512-uSx7VMuXwLuYcNSIg+0/fFNv0WinsfLAqsVVy7h7p80clKOHiGE8pfY6UjqwylTHiJrRIahTl6a8FPxGezhWoA==", + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.6.1.tgz", + "integrity": "sha512-yNgz2PqWLkhH2hw6X9AweV9YvoafbAD5ZsFdKN9BvSDVwGvPh+AUIrn7lYwy1S7IHmtFin75LLfX1m0D2tHu8Q==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], "dependencies": { - "@csstools/css-parser-algorithms": "^2.6.1", - "@csstools/css-tokenizer": "^2.2.4", - "@csstools/media-query-list-parser": "^2.1.9", - "@csstools/selector-specificity": "^3.0.3", - "@dual-bundle/import-meta-resolve": "^4.0.0", + "@csstools/css-parser-algorithms": "^2.6.3", + "@csstools/css-tokenizer": "^2.3.1", + "@csstools/media-query-list-parser": "^2.1.11", + "@csstools/selector-specificity": "^3.1.1", + "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", @@ -10238,7 +10216,7 @@ "debug": "^4.3.4", "fast-glob": "^3.3.2", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^8.0.0", + "file-entry-cache": "^9.0.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -10246,16 +10224,16 @@ "ignore": "^5.3.1", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.30.0", + "known-css-properties": "^0.31.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", - "micromatch": "^4.0.5", + "micromatch": "^4.0.7", "normalize-path": "^3.0.0", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "postcss": "^8.4.38", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^7.0.0", - "postcss-selector-parser": "^6.0.16", + "postcss-selector-parser": "^6.1.0", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", @@ -10270,10 +10248,6 @@ }, "engines": { "node": ">=18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" } }, "node_modules/stylelint-config-recommended": { @@ -10332,28 +10306,28 @@ "dev": true }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.0.0.tgz", + "integrity": "sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw==", "dev": true, "dependencies": { - "flat-cache": "^4.0.0" + "flat-cache": "^5.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", "dev": true, "dependencies": { - "flatted": "^3.2.9", + "flatted": "^3.3.1", "keyv": "^4.5.4" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/stylelint/node_modules/is-fullwidth-code-point": { @@ -10517,9 +10491,9 @@ "dev": true }, "node_modules/systeminformation": { - "version": "5.22.7", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.7.tgz", - "integrity": "sha512-AWxlP05KeHbpGdgvZkcudJpsmChc2Y5Eo/GvxG/iUA/Aws5LZKHAMSeAo+V+nD+nxWZaxrwpWcnx4SH3oxNL3A==", + "version": "5.22.11", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.11.tgz", + "integrity": "sha512-aLws5yi4KCHTb0BVvbodQY5bY8eW4asMRDTxTW46hqw9lGjACX6TlLdJrkdoHYRB0qs+MekqEq1zG7WDnWE8Ug==", "os": [ "darwin", "linux", @@ -10558,9 +10532,9 @@ } }, "node_modules/table/node_modules/ajv": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", - "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", @@ -10930,9 +10904,9 @@ } }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", + "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -10978,9 +10952,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.14.tgz", - "integrity": "sha512-JixKH8GR2pWYshIPUg/NujK3JO7JiqEEUiNArE86NQyrgUuZeTlZQN3xuS/yiV5Kb48ev9K6RqNkaJjXsdg7Jw==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "dev": true, "funding": [ { @@ -10998,7 +10972,7 @@ ], "dependencies": { "escalade": "^3.1.2", - "picocolors": "^1.0.0" + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -11086,13 +11060,10 @@ } }, "node_modules/validate-npm-package-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", - "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, - "dependencies": { - "builtins": "^5.0.0" - }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -11377,40 +11348,17 @@ "dev": true }, "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", "dev": true, + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } }, - "node_modules/yamljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", - "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", - "dependencies": { - "argparse": "^1.0.7", - "glob": "^7.0.5" - }, - "bin": { - "json2yaml": "bin/json2yaml", - "yaml2json": "bin/yaml2json" - } - }, - "node_modules/yamljs/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/yamljs/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index da54181ef6..25c4622f58 100644 --- a/package.json +++ b/package.json @@ -67,32 +67,32 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.18.0", - "pm2": "^5.3.1", + "pm2": "^5.4.0", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.22.7" + "systeminformation": "^5.22.11" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.8.0", + "@stylistic/eslint-plugin": "^1.8.1", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.3.0", - "eslint-plugin-jsdoc": "^48.2.3", - "eslint-plugin-package-json": "^0.13.1", - "eslint-plugin-unicorn": "^52.0.0", + "eslint-plugin-jest": "^28.6.0", + "eslint-plugin-jsdoc": "^48.2.9", + "eslint-plugin-package-json": "^0.14.0", + "eslint-plugin-unicorn": "^53.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", "jest": "^29.7.0", - "jsdom": "^24.0.0", - "lint-staged": "^15.2.2", - "playwright": "^1.43.1", - "prettier": "^3.2.5", + "jsdom": "^24.1.0", + "lint-staged": "^15.2.5", + "playwright": "^1.44.1", + "prettier": "^3.3.1", "sinon": "^17.0.1", - "stylelint": "^16.4.0", + "stylelint": "^16.6.1", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0" }, "optionalDependencies": { - "electron": "^30.0.1" + "electron": "^30.1.0" }, "engines": { "node": ">=18" From bc27c46723a31db40e584cfb6cd02fdc8aee1585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Wed, 19 Jun 2024 22:11:04 +0200 Subject: [PATCH 062/418] =?UTF-8?q?MM=C2=B2=20Main=20core=20use=20node=20>?= =?UTF-8?q?=3D=20v20=20//=20delete=20node=20v18=20from=20test=20suite=20(#?= =?UTF-8?q?3463)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #3462 --- .github/workflows/automated-tests.yaml | 2 +- .github/workflows/electronRebuild.yaml | 8 ++++++++ CHANGELOG.md | 3 +++ package.json | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 18795146b6..301b08d47b 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -18,7 +18,7 @@ jobs: timeout-minutes: 30 strategy: matrix: - node-version: [18.x, 20.x, 22.x] + node-version: [20.x, 22.x] steps: - name: "Checkout code" uses: actions/checkout@v4 diff --git a/.github/workflows/electronRebuild.yaml b/.github/workflows/electronRebuild.yaml index 5c6e3f7db3..f9cc50957f 100644 --- a/.github/workflows/electronRebuild.yaml +++ b/.github/workflows/electronRebuild.yaml @@ -6,9 +6,17 @@ jobs: rebuild: name: Run electron-rebuild runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20.x, 22.x] steps: - name: Checkout code uses: actions/checkout@v4 + - name: "Use Node.js ${{ matrix.node-version }}" + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + check-latest: true - name: Install MagicMirror run: npm run install-mm - name: Install @electron/rebuild diff --git a/CHANGELOG.md b/CHANGELOG.md index 10edb8aaa6..e37ab714f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,12 @@ _This release is scheduled to be released on 2024-07-01._ ### Removed +- [test suite] delete node v18 support + ### Updated - [chore] Update dependencies including electron to v30 +- [core] use node >= v20 ### Fixed diff --git a/package.json b/package.json index 25c4622f58..c7aebff9d5 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "electron": "^30.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "_moduleAliases": { "node_helper": "js/node_helper.js", From 9cbd30f2962168481ae594deedc0d5d3107f7d7c Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 19 Jun 2024 22:21:46 +0200 Subject: [PATCH 063/418] update dependencies incl. electron v31 (#3473) --- CHANGELOG.md | 2 +- package-lock.json | 1491 ++++++++++++++++++++++++++++++++++++--------- package.json | 16 +- 3 files changed, 1214 insertions(+), 295 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e37ab714f3..ba1a3c8baf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ _This release is scheduled to be released on 2024-07-01._ ### Updated -- [chore] Update dependencies including electron to v30 +- [chore] Update dependencies including electron to v31 - [core] use node >= v20 ### Fixed diff --git a/package-lock.json b/package-lock.json index 5b6eaf2976..22c2ad3242 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.18.0", - "pm2": "^5.4.0", + "pm2": "^5.4.1", "socket.io": "^4.7.5", "suncalc": "^1.9.0", "systeminformation": "^5.22.11" @@ -32,17 +32,17 @@ "@stylistic/eslint-plugin": "^1.8.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.2.9", - "eslint-plugin-package-json": "^0.14.0", - "eslint-plugin-unicorn": "^53.0.0", + "eslint-plugin-jsdoc": "^48.2.12", + "eslint-plugin-package-json": "^0.15.0", + "eslint-plugin-unicorn": "^54.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", "jest": "^29.7.0", "jsdom": "^24.1.0", - "lint-staged": "^15.2.5", + "lint-staged": "^15.2.7", "playwright": "^1.44.1", - "prettier": "^3.3.1", - "sinon": "^17.0.1", + "prettier": "^3.3.2", + "sinon": "^18.0.0", "stylelint": "^16.6.1", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0" @@ -51,7 +51,7 @@ "node": ">=18" }, "optionalDependencies": { - "electron": "^30.1.0" + "electron": "^31.0.1" } }, "node_modules/@ampproject/remapping": { @@ -59,6 +59,7 @@ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -72,6 +73,7 @@ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" @@ -85,6 +87,7 @@ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -94,6 +97,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -124,6 +128,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -133,6 +138,7 @@ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7", "@jridgewell/gen-mapping": "^0.3.5", @@ -148,6 +154,7 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -160,6 +167,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -176,6 +184,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -185,6 +194,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -197,6 +207,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.24.7", "@babel/types": "^7.24.7" @@ -210,6 +221,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -222,6 +234,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -235,6 +248,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", @@ -254,6 +268,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -263,6 +278,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -276,6 +292,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.24.7" }, @@ -288,6 +305,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -297,6 +315,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -306,6 +325,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -315,6 +335,7 @@ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.24.7", "@babel/types": "^7.24.7" @@ -328,6 +349,7 @@ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", @@ -343,6 +365,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -355,6 +378,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -369,6 +393,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -377,13 +402,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -393,6 +420,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -402,6 +430,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -414,6 +443,7 @@ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -426,6 +456,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -438,6 +469,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -450,6 +482,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -462,6 +495,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -474,6 +508,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -486,6 +521,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -501,6 +537,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -513,6 +550,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -525,6 +563,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -537,6 +576,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -549,6 +589,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -561,6 +602,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -573,6 +615,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -588,6 +631,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -603,6 +647,7 @@ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.24.7", @@ -617,6 +662,7 @@ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.24.7", @@ -638,6 +684,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -647,6 +694,7 @@ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.24.7", "@babel/helper-validator-identifier": "^7.24.7", @@ -660,7 +708,8 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@csstools/css-parser-algorithms": { "version": "2.6.3", @@ -677,6 +726,7 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { "node": "^14 || ^16 || >=18" }, @@ -699,6 +749,7 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { "node": "^14 || ^16 || >=18" } @@ -718,6 +769,7 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { "node": "^14 || ^16 || >=18" }, @@ -741,6 +793,7 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT-0", "engines": { "node": "^14 || ^16 || >=18" }, @@ -753,6 +806,7 @@ "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -762,6 +816,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "license": "MIT", "optional": true, "dependencies": { "debug": "^4.1.1", @@ -783,6 +838,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", "optional": true, "bin": { "semver": "bin/semver.js" @@ -793,6 +849,7 @@ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz", "integrity": "sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint": "^8.56.5", "@types/estree": "^1.0.5", @@ -806,10 +863,11 @@ } }, "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.0.tgz", - "integrity": "sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -822,6 +880,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -836,6 +895,7 @@ "version": "4.10.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -844,6 +904,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -866,6 +927,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -875,6 +937,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -886,6 +949,7 @@ "version": "8.57.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -895,6 +959,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "deprecated": "Use @eslint/config-array instead", + "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", "debug": "^4.3.1", @@ -908,6 +973,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -917,6 +983,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -928,6 +995,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -940,13 +1008,15 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead" + "deprecated": "Use @eslint/object-schema instead", + "license": "BSD-3-Clause" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -963,6 +1033,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } @@ -972,6 +1043,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -985,6 +1057,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -998,6 +1071,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -1010,6 +1084,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -1025,6 +1100,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -1037,6 +1113,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1045,13 +1122,15 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1061,6 +1140,7 @@ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -1078,6 +1158,7 @@ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/reporters": "^29.7.0", @@ -1131,6 +1212,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } @@ -1140,6 +1222,7 @@ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", @@ -1155,6 +1238,7 @@ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.7.0", "jest-snapshot": "^29.7.0" @@ -1168,6 +1252,7 @@ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3" }, @@ -1180,6 +1265,7 @@ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", @@ -1197,6 +1283,7 @@ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -1212,6 +1299,7 @@ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, + "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", @@ -1255,6 +1343,7 @@ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.27.8" }, @@ -1267,6 +1356,7 @@ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", @@ -1281,6 +1371,7 @@ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", @@ -1296,6 +1387,7 @@ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", @@ -1311,6 +1403,7 @@ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", @@ -1337,6 +1430,7 @@ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -1354,6 +1448,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -1368,6 +1463,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1377,6 +1473,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1385,13 +1482,15 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1401,6 +1500,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1413,6 +1513,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", "engines": { "node": ">= 8" } @@ -1421,6 +1522,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1430,9 +1532,10 @@ } }, "node_modules/@pm2/agent": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.3.tgz", - "integrity": "sha512-xkqqCoTf5VsciMqN0vb9jthW7olVAi4KRFNddCc7ZkeJZ3i8QwZANr4NSH2H5DvseRFHq7MiPspRY/EWAFWWTg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz", + "integrity": "sha512-n7WYvvTJhHLS2oBb1PjOtgLpMhgImOq8sXkPBw6smeg9LJBWZjiEgPKOpR8mn9UJZsB5P3W4V/MyvNnp31LKeA==", + "license": "AGPL-3.0", "dependencies": { "async": "~3.2.0", "chalk": "~3.0.0", @@ -1446,13 +1549,14 @@ "pm2-axon-rpc": "~0.7.0", "proxy-agent": "~6.3.0", "semver": "~7.5.0", - "ws": "~7.4.0" + "ws": "~7.5.10" } }, "node_modules/@pm2/agent/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1464,12 +1568,14 @@ "node_modules/@pm2/agent/node_modules/dayjs": { "version": "1.8.36", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz", - "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==" + "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==", + "license": "MIT" }, "node_modules/@pm2/agent/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -1481,6 +1587,7 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1492,9 +1599,10 @@ } }, "node_modules/@pm2/agent/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", "engines": { "node": ">=8.3.0" }, @@ -1514,12 +1622,14 @@ "node_modules/@pm2/agent/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, "node_modules/@pm2/io": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.0.tgz", "integrity": "sha512-sKUEgZoQ5/jRwTyMB1I7u2wXL6dG0j/F/M4ANJ7dJCApfW8nWC0RElMW2siEKvZ79iplIPAaWV27oyBoerEflw==", + "license": "Apache-2", "dependencies": { "async": "~2.6.1", "debug": "~4.3.1", @@ -1538,6 +1648,7 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", "dependencies": { "lodash": "^4.17.14" } @@ -1545,12 +1656,14 @@ "node_modules/@pm2/io/node_modules/eventemitter2": { "version": "6.4.9", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", + "license": "MIT" }, "node_modules/@pm2/io/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -1562,6 +1675,7 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1575,12 +1689,14 @@ "node_modules/@pm2/io/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, "node_modules/@pm2/js-api": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.8.0.tgz", "integrity": "sha512-nmWzrA/BQZik3VBz+npRcNIu01kdBhWL0mxKmP1ciF/gTcujPTQqt027N9fc1pK9ERM8RipFhymw7RcmCyOEYA==", + "license": "Apache-2", "dependencies": { "async": "^2.6.3", "debug": "~4.3.1", @@ -1596,6 +1712,7 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", "dependencies": { "lodash": "^4.17.14" } @@ -1603,12 +1720,14 @@ "node_modules/@pm2/js-api/node_modules/eventemitter2": { "version": "6.4.9", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", + "license": "MIT" }, "node_modules/@pm2/js-api/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", "engines": { "node": ">=8.3.0" }, @@ -1629,6 +1748,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz", "integrity": "sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==", + "license": "MIT", "dependencies": { "debug": "^4.3.1" } @@ -1637,6 +1757,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==", + "license": "MIT", "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" @@ -1649,12 +1770,14 @@ "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", "optional": true, "engines": { "node": ">=10" @@ -1668,6 +1791,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } @@ -1677,6 +1801,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } @@ -1686,6 +1811,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^2.0.0", "lodash.get": "^4.4.2", @@ -1697,6 +1823,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" } @@ -1705,18 +1832,21 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true + "dev": true, + "license": "(Unlicense OR Apache-2.0)" }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.8.1.tgz", "integrity": "sha512-64My6I7uCcmSQ//427Pfg2vjSf9SDzfsGIWohNFgISMLYdC5BzJqDo647iDDJzSxINh3WTC0Ql46ifiKuOoTyA==", "dev": true, + "license": "MIT", "dependencies": { "@stylistic/eslint-plugin-js": "1.8.1", "@stylistic/eslint-plugin-jsx": "1.8.1", @@ -1736,6 +1866,7 @@ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.1.tgz", "integrity": "sha512-c5c2C8Mos5tTQd+NWpqwEu7VT6SSRooAguFPMj1cp2RkTYl1ynKoXo8MWy3k4rkbzoeYHrqC2UlUzsroAN7wtQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint": "^8.56.10", "acorn": "^8.11.3", @@ -1755,6 +1886,7 @@ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.8.1.tgz", "integrity": "sha512-k1Eb6rcjMP+mmjvj+vd9y5KUdWn1OBkkPLHXhsrHt5lCDFZxJEs0aVQzE5lpYrtVZVkpc5esTtss/cPJux0lfA==", "dev": true, + "license": "MIT", "dependencies": { "@stylistic/eslint-plugin-js": "^1.8.1", "@types/eslint": "^8.56.10", @@ -1773,6 +1905,7 @@ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.8.1.tgz", "integrity": "sha512-4+40H3lHYTN8OWz+US8CamVkO+2hxNLp9+CAjorI7top/lHqemhpJvKA1LD9Uh+WMY9DYWiWpL2+SZ2wAXY9fQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint": "^8.56.10", "@typescript-eslint/utils": "^6.21.0" @@ -1786,6 +1919,7 @@ "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.8.1.tgz", "integrity": "sha512-/q1m+ZuO1JHfiSF16EATFzv7XSJkc5W6DocfvH5o9oB6WWYFMF77fVoBWnKT3wGptPOc2hkRupRKhmeFROdfWA==", "dev": true, + "license": "MIT", "dependencies": { "@stylistic/eslint-plugin-js": "1.8.1", "@types/eslint": "^8.56.10", @@ -1802,6 +1936,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", "optional": true, "dependencies": { "defer-to-connect": "^2.0.0" @@ -1813,13 +1948,15 @@ "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -1833,6 +1970,7 @@ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } @@ -1842,6 +1980,7 @@ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -1852,6 +1991,7 @@ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" } @@ -1860,6 +2000,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", "optional": true, "dependencies": { "@types/http-cache-semantics": "*", @@ -1871,12 +2012,14 @@ "node_modules/@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -1886,6 +2029,7 @@ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -1895,13 +2039,15 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, + "license": "MIT", "dependencies": { "@types/minimatch": "*", "@types/node": "*" @@ -1912,6 +2058,7 @@ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -1920,19 +2067,22 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "license": "MIT", "optional": true }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -1942,6 +2092,7 @@ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/istanbul-lib-report": "*" } @@ -1950,18 +2101,21 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*" @@ -1971,12 +2125,14 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "20.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", - "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "version": "20.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.6.tgz", + "integrity": "sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==", + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -1985,12 +2141,14 @@ "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/responselike": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*" @@ -2000,19 +2158,22 @@ "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } @@ -2021,12 +2182,14 @@ "version": "21.0.3", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/yauzl": { "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*" @@ -2037,6 +2200,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0" @@ -2054,6 +2218,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, + "license": "MIT", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -2067,6 +2232,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", @@ -2095,6 +2261,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -2120,6 +2287,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" @@ -2135,12 +2303,14 @@ "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "license": "ISC" }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -2150,9 +2320,10 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -2164,6 +2335,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -2172,6 +2344,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -2183,6 +2356,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2197,12 +2371,14 @@ "node_modules/amp": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", - "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==" + "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==", + "license": "MIT" }, "node_modules/amp-message": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz", "integrity": "sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==", + "license": "MIT", "dependencies": { "amp": "0.3.1" } @@ -2211,6 +2387,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "license": "MIT", "engines": { "node": ">=6" } @@ -2220,6 +2397,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -2235,6 +2413,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2246,6 +2425,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -2254,6 +2434,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -2268,6 +2449,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.2.0.tgz", "integrity": "sha512-Yk3BkHH9U7oPyCN3gL5Tc7CpahG/+UFv/6UG03C311Vy9lzRmA5uoxDTpU9CO3rGHL6KzJz/pdDeXZCZ5Mu/Sg==", + "license": "ISC", "engines": { "node": ">=15" } @@ -2276,6 +2458,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -2288,6 +2471,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -2300,6 +2484,7 @@ "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" } @@ -2307,12 +2492,14 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -2327,13 +2514,15 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/array-includes": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -2354,6 +2543,7 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2363,6 +2553,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -2383,6 +2574,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -2401,6 +2593,7 @@ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -2418,6 +2611,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -2439,6 +2633,7 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", "dependencies": { "tslib": "^2.0.1" }, @@ -2449,13 +2644,15 @@ "node_modules/ast-types/node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "license": "0BSD" }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2463,17 +2660,20 @@ "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -2488,6 +2688,7 @@ "version": "1.6.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.4", "form-data": "^4.0.0", @@ -2499,6 +2700,7 @@ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", @@ -2520,6 +2722,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -2536,6 +2739,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -2552,6 +2756,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -2561,6 +2766,7 @@ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -2576,6 +2782,7 @@ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -2599,6 +2806,7 @@ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, + "license": "MIT", "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" @@ -2613,12 +2821,14 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } @@ -2628,6 +2838,7 @@ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "5.1.2" }, @@ -2639,12 +2850,14 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/basic-ftp": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -2653,6 +2866,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -2664,6 +2878,7 @@ "version": "0.1.81", "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==", + "license": "MIT", "bin": { "blessed": "bin/tput.js" }, @@ -2674,17 +2889,20 @@ "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "license": "MIT" }, "node_modules/bodec": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", - "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==" + "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==", + "license": "MIT" }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -2708,6 +2926,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -2716,6 +2935,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -2726,12 +2946,14 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "license": "MIT", "optional": true }, "node_modules/brace-expansion": { @@ -2739,6 +2961,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -2747,6 +2970,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -2773,6 +2997,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001629", "electron-to-chromium": "^1.4.796", @@ -2791,6 +3016,7 @@ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "node-int64": "^0.4.0" } @@ -2799,6 +3025,7 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", "optional": true, "engines": { "node": "*" @@ -2807,13 +3034,15 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" }, "node_modules/builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -2825,6 +3054,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -2833,6 +3063,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", "optional": true, "engines": { "node": ">=10.6.0" @@ -2842,6 +3073,7 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", "optional": true, "dependencies": { "clone-response": "^1.0.2", @@ -2860,6 +3092,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2878,6 +3111,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -2887,14 +3121,15 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001632", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001632.tgz", - "integrity": "sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg==", + "version": "1.0.30001636", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", + "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", "dev": true, "funding": [ { @@ -2909,12 +3144,14 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2931,6 +3168,7 @@ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -2938,12 +3176,14 @@ "node_modules/charm": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", - "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==" + "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==", + "license": "MIT/X11" }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2967,6 +3207,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2985,6 +3226,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } @@ -2993,12 +3235,14 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/clarinet": { "version": "0.12.6", "resolved": "https://registry.npmjs.org/clarinet/-/clarinet-0.12.6.tgz", "integrity": "sha512-0FR+TrvLbYHLjhzs9oeIbd3yfZmd4u2DzYQEjUTm2dNfh4Y/9RIRWPjsm3aBtrVEpjKI7+lWa4ouqEXoml84mQ==", + "license": "BSD-2-Clause", "engines": { "chrome": ">=16.0.912", "firefox": ">=0.8.0", @@ -3010,6 +3254,7 @@ "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -3022,6 +3267,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -3031,6 +3277,7 @@ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, + "license": "MIT", "dependencies": { "restore-cursor": "^4.0.0" }, @@ -3056,6 +3303,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3069,6 +3317,7 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, + "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" @@ -3085,6 +3334,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -3098,13 +3348,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cliui/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" } @@ -3114,6 +3366,7 @@ "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", @@ -3128,6 +3381,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3144,6 +3398,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "license": "MIT", "optional": true, "dependencies": { "mimic-response": "^1.0.0" @@ -3157,6 +3412,7 @@ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, + "license": "MIT", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -3166,12 +3422,14 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -3182,24 +3440,28 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -3211,6 +3473,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -3220,6 +3483,7 @@ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12.0.0" } @@ -3227,12 +3491,14 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" }, "node_modules/console-stamp": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-3.1.2.tgz", "integrity": "sha512-ab66x3NxOTxPuq71dI6gXEiw2X6ql4Le5gZz0bm7FW3FSCB00eztra/oQUuCoCGlsyKOxtULnHwphzMrRtzMBg==", + "license": "MIT", "dependencies": { "chalk": "^4.1.2", "dateformat": "^4.6.3" @@ -3245,6 +3511,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -3256,6 +3523,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3264,12 +3532,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3277,13 +3547,15 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/core-js-compat": { "version": "3.37.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.23.0" }, @@ -3296,6 +3568,7 @@ "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -3309,6 +3582,7 @@ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, + "license": "MIT", "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -3335,6 +3609,7 @@ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -3354,12 +3629,14 @@ "node_modules/croner": { "version": "4.1.97", "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", - "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==", + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3374,6 +3651,7 @@ "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12 || >=16" } @@ -3383,6 +3661,7 @@ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "dev": true, + "license": "MIT", "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -3396,6 +3675,7 @@ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -3408,6 +3688,7 @@ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", "dev": true, + "license": "MIT", "dependencies": { "rrweb-cssom": "^0.6.0" }, @@ -3419,17 +3700,20 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/culvert": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", - "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==" + "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==", + "license": "MIT" }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "license": "MIT", "engines": { "node": ">= 14" } @@ -3439,6 +3723,7 @@ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, + "license": "MIT", "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0" @@ -3451,6 +3736,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -3467,6 +3753,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -3483,6 +3770,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -3499,6 +3787,7 @@ "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", "engines": { "node": "*" } @@ -3506,12 +3795,14 @@ "node_modules/dayjs": { "version": "1.11.11", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", - "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", + "license": "MIT" }, "node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -3528,12 +3819,14 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", "optional": true, "dependencies": { "mimic-response": "^3.1.0" @@ -3549,6 +3842,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "optional": true, "engines": { "node": ">=10" @@ -3562,6 +3856,7 @@ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, + "license": "MIT", "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -3574,12 +3869,14 @@ "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3588,6 +3885,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", "optional": true, "engines": { "node": ">=10" @@ -3597,6 +3895,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -3613,6 +3912,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -3629,6 +3929,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "license": "MIT", "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -3642,6 +3943,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -3650,6 +3952,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -3658,6 +3961,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -3668,6 +3972,7 @@ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3677,6 +3982,7 @@ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3685,12 +3991,14 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT", "optional": true }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -3700,6 +4008,7 @@ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -3709,6 +4018,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -3720,6 +4030,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -3731,6 +4042,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -3749,12 +4061,14 @@ "type": "github", "url": "https://github.com/sponsors/fb55" } - ] + ], + "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" }, @@ -3769,6 +4083,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -3781,13 +4096,15 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/electron": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-30.1.0.tgz", - "integrity": "sha512-9O8m7kinjwMH5Df0hpXbwUaqI6pk3aJm1sKQUkQGCF7NDbNkGhu2BXgqaicPU6oe26zQPc5vtwWnHmiKlh1hYA==", + "version": "31.0.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.0.1.tgz", + "integrity": "sha512-2eBcp4iqLkTsml6mMq+iqrS5u3kJ/2mpOLP7Mj7lo0uNK3OyfNqRS9z1ArsHjBF2/HV250Te/O9nKrwQRTX/+g==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "@electron/get": "^2.0.0", @@ -3802,16 +4119,18 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.796", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.796.tgz", - "integrity": "sha512-NglN/xprcM+SHD2XCli4oC6bWe6kHoytcyLKCWXmRL854F0qhPhaYgUswUsglnPxYaNQIg2uMY4BvaomIf3kLA==", - "dev": true + "version": "1.4.806", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.806.tgz", + "integrity": "sha512-nkoEX2QIB8kwCOtvtgwhXWy2IHVcOLQZu9Qo36uaGB835mdX/h8uLRlosL6QIhLVUnAiicXRW00PwaPZC74Nrg==", + "dev": true, + "license": "ISC" }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -3823,12 +4142,14 @@ "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -3837,15 +4158,17 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", "optional": true, "dependencies": { "once": "^1.4.0" } }, "node_modules/engine.io": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", - "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", + "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "license": "MIT", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -3856,7 +4179,7 @@ "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" @@ -3866,6 +4189,7 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -3874,34 +4198,16 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/engine.io/node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "license": "MIT", "dependencies": { "ansi-colors": "^4.1.1" }, @@ -3913,6 +4219,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -3925,6 +4232,7 @@ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "devOptional": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3933,6 +4241,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/envsub/-/envsub-4.1.0.tgz", "integrity": "sha512-B44hta3xNFu6+zDhOha1TIrZkQHGDO3G5K8D2sJIkm/s3XyQjxWBGp1B+b/Y74Go1PqMP+cp8moPR4JullnD9Q==", + "license": "ISC", "dependencies": { "bluebird": "^3.7.2", "chalk": "^3.0.0", @@ -3952,6 +4261,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3965,6 +4275,7 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } @@ -3973,6 +4284,7 @@ "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -4032,6 +4344,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -4043,6 +4356,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -4051,6 +4365,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -4062,6 +4377,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -4076,6 +4392,7 @@ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.0" } @@ -4084,6 +4401,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "license": "MIT", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -4100,6 +4418,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "license": "MIT", "optional": true }, "node_modules/escalade": { @@ -4107,6 +4426,7 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4114,12 +4434,14 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -4131,6 +4453,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -4151,6 +4474,7 @@ "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -4206,6 +4530,7 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -4217,6 +4542,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -4226,6 +4552,7 @@ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -4243,6 +4570,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -4252,6 +4580,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.7", "array.prototype.findlastindex": "^1.2.3", @@ -4283,6 +4612,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4293,6 +4623,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -4302,6 +4633,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -4314,6 +4646,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4326,6 +4659,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -4335,6 +4669,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" }, @@ -4356,10 +4691,11 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.9", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.9.tgz", - "integrity": "sha512-ErpKyr2mEUEkcdZ4nwW/cvDjClvAcvJMEXkGGll0wf8sro8h6qeQ3qlZyp1vM1dRk8Ap6rMdke8FnP94QBIaVQ==", + "version": "48.2.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.12.tgz", + "integrity": "sha512-sO9sKkJx5ovWoRk9hV0YiNzXQ4Z6j27CqE/po2E3wddZVuy9wvKPSTiIhpxMTrP/qURvKayJIDB2+o9kyCW1Fw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@es-joy/jsdoccomment": "~0.43.1", "are-docs-informative": "^0.0.2", @@ -4378,10 +4714,11 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.14.0.tgz", - "integrity": "sha512-/Ls/KMVAEy4n5fXSEyj3GpfzLm9R1ErI9PrIBJwvuLRNbW3+1m7JWvkjgsBy2tmNfhtMhCGodhRDK2CN7Y4ADw==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.0.tgz", + "integrity": "sha512-XPPehRGjoN2YPnwH/Vo9GTBTTSoJ9uveqKr7tCDskgKwXjtAfMIw4NyGvmTq4GLlnl+cw0VeKTC75863f2DBFw==", "dev": true, + "license": "MIT", "dependencies": { "detect-indent": "6.1.0", "detect-newline": "3.1.0", @@ -4400,10 +4737,11 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "53.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-53.0.0.tgz", - "integrity": "sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==", + "version": "54.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-54.0.0.tgz", + "integrity": "sha512-XxYLRiYtAWiAjPv6z4JREby1TAE2byBC7wlh0V4vWDCpccOSU1KovWV//jqPXF6bq3WKxqX9rdjoRQ1EhdmNdQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.24.5", "@eslint-community/eslint-utils": "^4.4.0", @@ -4437,6 +4775,7 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -4460,6 +4799,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4470,6 +4810,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -4478,12 +4819,13 @@ } }, "node_modules/eslint-plugin-unicorn/node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.0.0" }, @@ -4499,6 +4841,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -4511,6 +4854,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4522,6 +4866,7 @@ "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -4537,6 +4882,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -4548,6 +4894,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4557,6 +4904,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4568,6 +4916,7 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -4584,6 +4933,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -4596,6 +4946,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -4607,6 +4958,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -4618,6 +4970,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -4626,6 +4979,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -4634,6 +4988,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4641,19 +4996,22 @@ "node_modules/eventemitter2": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", - "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==" + "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==", + "license": "MIT" }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -4677,6 +5035,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4698,6 +5057,7 @@ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", @@ -4713,6 +5073,7 @@ "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -4755,6 +5116,7 @@ "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==", "dev": true, + "license": "MIT", "dependencies": { "basic-auth": "^2.0.1" } @@ -4763,6 +5125,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/express-ipfilter/-/express-ipfilter-1.3.2.tgz", "integrity": "sha512-yMzCWGuVMnR8CFlsIC2spHWoQYp9vtyZXUgS/JdV5GOJgrz6zmKOEZsA4eF1XrxkOIVzaVk6yzTBk65pBhliNw==", + "license": "MIT", "dependencies": { "ip": "^2.0.1", "lodash": "^4.17.11", @@ -4777,6 +5140,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -4784,12 +5148,14 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", "optional": true, "dependencies": { "debug": "^4.1.1", @@ -4810,6 +5176,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz", "integrity": "sha512-Gum0g1QYb6wpPJCVypWP3bbIuaibcFiJcpuPM10YSXp/tzqi84x9PJageob+eN4xVRIOto4wjSGNLyMD54D2xA==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.14.0" } @@ -4817,19 +5184,22 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -4846,6 +5216,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -4856,23 +5227,27 @@ "node_modules/fast-json-patch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", - "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "license": "MIT" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.9.1" } @@ -4881,6 +5256,7 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -4890,6 +5266,7 @@ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "bser": "2.1.1" } @@ -4897,12 +5274,14 @@ "node_modules/fclone": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", - "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" + "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==", + "license": "MIT" }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", "optional": true, "dependencies": { "pend": "~1.2.0" @@ -4912,6 +5291,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/feedme/-/feedme-2.0.2.tgz", "integrity": "sha512-0RNn0uLaSey8EThxgABR0T1Q47kSRatYnAXy1cfUc8/eypqXiAu38XGthuwwzb7mESCD9465k6Nym8D9AtB8HA==", + "license": "MIT", "dependencies": { "clarinet": "^0.12.4", "sax": "^1.2.4" @@ -4924,6 +5304,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -4935,6 +5316,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -4946,6 +5328,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -4963,6 +5346,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -4970,12 +5354,14 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -4991,6 +5377,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -5003,7 +5390,8 @@ "node_modules/flatted": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.15.6", @@ -5015,6 +5403,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -5028,6 +5417,7 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } @@ -5036,6 +5426,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -5049,6 +5440,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5057,6 +5449,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5065,6 +5458,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", "optional": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -5078,13 +5472,15 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -5097,6 +5493,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5105,6 +5502,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -5122,6 +5520,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5131,6 +5530,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -5140,6 +5540,7 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -5149,6 +5550,7 @@ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -5160,6 +5562,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -5179,6 +5582,7 @@ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.0.0" } @@ -5187,6 +5591,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", "optional": true, "dependencies": { "pump": "^3.0.0" @@ -5202,6 +5607,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -5218,6 +5624,7 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "license": "MIT", "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", @@ -5232,6 +5639,7 @@ "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -5245,6 +5653,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -5256,6 +5665,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -5265,6 +5675,7 @@ "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/fisker/git-hooks-list?sponsor=1" } @@ -5272,18 +5683,21 @@ "node_modules/git-node-fs": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", - "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==" + "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==", + "license": "MIT" }, "node_modules/git-sha1": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", - "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==" + "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==", + "license": "MIT" }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5303,6 +5717,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -5314,6 +5729,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5323,6 +5739,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -5334,6 +5751,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "license": "BSD-3-Clause", "optional": true, "dependencies": { "boolean": "^3.0.1", @@ -5352,6 +5770,7 @@ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, + "license": "MIT", "dependencies": { "global-prefix": "^3.0.0" }, @@ -5364,6 +5783,7 @@ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, + "license": "MIT", "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", @@ -5378,6 +5798,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -5389,6 +5810,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -5403,6 +5825,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -5419,6 +5842,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -5438,12 +5862,14 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -5455,6 +5881,7 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", "optional": true, "dependencies": { "@sindresorhus/is": "^4.0.0", @@ -5479,17 +5906,20 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "license": "MIT" }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -5510,6 +5940,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5518,6 +5949,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -5526,6 +5958,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -5537,6 +5970,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5548,6 +5982,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5559,6 +5994,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -5573,6 +6009,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -5584,6 +6021,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", + "license": "MIT", "engines": { "node": ">=16.0.0" } @@ -5592,13 +6030,15 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, + "license": "MIT", "dependencies": { "whatwg-encoding": "^3.1.1" }, @@ -5610,13 +6050,15 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/html-tags": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -5628,6 +6070,7 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==", + "license": "MIT", "dependencies": { "@selderee/plugin-htmlparser2": "^0.11.0", "deepmerge": "^4.3.1", @@ -5650,6 +6093,7 @@ "url": "https://github.com/sponsors/fb55" } ], + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", @@ -5661,12 +6105,14 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause", "optional": true }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -5682,6 +6128,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -5694,6 +6141,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", "optional": true, "dependencies": { "quick-lru": "^5.1.1", @@ -5707,6 +6155,7 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -5720,6 +6169,7 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10.17.0" } @@ -5729,6 +6179,7 @@ "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, + "license": "MIT", "bin": { "husky": "bin.mjs" }, @@ -5743,6 +6194,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -5754,6 +6206,7 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "license": "MIT", "engines": { "node": ">= 4" } @@ -5762,6 +6215,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -5778,6 +6232,7 @@ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -5796,6 +6251,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -5805,6 +6261,7 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5814,6 +6271,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -5822,17 +6280,20 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -5845,12 +6306,14 @@ "node_modules/ip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "license": "MIT" }, "node_modules/ip-address": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", "dependencies": { "jsbn": "1.1.0", "sprintf-js": "^1.1.3" @@ -5862,12 +6325,14 @@ "node_modules/ip-address/node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" }, "node_modules/ip6": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.2.10.tgz", "integrity": "sha512-1LdpyKjhvepd6EbAU6rW4g14vuYtx5TnJX9TfZZBhsM6DsyPQLNzW12rtbUqXBMwqFrLVV/Gcxv0GNFvJp2cYA==", + "license": "MIT", "bin": { "ip6": "ip6-cli.js" } @@ -5876,6 +6341,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -5884,6 +6350,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -5899,12 +6366,14 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" }, @@ -5916,6 +6385,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -5927,6 +6397,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -5943,6 +6414,7 @@ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", "dev": true, + "license": "MIT", "dependencies": { "builtin-modules": "^3.3.0" }, @@ -5957,6 +6429,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -5968,6 +6441,7 @@ "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "license": "MIT", "dependencies": { "hasown": "^2.0.0" }, @@ -5979,6 +6453,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "license": "MIT", "dependencies": { "is-typed-array": "^1.1.13" }, @@ -5993,6 +6468,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -6007,6 +6483,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6016,6 +6493,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -6028,6 +6506,7 @@ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -6036,6 +6515,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -6047,6 +6527,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -6058,6 +6539,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -6066,6 +6548,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -6080,6 +6563,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -6089,6 +6573,7 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -6098,6 +6583,7 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6106,12 +6592,14 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -6127,6 +6615,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7" }, @@ -6142,6 +6631,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -6153,6 +6643,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -6167,6 +6658,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -6181,6 +6673,7 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "license": "MIT", "dependencies": { "which-typed-array": "^1.1.14" }, @@ -6195,6 +6688,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -6205,18 +6699,21 @@ "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } @@ -6226,6 +6723,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.23.9", "@babel/parser": "^7.23.9", @@ -6242,6 +6740,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -6256,6 +6755,7 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -6270,6 +6770,7 @@ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -6283,6 +6784,7 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -6309,6 +6811,7 @@ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, + "license": "MIT", "dependencies": { "execa": "^5.0.0", "jest-util": "^29.7.0", @@ -6323,6 +6826,7 @@ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", @@ -6354,6 +6858,7 @@ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/core": "^29.7.0", "@jest/test-result": "^29.7.0", @@ -6387,6 +6892,7 @@ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", @@ -6438,6 +6944,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } @@ -6447,6 +6954,7 @@ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", @@ -6462,6 +6970,7 @@ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, + "license": "MIT", "dependencies": { "detect-newline": "^3.0.0" }, @@ -6474,6 +6983,7 @@ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -6490,6 +7000,7 @@ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -6507,6 +7018,7 @@ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -6516,6 +7028,7 @@ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", @@ -6541,6 +7054,7 @@ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, + "license": "MIT", "dependencies": { "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" @@ -6554,6 +7068,7 @@ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", @@ -6569,6 +7084,7 @@ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", @@ -6589,6 +7105,7 @@ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -6603,6 +7120,7 @@ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -6620,6 +7138,7 @@ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -6629,6 +7148,7 @@ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", @@ -6649,6 +7169,7 @@ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, + "license": "MIT", "dependencies": { "jest-regex-util": "^29.6.3", "jest-snapshot": "^29.7.0" @@ -6662,6 +7183,7 @@ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/console": "^29.7.0", "@jest/environment": "^29.7.0", @@ -6694,6 +7216,7 @@ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", @@ -6727,6 +7250,7 @@ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", @@ -6758,6 +7282,7 @@ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -6781,6 +7306,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } @@ -6790,6 +7316,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -6802,6 +7329,7 @@ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", @@ -6819,6 +7347,7 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6831,6 +7360,7 @@ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, + "license": "MIT", "dependencies": { "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", @@ -6850,6 +7380,7 @@ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", @@ -6865,6 +7396,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -6879,6 +7411,7 @@ "version": "0.7.8", "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", "integrity": "sha512-+E5ZH/HeRnoc/LW0AmAyhU+mNcWBzAKE+30+IDMLSLbbK+Tdt02AdkOKq9u15rlJsDEGFqtgckc8ZM59LhhiUA==", + "license": "MIT", "dependencies": { "bodec": "^0.1.0", "culvert": "^0.1.2", @@ -6890,12 +7423,14 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -6906,13 +7441,15 @@ "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" }, "node_modules/jsdoc-type-pratt-parser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" } @@ -6922,6 +7459,7 @@ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz", "integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==", "dev": true, + "license": "MIT", "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", @@ -6962,6 +7500,7 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -6972,28 +7511,33 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC", "optional": true }, "node_modules/json5": { @@ -7001,6 +7545,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -7013,6 +7558,7 @@ "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "acorn": "^8.5.0", @@ -7031,6 +7577,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", "optional": true, "optionalDependencies": { "graceful-fs": "^4.1.6" @@ -7040,12 +7587,14 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -7055,6 +7604,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7064,6 +7614,7 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -7072,12 +7623,14 @@ "version": "0.31.0", "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.31.0.tgz", "integrity": "sha512-sBPIUGTNF0czz0mwGGUoKKJC8Q7On1GPbCSFPfyEsfHb2DyBG0Y4QtV+EVWpINSaiGKZblDNuF5AezxSgOhesQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lazy": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", "integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==", + "license": "MIT", "engines": { "node": ">=0.2.0" } @@ -7086,6 +7639,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==", + "license": "MIT", "funding": { "url": "https://ko-fi.com/killymxi" } @@ -7095,6 +7649,7 @@ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -7103,6 +7658,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -7116,6 +7672,7 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" }, @@ -7127,13 +7684,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.5", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.5.tgz", - "integrity": "sha512-j+DfX7W9YUvdzEZl3Rk47FhDF6xwDBV5wwsCPw6BwWZVPYJemusQmvb9bRsW23Sqsaa+vRloAWogbK4BUuU2zA==", + "version": "15.2.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz", + "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "~5.3.0", "commander": "~12.1.0", @@ -7161,6 +7720,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -7173,6 +7733,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } @@ -7182,6 +7743,7 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", @@ -7205,6 +7767,7 @@ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -7217,6 +7780,7 @@ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=16.17.0" } @@ -7226,6 +7790,7 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -7238,6 +7803,7 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -7250,6 +7816,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^4.0.0" }, @@ -7265,6 +7832,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^4.0.0" }, @@ -7280,6 +7848,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -7292,6 +7861,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -7304,6 +7874,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -7316,6 +7887,7 @@ "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz", "integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==", "dev": true, + "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", @@ -7332,6 +7904,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -7345,30 +7918,35 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT" }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/log-update": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^6.2.0", "cli-cursor": "^4.0.0", @@ -7388,6 +7966,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.16" }, @@ -7400,6 +7979,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -7412,6 +7992,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -7424,6 +8005,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, + "license": "MIT", "dependencies": { "get-east-asian-width": "^1.0.0" }, @@ -7439,6 +8021,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -7455,6 +8038,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -7469,6 +8053,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", "optional": true, "engines": { "node": ">=8" @@ -7479,6 +8064,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -7488,6 +8074,7 @@ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -7503,6 +8090,7 @@ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tmpl": "1.0.5" } @@ -7511,6 +8099,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "license": "MIT", "optional": true, "dependencies": { "escape-string-regexp": "^4.0.0" @@ -7524,6 +8113,7 @@ "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -7533,12 +8123,14 @@ "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7548,6 +8140,7 @@ "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -7558,19 +8151,22 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "license": "MIT" }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -7579,6 +8175,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7588,6 +8185,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -7601,6 +8199,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -7612,6 +8211,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -7623,6 +8223,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7631,6 +8232,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -7643,6 +8245,7 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -7651,6 +8254,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", "optional": true, "engines": { "node": ">=4" @@ -7661,6 +8265,7 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -7670,6 +8275,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -7684,6 +8290,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7692,6 +8299,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -7702,17 +8310,20 @@ "node_modules/module-alias": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz", - "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==" + "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==", + "license": "MIT" }, "node_modules/module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", + "license": "MIT" }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } @@ -7721,6 +8332,7 @@ "version": "0.5.45", "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "license": "MIT", "dependencies": { "moment": "^2.29.4" }, @@ -7731,12 +8343,14 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "license": "ISC" }, "node_modules/nanoid": { "version": "3.3.7", @@ -7749,6 +8363,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -7759,12 +8374,14 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "license": "MIT" }, "node_modules/needle": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "license": "MIT", "dependencies": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -7781,6 +8398,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -7789,6 +8407,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -7800,6 +8419,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -7807,21 +8427,24 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" }, "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==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/nise": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", - "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.0.0.tgz", + "integrity": "sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0", "@sinonjs/fake-timers": "^11.2.2", @@ -7835,6 +8458,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } @@ -7843,12 +8467,14 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-ical": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.18.0.tgz", "integrity": "sha512-FrOUPztjw9OUgSB9o/ffhl86BiVClQTut97C2NqCwKIgOAcKPEw5UQMuSuNJO/Y4hqTyJdKZh2TCqNHQnE9YFg==", + "license": "Apache-2.0", "dependencies": { "axios": "1.6.7", "moment-timezone": "^0.5.44", @@ -7860,19 +8486,22 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -7885,6 +8514,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -7893,6 +8523,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7901,6 +8532,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", "optional": true, "engines": { "node": ">=10" @@ -7914,6 +8546,7 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.0.0" }, @@ -7925,6 +8558,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", "integrity": "sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==", + "license": "MIT", "dependencies": { "eventemitter2": "~0.4.14", "lazy": "~1.0.11" @@ -7936,18 +8570,21 @@ "node_modules/nssocket/node_modules/eventemitter2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==", + "license": "MIT" }, "node_modules/nwsapi": { "version": "2.2.10", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz", "integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7956,6 +8593,7 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7964,6 +8602,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -7972,6 +8611,7 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -7990,6 +8630,7 @@ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8008,6 +8649,7 @@ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8022,6 +8664,7 @@ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8038,6 +8681,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -8049,6 +8693,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -8058,6 +8703,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -8073,6 +8719,7 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", "dev": true, + "license": "MIT/X11", "dependencies": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" @@ -8082,13 +8729,15 @@ "version": "0.0.10", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/optimist/node_modules/wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -8097,6 +8746,7 @@ "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -8113,6 +8763,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", "optional": true, "engines": { "node": ">=8" @@ -8122,6 +8773,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -8136,6 +8788,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -8151,6 +8804,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -8159,6 +8813,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -8177,6 +8832,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "license": "MIT", "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" @@ -8200,12 +8856,14 @@ "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "license": "MIT" }, "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==", + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -8218,6 +8876,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -8236,6 +8895,7 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", "dev": true, + "license": "MIT", "dependencies": { "entities": "^4.4.0" }, @@ -8247,6 +8907,7 @@ "version": "0.12.1", "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==", + "license": "MIT", "dependencies": { "leac": "^0.6.0", "peberminta": "^0.9.0" @@ -8259,6 +8920,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -8267,6 +8929,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", "engines": { "node": ">=8" } @@ -8275,6 +8938,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8283,6 +8947,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { "node": ">=8" } @@ -8290,18 +8955,21 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8310,6 +8978,7 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==", + "license": "MIT", "funding": { "url": "https://ko-fi.com/killymxi" } @@ -8318,19 +8987,22 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT", "optional": true }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -8343,6 +9015,7 @@ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, + "license": "MIT", "bin": { "pidtree": "bin/pidtree.js" }, @@ -8354,6 +9027,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz", "integrity": "sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==", + "license": "MIT", "dependencies": { "safe-buffer": "^5.2.1" }, @@ -8366,6 +9040,7 @@ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 6" } @@ -8375,6 +9050,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -8387,6 +9063,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -8400,6 +9077,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -8412,6 +9090,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -8427,6 +9106,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -8439,6 +9119,7 @@ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "playwright-core": "1.44.1" }, @@ -8457,6 +9138,7 @@ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -8470,6 +9152,7 @@ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -8483,14 +9166,16 @@ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/pm2": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.0.tgz", - "integrity": "sha512-9TrDuckcSEnINoURygr3yfruK20qXuOUPOPQyIh4FIskQduyDNst9ys1XAt9YPY3RyGxVr2+x8Irsdma3klVQw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.1.tgz", + "integrity": "sha512-y9ndADjy78XfzdbVHISn4WiUTrcvmsO7ieCtM/oC80rwPgBDg+bHkkz1e4eaLOW5a7sJsnDfQjJe4AqxNnIw5Q==", + "license": "AGPL-3.0", "dependencies": { "@pm2/agent": "~2.0.0", "@pm2/io": "~6.0.0", @@ -8539,6 +9224,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz", "integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==", + "license": "MIT", "dependencies": { "amp": "~0.3.1", "amp-message": "~0.1.1", @@ -8553,6 +9239,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz", "integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==", + "license": "MIT", "dependencies": { "debug": "^4.3.1" }, @@ -8564,6 +9251,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-1.0.2.tgz", "integrity": "sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==", + "license": "MIT", "dependencies": { "run-series": "^1.1.8", "tv4": "^1.3.0" @@ -8576,6 +9264,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz", "integrity": "sha512-S+wT6XfyKfd7SJIBqRgOctGxaBzUOmVQzTAS+cg04TsEUObJVreha7lvCfX8zzGVr871XwCSnHUU7DQQ5xEsfA==", + "license": "MIT/X11", "dependencies": { "charm": "~0.1.1" } @@ -8584,6 +9273,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz", "integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==", + "license": "Apache", "optional": true, "dependencies": { "async": "^3.2.0", @@ -8597,6 +9287,7 @@ "version": "2.0.21", "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", + "license": "MIT", "optional": true, "dependencies": { "safe-buffer": "^5.2.1" @@ -8609,6 +9300,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -8620,12 +9312,14 @@ "node_modules/pm2/node_modules/commander": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "license": "MIT" }, "node_modules/pm2/node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -8635,6 +9329,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -8658,6 +9353,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -8671,7 +9367,8 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/postcss-safe-parser": { "version": "7.0.0", @@ -8692,6 +9389,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "engines": { "node": ">=18.0" }, @@ -8704,6 +9402,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8716,21 +9415,24 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", - "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -8746,6 +9448,7 @@ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -8758,6 +9461,7 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", @@ -8772,6 +9476,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -8783,6 +9488,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", "optional": true, "engines": { "node": ">=0.4.0" @@ -8792,6 +9498,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", "integrity": "sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==", + "license": "MIT", "dependencies": { "read": "^1.0.4" } @@ -8801,6 +9508,7 @@ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, + "license": "MIT", "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -8813,6 +9521,7 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -8825,6 +9534,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", @@ -8843,6 +9553,7 @@ "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -8850,18 +9561,21 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "license": "MIT", "optional": true, "dependencies": { "end-of-stream": "^1.1.0", @@ -8872,6 +9586,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", "engines": { "node": ">=6" } @@ -8890,12 +9605,14 @@ "type": "opencollective", "url": "https://opencollective.com/fast-check" } - ] + ], + "license": "MIT" }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" }, @@ -8910,7 +9627,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -8929,12 +9647,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", "optional": true, "engines": { "node": ">=10" @@ -8947,6 +9667,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/range_check/-/range_check-2.0.4.tgz", "integrity": "sha512-aed0ocXXj+SIiNNN9b+mZWA3Ow2GXHtftOGk2xQwshK5GbEZAvUcPWNQBLTx/lPcdFRIUFlFCRtHTQNIFMqynQ==", + "license": "BSD-2-Clause", "dependencies": { "ip6": "^0.2.0", "ipaddr.js": "^1.9.1" @@ -8959,6 +9680,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8967,6 +9689,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -8981,6 +9704,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -8992,12 +9716,14 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "license": "ISC", "dependencies": { "mute-stream": "~0.0.4" }, @@ -9010,6 +9736,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, + "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -9025,6 +9752,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -9042,6 +9770,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -9055,6 +9784,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -9067,6 +9797,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -9082,6 +9813,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -9094,6 +9826,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -9103,6 +9836,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -9111,6 +9845,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -9122,6 +9857,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -9134,6 +9870,7 @@ "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", "dev": true, + "license": "MIT", "bin": { "regexp-tree": "bin/regexp-tree" } @@ -9142,6 +9879,7 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -9160,6 +9898,7 @@ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "jsesc": "~0.5.0" }, @@ -9180,6 +9919,7 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/replace-last/-/replace-last-1.2.6.tgz", "integrity": "sha512-Cj+MK38VtNu1S5J73mEZY3ciQb9dJajNq1Q8inP4dn/MhJMjHwoAF3Z3FjspwAEV9pfABl565MQucmrjOkty4g==", + "license": "ISC", "engines": { "node": ">= 4.0.0" } @@ -9189,6 +9929,7 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9198,6 +9939,7 @@ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9206,6 +9948,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", + "license": "MIT", "dependencies": { "debug": "^4.1.1", "module-details-from-path": "^1.0.3", @@ -9219,12 +9962,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9241,6 +9986,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT", "optional": true }, "node_modules/resolve-cwd": { @@ -9248,6 +9994,7 @@ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -9260,6 +10007,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9268,6 +10016,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", "engines": { "node": ">=4" } @@ -9277,6 +10026,7 @@ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -9285,6 +10035,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", "optional": true, "dependencies": { "lowercase-keys": "^2.0.0" @@ -9298,6 +10049,7 @@ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, + "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -9313,22 +10065,25 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", - "dev": true + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -9343,6 +10098,7 @@ "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "license": "BSD-3-Clause", "optional": true, "dependencies": { "boolean": "^3.0.1", @@ -9360,6 +10116,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.8.1.tgz", "integrity": "sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==", + "license": "BSD-3-Clause", "dependencies": { "tslib": "^2.4.0" } @@ -9367,13 +10124,15 @@ "node_modules/rrule/node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "license": "0BSD" }, "node_modules/rrweb-cssom": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.0.tgz", - "integrity": "sha512-KlSv0pm9kgQSRxXEMgtivPJ4h826YHsuob8pSHcfSZsSXGtvpEAie8S0AnXuObEJ7nhikOb4ahwxDm0H2yW17g==", - "dev": true + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" }, "node_modules/run-parallel": { "version": "1.2.0", @@ -9393,6 +10152,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -9414,12 +10174,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-array-concat": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -9450,12 +10212,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-regex-test": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -9471,18 +10235,21 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/sax": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, + "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" }, @@ -9494,6 +10261,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", + "license": "MIT", "dependencies": { "parseley": "^0.12.0" }, @@ -9505,6 +10273,7 @@ "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -9516,12 +10285,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT", "optional": true }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -9545,6 +10316,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -9552,17 +10324,20 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "license": "MIT", "optional": true, "dependencies": { "type-fest": "^0.13.1" @@ -9578,6 +10353,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "license": "(MIT OR CC0-1.0)", "optional": true, "engines": { "node": ">=10" @@ -9590,6 +10366,7 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "license": "MIT", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -9604,6 +10381,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -9620,6 +10398,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -9633,12 +10412,14 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -9650,6 +10431,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", "engines": { "node": ">=8" } @@ -9657,12 +10439,14 @@ "node_modules/shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -9679,20 +10463,22 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/sinon": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", - "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.0.tgz", + "integrity": "sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^3.0.0", + "@sinonjs/commons": "^3.0.1", "@sinonjs/fake-timers": "^11.2.2", "@sinonjs/samsam": "^8.0.0", - "diff": "^5.1.0", - "nise": "^5.1.5", - "supports-color": "^7.2.0" + "diff": "^5.2.0", + "nise": "^6.0.0", + "supports-color": "^7" }, "funding": { "type": "opencollective", @@ -9704,6 +10490,7 @@ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } @@ -9713,6 +10500,7 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -9721,13 +10509,15 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9737,6 +10527,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -9753,6 +10544,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -9764,6 +10556,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -9773,6 +10566,7 @@ "version": "4.7.5", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -9787,38 +10581,20 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", - "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "license": "MIT", "dependencies": { "debug": "~4.3.4", - "ws": "~8.11.0" - } - }, - "node_modules/socket.io-adapter/node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "ws": "~8.17.1" } }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -9831,6 +10607,7 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "license": "MIT", "dependencies": { "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" @@ -9844,6 +10621,7 @@ "version": "8.0.3", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", + "license": "MIT", "dependencies": { "agent-base": "^7.1.1", "debug": "^4.3.4", @@ -9857,13 +10635,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/sort-package-json": { "version": "1.57.0", "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.57.0.tgz", "integrity": "sha512-FYsjYn2dHTRb41wqnv+uEqCUvBpK3jZcTp9rbz2qDTmel7Pmdtf+i2rLaaPMRZeSVM60V3Se31GyWFpmKs4Q5Q==", "dev": true, + "license": "MIT", "dependencies": { "detect-indent": "^6.0.0", "detect-newline": "3.1.0", @@ -9881,6 +10661,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", "dev": true, + "license": "MIT", "dependencies": { "@types/glob": "^7.1.1", "array-union": "^2.1.0", @@ -9899,6 +10680,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -9908,6 +10690,7 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -9917,6 +10700,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -9927,6 +10711,7 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -9937,6 +10722,7 @@ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -9946,13 +10732,15 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -9962,18 +10750,21 @@ "version": "3.0.18", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/sprintf-js": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "license": "BSD-3-Clause" }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -9986,6 +10777,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9994,6 +10786,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10003,6 +10796,7 @@ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6.19" } @@ -10012,6 +10806,7 @@ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, + "license": "MIT", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -10025,6 +10820,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -10042,6 +10838,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10054,6 +10851,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -10068,6 +10866,7 @@ "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -10093,6 +10892,7 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -10110,6 +10910,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -10123,6 +10924,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -10139,6 +10941,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10151,6 +10954,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10160,6 +10964,7 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -10169,6 +10974,7 @@ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, + "license": "MIT", "dependencies": { "min-indent": "^1.0.0" }, @@ -10180,6 +10986,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -10202,6 +11009,7 @@ "url": "https://github.com/sponsors/stylelint" } ], + "license": "MIT", "dependencies": { "@csstools/css-parser-algorithms": "^2.6.3", "@csstools/css-tokenizer": "^2.3.1", @@ -10255,6 +11063,7 @@ "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.0.tgz", "integrity": "sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18.12.0" }, @@ -10267,6 +11076,7 @@ "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.0.tgz", "integrity": "sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug==", "dev": true, + "license": "MIT", "dependencies": { "stylelint-config-recommended": "^14.0.0" }, @@ -10282,6 +11092,7 @@ "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.0.tgz", "integrity": "sha512-RHfSlRJIsaVg5Br94gZVdWlz/rBTyQzZflNE6dXvSxt/GthWMY3gEHsWZEBaVGg7GM+XrtVSp4RznFlB7i0oyw==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0" }, @@ -10297,19 +11108,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/stylelint/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.0.0.tgz", "integrity": "sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^5.0.0" }, @@ -10322,6 +11136,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.3.1", "keyv": "^4.5.4" @@ -10335,6 +11150,7 @@ "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" } @@ -10344,6 +11160,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10353,6 +11170,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -10365,6 +11183,7 @@ "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", @@ -10379,6 +11198,7 @@ "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" }, @@ -10391,6 +11211,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -10406,6 +11227,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10418,6 +11240,7 @@ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -10430,6 +11253,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "license": "Apache-2.0", "optional": true, "dependencies": { "debug": "^4.1.0" @@ -10447,6 +11271,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -10459,6 +11284,7 @@ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -10471,6 +11297,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10488,12 +11315,14 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/systeminformation": { "version": "5.22.11", "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.11.tgz", "integrity": "sha512-aLws5yi4KCHTb0BVvbodQY5bY8eW4asMRDTxTW46hqw9lGjACX6TlLdJrkdoHYRB0qs+MekqEq1zG7WDnWE8Ug==", + "license": "MIT", "os": [ "darwin", "linux", @@ -10520,6 +11349,7 @@ "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -10536,6 +11366,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", @@ -10551,13 +11382,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/table/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" } @@ -10566,13 +11399,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/table/node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -10590,6 +11425,7 @@ "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", @@ -10604,6 +11440,7 @@ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -10618,6 +11455,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -10628,6 +11466,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -10638,19 +11477,22 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "license": "MIT" }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10659,6 +11501,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -10670,6 +11513,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -10679,6 +11523,7 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -10694,6 +11539,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -10703,6 +11549,7 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, @@ -10715,6 +11562,7 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -10727,6 +11575,7 @@ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -10739,6 +11588,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -10751,6 +11601,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10758,12 +11609,23 @@ "node_modules/tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "license": "Apache-2.0" }, "node_modules/tv4": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==", + "license": [ + { + "type": "Public Domain", + "url": "http://geraintluff.github.io/tv4/LICENSE.txt" + }, + { + "type": "MIT", + "url": "http://jsonary.com/LICENSE.txt" + } + ], "engines": { "node": ">= 0.8.0" } @@ -10772,6 +11634,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz", "integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==", + "license": "MIT", "optional": true, "dependencies": { "json-stringify-safe": "^5.0.1" @@ -10781,6 +11644,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -10793,6 +11657,7 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10801,6 +11666,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -10812,6 +11678,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -10824,6 +11691,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -10837,6 +11705,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -10855,6 +11724,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -10874,6 +11744,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -10894,6 +11765,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, + "license": "Apache-2.0", "peer": true, "bin": { "tsc": "bin/tsc", @@ -10907,6 +11779,7 @@ "version": "3.18.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -10919,6 +11792,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -10932,12 +11806,14 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", "optional": true, "engines": { "node": ">= 4.0.0" @@ -10947,6 +11823,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10970,6 +11847,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" @@ -10985,6 +11863,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -10994,6 +11873,7 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, + "license": "MIT", "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -11003,12 +11883,14 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } @@ -11021,6 +11903,7 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -11030,6 +11913,7 @@ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, + "license": "ISC", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -11044,6 +11928,7 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -11054,6 +11939,7 @@ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -11064,6 +11950,7 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, + "license": "ISC", "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -11072,6 +11959,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -11080,6 +11968,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/vizion/-/vizion-2.2.1.tgz", "integrity": "sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==", + "license": "Apache-2.0", "dependencies": { "async": "^2.6.3", "git-node-fs": "^1.0.0", @@ -11094,6 +11983,7 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", "dependencies": { "lodash": "^4.17.14" } @@ -11103,6 +11993,7 @@ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, + "license": "MIT", "dependencies": { "xml-name-validator": "^5.0.0" }, @@ -11115,6 +12006,7 @@ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" } @@ -11124,6 +12016,7 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" } @@ -11133,6 +12026,7 @@ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, + "license": "MIT", "dependencies": { "iconv-lite": "0.6.3" }, @@ -11145,6 +12039,7 @@ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } @@ -11154,6 +12049,7 @@ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, + "license": "MIT", "dependencies": { "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" @@ -11166,6 +12062,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -11180,6 +12077,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -11195,6 +12093,7 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -11213,6 +12112,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11220,13 +12120,15 @@ "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" }, "node_modules/wrap-ansi": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -11244,6 +12146,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -11256,6 +12159,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -11268,6 +12172,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -11281,13 +12186,15 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, "node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -11297,10 +12204,10 @@ } }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", - "dev": true, + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -11322,6 +12229,7 @@ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18" } @@ -11330,13 +12238,15 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -11345,13 +12255,15 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yaml": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", "dev": true, + "license": "ISC", "bin": { "yaml": "bin.mjs" }, @@ -11364,6 +12276,7 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -11382,6 +12295,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } @@ -11390,13 +12304,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/yargs/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" } @@ -11406,6 +12322,7 @@ "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", @@ -11419,6 +12336,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", "optional": true, "dependencies": { "buffer-crc32": "~0.2.3", @@ -11429,6 +12347,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index c7aebff9d5..b79a8caa77 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.18.0", - "pm2": "^5.4.0", + "pm2": "^5.4.1", "socket.io": "^4.7.5", "suncalc": "^1.9.0", "systeminformation": "^5.22.11" @@ -76,23 +76,23 @@ "@stylistic/eslint-plugin": "^1.8.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.2.9", - "eslint-plugin-package-json": "^0.14.0", - "eslint-plugin-unicorn": "^53.0.0", + "eslint-plugin-jsdoc": "^48.2.12", + "eslint-plugin-package-json": "^0.15.0", + "eslint-plugin-unicorn": "^54.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.0.11", "jest": "^29.7.0", "jsdom": "^24.1.0", - "lint-staged": "^15.2.5", + "lint-staged": "^15.2.7", "playwright": "^1.44.1", - "prettier": "^3.3.1", - "sinon": "^17.0.1", + "prettier": "^3.3.2", + "sinon": "^18.0.0", "stylelint": "^16.6.1", "stylelint-config-standard": "^36.0.0", "stylelint-prettier": "^5.0.0" }, "optionalDependencies": { - "electron": "^30.1.0" + "electron": "^31.0.1" }, "engines": { "node": ">=20" From 4c748a4d3257896460176efb64c9f869d2558e4a Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 22 Jun 2024 21:23:58 +0200 Subject: [PATCH 064/418] update `config.js.sample` to use openmeteo as weather provider (#3476) which needs no api key. I think this is a better choice than the old one because new users which use this config as starting point will now see weather data instead of `loading...` --- CHANGELOG.md | 13 +++++++------ config/config.js.sample | 14 ++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba1a3c8baf..01502e425d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,9 @@ _This release is scheduled to be released on 2024-07-01._ ### Updated -- [chore] Update dependencies including electron to v31 +- [core] Update dependencies including electron to v31 - [core] use node >= v20 +- [core] Update `config.js.sample` to use openmeteo as weather provider which needs no api key ### Fixed @@ -37,7 +38,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T ### Added - Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 (#3349) -- [chore] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368) +- [core] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368) - [weather] `showHumidity` config is now a string describing where to show this element. Supported values: "wind", "temp", "feelslike", "below", "none". (#3330) - electron-rebuild test suite for electron and 3rd party modules compatibility (#3392) - Create MM² icon and attach it to electron process (#3407) @@ -49,8 +50,8 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T - Use node prefix for build-in modules (#3340) - Rework logging colors (#3350) - Update pm2 to v5.3.1 with no allow-ghsas (#3364) -- [chore] Update husky and let lint-staged fix ESLint issues -- [chore] Update dependencies including electron to v29 (#3357) and node-ical +- [core] Update husky and let lint-staged fix ESLint issues +- [core] Update dependencies including electron to v29 (#3357) and node-ical - Update translations for estonian (#3371) - Update electron to v29 and update other dependencies - [calendar] fullDay events over several days now show the left days from the first day on and 'today' on the last day @@ -72,9 +73,9 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T - added message in case where config.js is missing the module.export line PR #3383 - Fixed an issue where recurring events could extend past their recurrence end date (#3393) - Don't display any `npm WARN <....>` on install (#3399) -- [chore] Moved suncalc dependency to production from dev, as it is used by clock module +- [core] Moved suncalc dependency to production from dev, as it is used by clock module - [compliments] Fix mirror not responding anymore when no compliments are to be shown (#3385) -- [chore] Fixed mastermerge workflow (#3415) +- [core] Fixed mastermerge workflow (#3415) ### Deleted diff --git a/config/config.js.sample b/config/config.js.sample index 688f627286..56edb59df8 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -67,11 +67,10 @@ let config = { module: "weather", position: "top_right", config: { - weatherProvider: "openweathermap", + weatherProvider: "openmeteo", type: "current", - location: "New York", - locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city - apiKey: "YOUR_OPENWEATHER_API_KEY" + lat: 40.776676, + lon: -73.971321 } }, { @@ -79,11 +78,10 @@ let config = { position: "top_right", header: "Weather Forecast", config: { - weatherProvider: "openweathermap", + weatherProvider: "openmeteo", type: "forecast", - location: "New York", - locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city - apiKey: "YOUR_OPENWEATHER_API_KEY" + lat: 40.776676, + lon: -73.971321 } }, { From e95c144c3e174f3514fa4af232e9da7bc51d1a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Mon, 24 Jun 2024 21:51:54 +0200 Subject: [PATCH 065/418] Fix crash possibility if `module: ` is not defined and on mistake `position: ` (#3445) Fix #3442 --- CHANGELOG.md | 1 + js/app.js | 11 ++++-- js/check_config.js | 66 +++++++++++++++++++++++++++++++++++ js/loader.js | 3 +- js/main.js | 11 +++--- js/utils.js | 11 ++++++ package-lock.json | 87 ++++++++++++++++++++++++++++++++++++++-------- package.json | 1 + 8 files changed, 170 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01502e425d..916c68770b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ _This release is scheduled to be released on 2024-07-01._ ### Fixed +- Fix crash possibility if `module: ` is not defined and on `postion: ` misktake. - [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) - [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) - [weather] Fixed type=daily for provider openmeteo showing nightly icons in forecast when current time is "nightly" (#3458) diff --git a/js/app.js b/js/app.js index 77d0dc206f..f6e116d17d 100644 --- a/js/app.js +++ b/js/app.js @@ -253,8 +253,15 @@ function App () { let modules = []; for (const module of config.modules) { - if (!modules.includes(module.module) && !module.disabled) { - modules.push(module.module); + if (module.disabled) continue; + if (module.module) { + if (Utils.moduleHasValidPosition(module.position) || typeof (module.position) === "undefined") { + modules.push(module.module); + } else { + Log.warn("Invalid module position found for this configuration:", module); + } + } else { + Log.warn("No module name found for this configuration:", module); } } diff --git a/js/check_config.js b/js/check_config.js index ec5ebcae66..6a514de3eb 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -5,6 +5,10 @@ const { Linter } = require("eslint"); const linter = new Linter(); +const Ajv = require("ajv"); + +const ajv = new Ajv(); + const rootPath = path.resolve(`${__dirname}/../`); const Log = require(`${rootPath}/js/logger.js`); @@ -59,6 +63,68 @@ function checkConfigFile () { for (const error of errors) { Log.error(`Line ${error.line} column ${error.column}: ${error.message}`); } + return; + } + + Log.info("Checking modules structure configuration... "); + + // Make Ajv schema confguration of modules config + // only scan "module" and "position" + const schema = { + type: "object", + properties: { + modules: { + type: "array", + items: { + type: "object", + properties: { + module: { + type: "string" + }, + position: { + type: "string", + enum: [ + "top_bar", + "top_left", + "top_center", + "top_right", + "upper_third", + "middle_center", + "lower_third", + "bottom_left", + "bottom_center", + "bottom_right", + "bottom_bar", + "fullscreen_above", + "fullscreen_below" + ] + } + }, + required: ["module"] + } + } + } + }; + + // scan all modules + const validate = ajv.compile(schema); + const data = require(configFileName); + + const valid = validate(data); + if (!valid) { + let module = validate.errors[0].instancePath.split("/")[2]; + let position = validate.errors[0].instancePath.split("/")[3]; + + Log.error(colors.red("This module configuration contains errors:")); + Log.error(data.modules[module]); + if (position) { + Log.error(colors.red(`${position}: ${validate.errors[0].message}`)); + Log.error(validate.errors[0].params.allowedValues); + } else { + Log.error(colors.red(validate.errors[0].message)); + } + } else { + Log.info(colors.green("Your modules structure configuration doesn't contain errors :)")); } } diff --git a/js/loader.js b/js/loader.js index 0d59858c77..e8dff1907c 100644 --- a/js/loader.js +++ b/js/loader.js @@ -50,7 +50,8 @@ const Loader = (function () { * @returns {object[]} module data as configured in config */ const getAllModules = function () { - return config.modules; + const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined")); + return AllModules; }; /** diff --git a/js/main.js b/js/main.js index 43ec02ad87..bc69f0bb93 100644 --- a/js/main.js +++ b/js/main.js @@ -450,10 +450,10 @@ const MM = (function () { * an ugly top margin. By using this function, the top bar will be hidden if the * update notification is not visible. */ - const updateWrapperStates = function () { - const positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"]; + const modulePositions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"]; - positions.forEach(function (position) { + const updateWrapperStates = function () { + modulePositions.forEach(function (position) { const wrapper = selectWrapper(position); const moduleWrappers = wrapper.getElementsByClassName("module"); @@ -701,7 +701,10 @@ const MM = (function () { showModule (module, speed, callback, options) { // do not change module.hidden yet, only if we really show it later showModule(module, speed, callback, options); - } + }, + + // return all available module postions. + getAvailableModulePositions: modulePositions }; }()); diff --git a/js/utils.js b/js/utils.js index ba80004bb3..89784f6937 100644 --- a/js/utils.js +++ b/js/utils.js @@ -25,5 +25,16 @@ module.exports = { } catch (e) { Log.error(e); } + }, + + // return all available module positions + getAvailableModulePositions () { + return ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"]; + }, + + // return if postion is on modulePositions Array (true/false) + moduleHasValidPosition (position) { + if (this.getAvailableModulePositions().indexOf(position) === -1) return false; + return true; } }; diff --git a/package-lock.json b/package-lock.json index 22c2ad3242..018afa76b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { + "ajv": "^8.16.0", "ansis": "^3.2.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", @@ -923,6 +924,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -933,6 +949,11 @@ "concat-map": "0.0.1" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2353,15 +2374,14 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "license": "MIT", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -4794,6 +4814,22 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-plugin-unicorn/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint-plugin-unicorn/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4849,6 +4885,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint-plugin-unicorn/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "node_modules/eslint-plugin-unicorn/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4890,6 +4932,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4900,6 +4957,11 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -7522,10 +7584,9 @@ "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -9938,8 +9999,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } diff --git a/package.json b/package.json index b79a8caa77..dc9a8d298e 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "*.css": "stylelint --fix" }, "dependencies": { + "ajv": "^8.16.0", "ansis": "^3.2.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", From 8d20832bc57e3fd54cb65468a8f87bab9a16224c Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 24 Jun 2024 21:52:19 +0200 Subject: [PATCH 066/418] [calendar] add config option "showEndsOnlyWithDuration" (#3477) redo and rebase changes made in PR https://github.com/MagicMirrorOrg/MagicMirror/pull/2968 by https://github.com/kleinmantara --- CHANGELOG.md | 4 ++++ modules/default/calendar/calendar.js | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 916c68770b..cada597d3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,12 @@ This project adheres to [Semantic Versioning](https://semver.org/). _This release is scheduled to be released on 2024-07-01._ +Thanks to: @kleinmantara (to be continued before release) + ### Added +- [calendar] Added config option "showEndsOnlyWithDuration" for default calendar + ### Removed - [test suite] delete node v18 support diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index a3f597592f..4b0409c01c 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -29,6 +29,7 @@ Module.register("calendar", { dateEndFormat: "LT", fullDayEventDateFormat: "MMM Do", showEnd: false, + showEndsOnlyWithDuration: false, getRelative: 6, hidePrivate: false, hideOngoing: false, @@ -388,7 +389,11 @@ Module.register("calendar", { // Add endDate to dataheaders if showEnd is enabled if (this.config.showEnd) { - timeWrapper.innerHTML += ` - ${CalendarUtils.capFirst(moment(event.endDate, "x").format("LT"))}`; + if (this.config.showEndsOnlyWithDuration && event.startDate === event.endDate) { + // no duration here, don't display end + } else { + timeWrapper.innerHTML += ` - ${CalendarUtils.capFirst(moment(event.endDate, "x").format("LT"))}`; + } } eventWrapper.appendChild(timeWrapper); @@ -407,8 +412,12 @@ Module.register("calendar", { timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").format(this.config.dateFormat)); // Add end time if showEnd if (this.config.showEnd) { - timeWrapper.innerHTML += "-"; - timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat)); + if (this.config.showEndsOnlyWithDuration && event.startDate === event.endDate) { + // no duration here, don't display end + } else { + timeWrapper.innerHTML += "-"; + timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat)); + } } // For full day events we use the fullDayEventDateFormat if (event.fullDayEvent) { From 3d9d72e64e6a0365fb34351f6593ce212734b0e4 Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Mon, 24 Jun 2024 16:18:49 -0400 Subject: [PATCH 067/418] Open-Meteo: Fix forecast and hourly weather to use real temperatures, not apparent temperatures (#3468) As discussed in #3466, the Open-Meteo provider is using the apparent temperature ("Feels like") in the forecast and hourly weather reporting. This is contrary to expected behavior. Note: I'm a little unclear on how I should be editing the `CHANGELOG.md` file with this PR - happy to update this PR with a little guidance. This is my first attempted PR in this project. Let me know if there are any questions. --------- Co-authored-by: veeck --- CHANGELOG.md | 3 ++- modules/default/weather/providers/openmeteo.js | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cada597d3b..9443b6a711 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,10 +27,11 @@ Thanks to: @kleinmantara (to be continued before release) ### Fixed -- Fix crash possibility if `module: ` is not defined and on `postion: ` misktake. +- [core] Fixed crash possibility if `module: ` is not defined and on `postion: ` misktake. - [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) - [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) - [weather] Fixed type=daily for provider openmeteo showing nightly icons in forecast when current time is "nightly" (#3458) +- [weather] Fixed forecast and hourly weather for provider openmeteo to use real temperatures, not apparent temperatures ## [2.27.0] - 2024-04-01 diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index e199caff65..6acddec763 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -398,9 +398,9 @@ WeatherProvider.register("openmeteo", { currentWeather.windFromDirection = weather.winddirection_10m_dominant; currentWeather.sunrise = weather.sunrise; currentWeather.sunset = weather.sunset; - currentWeather.temperature = parseFloat((weather.apparent_temperature_max + weather.apparent_temperature_min) / 2); - currentWeather.minTemperature = parseFloat(weather.apparent_temperature_min); - currentWeather.maxTemperature = parseFloat(weather.apparent_temperature_max); + currentWeather.temperature = parseFloat((weather.temperature_2m_max + weather.temperature_2m_min) / 2); + currentWeather.minTemperature = parseFloat(weather.temperature_2m_min); + currentWeather.maxTemperature = parseFloat(weather.temperature_2m_max); currentWeather.weatherType = this.convertWeatherType(weather.weathercode, true); currentWeather.rain = parseFloat(weather.rain_sum); currentWeather.snow = parseFloat(weather.snowfall_sum * 10); @@ -432,9 +432,9 @@ WeatherProvider.register("openmeteo", { currentWeather.windFromDirection = weather.winddirection_10m; currentWeather.sunrise = weathers.daily[h].sunrise; currentWeather.sunset = weathers.daily[h].sunset; - currentWeather.temperature = parseFloat(weather.apparent_temperature); - currentWeather.minTemperature = parseFloat(weathers.daily[h].apparent_temperature_min); - currentWeather.maxTemperature = parseFloat(weathers.daily[h].apparent_temperature_max); + currentWeather.temperature = parseFloat(weather.temperature_2m); + currentWeather.minTemperature = parseFloat(weathers.daily[h].temperature_2m_min); + currentWeather.maxTemperature = parseFloat(weathers.daily[h].temperature_2m_max); currentWeather.weatherType = this.convertWeatherType(weather.weathercode, currentWeather.isDayTime()); currentWeather.humidity = parseFloat(weather.relativehumidity_2m); currentWeather.rain = parseFloat(weather.rain); From aefb3a0b6d1add3a1c5764b680eef006f749e761 Mon Sep 17 00:00:00 2001 From: WallysWellies <59727507+WallysWellies@users.noreply.github.com> Date: Mon, 24 Jun 2024 21:40:59 +0100 Subject: [PATCH 068/418] Update compliments module (#3471) `Fixes #3465` Add config option `specialDayUnique` that defaults to `false` and causes special day compliments to be added to the existing compliments array. Setting this option to `true` will only show the compliments that have been configured for that day. --------- Co-authored-by: Veeck Co-authored-by: veeck Co-authored-by: Karsten Hassel --- CHANGELOG.md | 1 + modules/default/compliments/compliments.js | 7 +++++- .../compliments_specialDayUnique_false.js | 22 +++++++++++++++++ .../compliments_specialDayUnique_true.js | 22 +++++++++++++++++ tests/e2e/modules/compliments_spec.js | 24 +++++++++++++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tests/configs/modules/compliments/compliments_specialDayUnique_false.js create mode 100644 tests/configs/modules/compliments/compliments_specialDayUnique_true.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 9443b6a711..4257949432 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Thanks to: @kleinmantara (to be continued before release) ### Added - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar +- [compliments] Added `specialDayUnique` config option, defaults to `false`. (#3465) ### Removed diff --git a/modules/default/compliments/compliments.js b/modules/default/compliments/compliments.js index 39e6c34d49..c249f9915f 100644 --- a/modules/default/compliments/compliments.js +++ b/modules/default/compliments/compliments.js @@ -15,7 +15,8 @@ Module.register("compliments", { morningEndTime: 12, afternoonStartTime: 12, afternoonEndTime: 17, - random: true + random: true, + specialDayUnique: false }, lastIndexUsed: -1, // Set currentweather from module @@ -98,6 +99,10 @@ Module.register("compliments", { // Add compliments for special days for (let entry in this.config.compliments) { if (new RegExp(entry).test(date)) { + // Only display compliments configured for the day if specialDayUnique is set to true + if (this.config.specialDayUnique) { + compliments.length = 0; + } Array.prototype.push.apply(compliments, this.config.compliments[entry]); } } diff --git a/tests/configs/modules/compliments/compliments_specialDayUnique_false.js b/tests/configs/modules/compliments/compliments_specialDayUnique_false.js new file mode 100644 index 0000000000..e4cb64c6ab --- /dev/null +++ b/tests/configs/modules/compliments/compliments_specialDayUnique_false.js @@ -0,0 +1,22 @@ +let config = { + modules: [ + { + module: "compliments", + position: "middle_center", + config: { + specialDayUnique: false, + compliments: { + anytime: [ + "Typical message 1", + "Typical message 2", + "Typical message 3" + ], + "....-..-..": ["Special day message"] + } + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { module.exports = config; } diff --git a/tests/configs/modules/compliments/compliments_specialDayUnique_true.js b/tests/configs/modules/compliments/compliments_specialDayUnique_true.js new file mode 100644 index 0000000000..3d578611c8 --- /dev/null +++ b/tests/configs/modules/compliments/compliments_specialDayUnique_true.js @@ -0,0 +1,22 @@ +let config = { + modules: [ + { + module: "compliments", + position: "middle_center", + config: { + specialDayUnique: true, + compliments: { + anytime: [ + "Typical message 1", + "Typical message 2", + "Typical message 3" + ], + "....-..-..": ["Special day message"] + } + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { module.exports = config; } diff --git a/tests/e2e/modules/compliments_spec.js b/tests/e2e/modules/compliments_spec.js index 0604dab49f..95b342577e 100644 --- a/tests/e2e/modules/compliments_spec.js +++ b/tests/e2e/modules/compliments_spec.js @@ -54,4 +54,28 @@ describe("Compliments module", () => { await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true); }); }); + + describe("Feature specialDayUnique in compliments module", () => { + describe("specialDayUnique is false", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_specialDayUnique_false.js"); + await helpers.getDocument(); + }); + + it("compliments array can contain all values", async () => { + await expect(doTest(["Special day message", "Typical message 1", "Typical message 2", "Typical message 3"])).resolves.toBe(true); + }); + }); + + describe("specialDayUnique is true", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_specialDayUnique_true.js"); + await helpers.getDocument(); + }); + + it("compliments array contains only special value", async () => { + await expect(doTest(["Special day message"])).resolves.toBe(true); + }); + }); + }); }); From f28b4bd709489ec7bdfc537338a33c701d632345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Wed, 26 Jun 2024 21:43:41 +0200 Subject: [PATCH 069/418] Use latest@version of node for automated-tests.yaml (#3483) Maybe it's a good idea to use latest@node version for automated-tests Actually it's an "random" version Note: it's already used [there in electronRebuild](https://github.com/MagicMirrorOrg/MagicMirror/blob/develop/.github/workflows/electronRebuild.yaml#L19) --- .github/workflows/automated-tests.yaml | 1 + CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 301b08d47b..9ac92f216a 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -26,6 +26,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + check-latest: true cache: "npm" - name: "Install dependencies" run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 4257949432..8d169a4974 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Thanks to: @kleinmantara (to be continued before release) - [core] Update dependencies including electron to v31 - [core] use node >= v20 - [core] Update `config.js.sample` to use openmeteo as weather provider which needs no api key +- [Tests] Use latest@version of node for automated-tests.yaml ### Fixed From 4aafa32875763c2845bde30980f6ca135282501b Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Thu, 27 Jun 2024 10:38:29 +0200 Subject: [PATCH 070/418] fixes e2e tests running in docker container (#3485) which needs `address: "0.0.0.0"` fixes #3479 --- CHANGELOG.md | 1 + js/app.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d169a4974..54b7c2e1e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ Thanks to: @kleinmantara (to be continued before release) - [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) - [weather] Fixed type=daily for provider openmeteo showing nightly icons in forecast when current time is "nightly" (#3458) - [weather] Fixed forecast and hourly weather for provider openmeteo to use real temperatures, not apparent temperatures +- [tests] Fixed e2e tests running in docker container which needs `address: "0.0.0.0"` (#3479) ## [2.27.0] - 2024-04-01 diff --git a/js/app.js b/js/app.js index f6e116d17d..f9313ed403 100644 --- a/js/app.js +++ b/js/app.js @@ -58,6 +58,10 @@ function App () { async function loadConfig () { Log.log("Loading config ..."); const defaults = require(`${__dirname}/defaults`); + if (process.env.JEST_WORKER_ID !== undefined) { + // if we are running with jest + defaults.address = "0.0.0.0"; + } // For this check proposed to TestSuite // https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8 From cfc0bc617f2618692167bf5dbc2ca905510b7aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Thu, 27 Jun 2024 21:37:22 +0200 Subject: [PATCH 071/418] Update CHANGELOG.md (#3486) Adjust my own ChangeLog entry --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b7c2e1e8..5f7f9733fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ _This release is scheduled to be released on 2024-07-01._ Thanks to: @kleinmantara (to be continued before release) +> ⚠️ This release needs nodejs version >= v20 + ### Added - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar @@ -18,18 +20,18 @@ Thanks to: @kleinmantara (to be continued before release) ### Removed -- [test suite] delete node v18 support +- [tests] delete node v18 support (#3462) ### Updated - [core] Update dependencies including electron to v31 -- [core] use node >= v20 +- [core] use node >= v20 (#3462) - [core] Update `config.js.sample` to use openmeteo as weather provider which needs no api key -- [Tests] Use latest@version of node for automated-tests.yaml +- [tests] Use latest@version of node for automated-tests.yaml (#3483) ### Fixed -- [core] Fixed crash possibility if `module: ` is not defined and on `postion: ` misktake. +- [core] Fixed crash possibility if `module: ` is not defined and on `postion: ` misktake. (#3445) - [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) - [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) - [weather] Fixed type=daily for provider openmeteo showing nightly icons in forecast when current time is "nightly" (#3458) From 74c6bb30b0403e20a181c6e25d92b36036741af9 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 28 Jun 2024 22:09:44 +0200 Subject: [PATCH 072/418] Update dependencies (#3487) and minor fixes in changelog. --- CHANGELOG.md | 10 +- package-lock.json | 282 +++++++++++++++++++++++++++++----------------- package.json | 8 +- 3 files changed, 189 insertions(+), 111 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f7f9733fd..51ac3693a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,14 +9,14 @@ This project adheres to [Semantic Versioning](https://semver.org/). _This release is scheduled to be released on 2024-07-01._ -Thanks to: @kleinmantara (to be continued before release) +Thanks to: @btoconnor, @bugsounet, @khassel, @kleinmantara and @WallysWellies. > ⚠️ This release needs nodejs version >= v20 ### Added - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar -- [compliments] Added `specialDayUnique` config option, defaults to `false`. (#3465) +- [compliments] Added `specialDayUnique` config option, defaults to `false` (#3465) ### Removed @@ -27,15 +27,15 @@ Thanks to: @kleinmantara (to be continued before release) - [core] Update dependencies including electron to v31 - [core] use node >= v20 (#3462) - [core] Update `config.js.sample` to use openmeteo as weather provider which needs no api key -- [tests] Use latest@version of node for automated-tests.yaml (#3483) +- [tests] Use latest@version of node for `automated-tests.yaml` (#3483) ### Fixed -- [core] Fixed crash possibility if `module: ` is not defined and on `postion: ` misktake. (#3445) +- [core] Fixed crash possibility if `module: ` is not defined and on `postion: ` mistake (#3445) - [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) - [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) - [weather] Fixed type=daily for provider openmeteo showing nightly icons in forecast when current time is "nightly" (#3458) -- [weather] Fixed forecast and hourly weather for provider openmeteo to use real temperatures, not apparent temperatures +- [weather] Fixed forecast and hourly weather for provider openmeteo to use real temperatures, not apparent temperatures (#3466) - [tests] Fixed e2e tests running in docker container which needs `address: "0.0.0.0"` (#3479) ## [2.27.0] - 2024-04-01 diff --git a/package-lock.json b/package-lock.json index 018afa76b6..bcd28e429f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "@stylistic/eslint-plugin": "^1.8.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.2.12", + "eslint-plugin-jsdoc": "^48.5.0", "eslint-plugin-package-json": "^0.15.0", "eslint-plugin-unicorn": "^54.0.0", "express-basic-auth": "^1.2.1", @@ -41,18 +41,18 @@ "jest": "^29.7.0", "jsdom": "^24.1.0", "lint-staged": "^15.2.7", - "playwright": "^1.44.1", + "playwright": "^1.45.0", "prettier": "^3.3.2", "sinon": "^18.0.0", "stylelint": "^16.6.1", - "stylelint-config-standard": "^36.0.0", + "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "optionalDependencies": { - "electron": "^31.0.1" + "electron": "^31.1.0" } }, "node_modules/@ampproject/remapping": { @@ -864,9 +864,9 @@ } }, "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", - "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", + "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", "dev": true, "license": "MIT", "engines": { @@ -893,9 +893,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -928,6 +928,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -952,7 +953,8 @@ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", @@ -1552,6 +1554,19 @@ "node": ">= 8" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@pm2/agent": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz", @@ -2150,9 +2165,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.14.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.6.tgz", - "integrity": "sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==", + "version": "20.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", + "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -2377,6 +2392,7 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", @@ -3147,9 +3163,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001636", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", - "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", + "version": "1.0.30001638", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001638.tgz", + "integrity": "sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ==", "dev": true, "funding": [ { @@ -4120,9 +4136,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "31.0.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.0.1.tgz", - "integrity": "sha512-2eBcp4iqLkTsml6mMq+iqrS5u3kJ/2mpOLP7Mj7lo0uNK3OyfNqRS9z1ArsHjBF2/HV250Te/O9nKrwQRTX/+g==", + "version": "31.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.1.0.tgz", + "integrity": "sha512-TBOwqLxSxnx6+pH6GMri7R3JPH2AkuGJHfWZS0p1HsmN+Qr1T9b0IRJnnehSd/3NZAmAre4ft9Ljec7zjyKFJA==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4139,9 +4155,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.806", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.806.tgz", - "integrity": "sha512-nkoEX2QIB8kwCOtvtgwhXWy2IHVcOLQZu9Qo36uaGB835mdX/h8uLRlosL6QIhLVUnAiicXRW00PwaPZC74Nrg==", + "version": "1.4.814", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.814.tgz", + "integrity": "sha512-GVulpHjFu1Y9ZvikvbArHmAhZXtm3wHlpjTMcXNGKl4IQ4jMQjlnz8yMQYYqdLHKi/jEL2+CBC2akWVCoIGUdw==", "dev": true, "license": "ISC" }, @@ -4381,6 +4397,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", @@ -4711,9 +4734,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.2.12", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.12.tgz", - "integrity": "sha512-sO9sKkJx5ovWoRk9hV0YiNzXQ4Z6j27CqE/po2E3wddZVuy9wvKPSTiIhpxMTrP/qURvKayJIDB2+o9kyCW1Fw==", + "version": "48.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.5.0.tgz", + "integrity": "sha512-ukXPNpGby3KjCveCizIS8t1EbuJEHYEu/tBg8GCbn/YbHcXwphyvYCdvRZ/oMRfTscGSSzfsWoZ+ZkAP0/6YMQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -4723,8 +4746,10 @@ "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "esquery": "^1.5.0", + "parse-imports": "^2.1.0", "semver": "^7.6.2", - "spdx-expression-parse": "^4.0.0" + "spdx-expression-parse": "^4.0.0", + "synckit": "^0.9.0" }, "engines": { "node": ">=18" @@ -4819,6 +4844,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4889,7 +4915,8 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/eslint-plugin-unicorn/node_modules/minimatch": { "version": "3.1.2", @@ -4936,6 +4963,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4960,7 +4988,8 @@ "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", @@ -6214,9 +6243,9 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "license": "MIT", "dependencies": { "agent-base": "^7.0.2", @@ -6500,12 +6529,15 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7586,7 +7618,8 @@ "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -7944,9 +7977,9 @@ } }, "node_modules/listr2": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz", - "integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz", + "integrity": "sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==", "dev": true, "license": "MIT", "dependencies": { @@ -7954,7 +7987,7 @@ "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.0.0", - "rfdc": "^1.3.1", + "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" }, "engines": { @@ -8651,10 +8684,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8871,9 +8907,9 @@ } }, "node_modules/pac-proxy-agent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", - "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", + "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", @@ -8881,9 +8917,9 @@ "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "pac-resolver": "^7.0.0", - "socks-proxy-agent": "^8.0.2" + "https-proxy-agent": "^7.0.5", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.4" }, "engines": { "node": ">= 14" @@ -8932,6 +8968,20 @@ "node": ">=6" } }, + "node_modules/parse-imports": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.1.0.tgz", + "integrity": "sha512-JQWgmK2o4w8leUkZeZPatWdAny6vXGU/3siIUvMF6J2rDCud9aTt8h/px9oZJ6U3EcfhngBJ635uPFI0q0VAeA==", + "dev": true, + "license": "Apache 2.0", + "dependencies": { + "es-module-lexer": "^1.5.3", + "slashes": "^3.0.12" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9176,35 +9226,35 @@ } }, "node_modules/playwright": { - "version": "1.44.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", - "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.0.tgz", + "integrity": "sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.44.1" + "playwright-core": "1.45.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.44.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", - "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.0.tgz", + "integrity": "sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/playwright/node_modules/fsevents": { @@ -9999,6 +10049,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10581,6 +10632,13 @@ "node": ">=8" } }, + "node_modules/slashes": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", + "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", + "dev": true, + "license": "ISC" + }, "node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -10677,14 +10735,14 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", - "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "license": "MIT", "dependencies": { "agent-base": "^7.1.1", "debug": "^4.3.4", - "socks": "^2.7.1" + "socks": "^2.8.3" }, "engines": { "node": ">= 14" @@ -11118,26 +11176,46 @@ } }, "node_modules/stylelint-config-recommended": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.0.tgz", - "integrity": "sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", + "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], "license": "MIT", "engines": { "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.0.0" + "stylelint": "^16.1.0" } }, "node_modules/stylelint-config-standard": { - "version": "36.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.0.tgz", - "integrity": "sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug==", + "version": "36.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz", + "integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], "license": "MIT", "dependencies": { - "stylelint-config-recommended": "^14.0.0" + "stylelint-config-recommended": "^14.0.1" }, "engines": { "node": ">=18.12.0" @@ -11377,6 +11455,30 @@ "dev": true, "license": "MIT" }, + "node_modules/synckit": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.0.tgz", + "integrity": "sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, "node_modules/systeminformation": { "version": "5.22.11", "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.11.tgz", @@ -11420,23 +11522,6 @@ "node": ">=10.0.0" } }, - "node_modules/table/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -11454,13 +11539,6 @@ "node": ">=8" } }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, "node_modules/table/node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", @@ -11820,9 +11898,9 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", + "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -11968,9 +12046,9 @@ } }, "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index dc9a8d298e..56ee43bc42 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "@stylistic/eslint-plugin": "^1.8.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.2.12", + "eslint-plugin-jsdoc": "^48.5.0", "eslint-plugin-package-json": "^0.15.0", "eslint-plugin-unicorn": "^54.0.0", "express-basic-auth": "^1.2.1", @@ -85,15 +85,15 @@ "jest": "^29.7.0", "jsdom": "^24.1.0", "lint-staged": "^15.2.7", - "playwright": "^1.44.1", + "playwright": "^1.45.0", "prettier": "^3.3.2", "sinon": "^18.0.0", "stylelint": "^16.6.1", - "stylelint-config-standard": "^36.0.0", + "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.0" }, "optionalDependencies": { - "electron": "^31.0.1" + "electron": "^31.1.0" }, "engines": { "node": ">=20" From c89c3edf974d8de892ab8d93fa248961d27f6a09 Mon Sep 17 00:00:00 2001 From: Jason Stieber Date: Fri, 28 Jun 2024 13:21:38 -0700 Subject: [PATCH 073/418] Fix weathergov api precipitationLastHour (#3125) Pull request fixes small big in weathergov api format mismatch #3124 --------- Co-authored-by: Karsten Hassel --- CHANGELOG.md | 1 + modules/default/weather/providers/weathergov.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51ac3693a6..fe997efda7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Thanks to: @btoconnor, @bugsounet, @khassel, @kleinmantara and @WallysWellies. - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar - [compliments] Added `specialDayUnique` config option, defaults to `false` (#3465) +- [weather] Provider weathergov: Use `precipitationLast3Hours` if `precipitationLastHour` is `null` (#3124) ### Removed diff --git a/modules/default/weather/providers/weathergov.js b/modules/default/weather/providers/weathergov.js index 3c16bd7344..8a65478465 100644 --- a/modules/default/weather/providers/weathergov.js +++ b/modules/default/weather/providers/weathergov.js @@ -211,7 +211,7 @@ WeatherProvider.register("weathergov", { currentWeather.minTemperature = currentWeatherData.minTemperatureLast24Hours.value; currentWeather.maxTemperature = currentWeatherData.maxTemperatureLast24Hours.value; currentWeather.humidity = Math.round(currentWeatherData.relativeHumidity.value); - currentWeather.precipitationAmount = currentWeatherData.precipitationLastHour.value; + currentWeather.precipitationAmount = currentWeatherData.precipitationLastHour.value ? currentWeatherData.precipitationLastHour.value : currentWeatherData.precipitationLast3Hours.value; if (currentWeatherData.heatIndex.value !== null) { currentWeather.feelsLikeTemp = currentWeatherData.heatIndex.value; } else if (currentWeatherData.windChill.value !== null) { From 92ac3895a77928906446f7fdf8e103a117a92f39 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 28 Jun 2024 22:33:21 +0200 Subject: [PATCH 074/418] updatenotification: avoid using pm2 when running in docker container (#3484) related to #3480 Change module updatenotification so that it can work without `pm2` in a docker container. It now tests if file `/.dockerenv` exists and if so `require("pm2")` is never called. --- CHANGELOG.md | 3 ++- modules/default/updatenotification/update_helper.js | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe997efda7..57446d26e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). _This release is scheduled to be released on 2024-07-01._ -Thanks to: @btoconnor, @bugsounet, @khassel, @kleinmantara and @WallysWellies. +Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @WallysWellies. > ⚠️ This release needs nodejs version >= v20 @@ -29,6 +29,7 @@ Thanks to: @btoconnor, @bugsounet, @khassel, @kleinmantara and @WallysWellies. - [core] use node >= v20 (#3462) - [core] Update `config.js.sample` to use openmeteo as weather provider which needs no api key - [tests] Use latest@version of node for `automated-tests.yaml` (#3483) +- [updatenotification] Avoid using pm2 when running in docker container ### Fixed diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index 33130f1988..0bf3868e7c 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -1,6 +1,6 @@ const Exec = require("node:child_process").exec; const Spawn = require("node:child_process").spawn; -const pm2 = require("pm2"); +const fs = require("node:fs"); const Log = require("logger"); @@ -139,6 +139,7 @@ class Updater { // restart MagicMiror with "pm2" pm2Restart () { Log.info("updatenotification: PM2 will restarting MagicMirror..."); + const pm2 = require("pm2"); pm2.restart(this.PM2, (err, proc) => { if (err) { Log.error("updatenotification:[PM2] restart Error", err); @@ -160,6 +161,14 @@ class Updater { check_PM2_Process () { Log.info("updatenotification: Checking PM2 using..."); return new Promise((resolve) => { + if (fs.existsSync("/.dockerenv")) { + Log.info("updatenotification: Running in docker container, not using PM2 ..."); + this.usePM2 = false; + resolve(false); + return; + } + + const pm2 = require("pm2"); pm2.connect((err) => { if (err) { Log.error("updatenotification: [PM2]", err); From 795e5c76c17e8b0ded3902aa3192286cbc72a1ba Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 28 Jun 2024 20:42:08 +0200 Subject: [PATCH 075/418] Release 2.28.0 --- CHANGELOG.md | 4 +--- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57446d26e0..9e882fd9ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². -## [2.28.0] - Unreleased (`develop` branch) - -_This release is scheduled to be released on 2024-07-01._ +## [2.28.0] - 2024-07-01 Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @WallysWellies. diff --git a/package-lock.json b/package-lock.json index bcd28e429f..5ed883c35e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.28.0-develop", + "version": "2.28.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.28.0-develop", + "version": "2.28.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 56ee43bc42..55366ee296 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.28.0-develop", + "version": "2.28.0", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From f7369a7e85081ad46e8da6adbce5188788a666ad Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 30 Jun 2024 23:53:28 +0200 Subject: [PATCH 076/418] Prepare v2.29.0-develop --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e882fd9ad..37a4de2971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ This project adheres to [Semantic Versioning](https://semver.org/). ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². +## [2.29.0] - Unreleased (`develop` branch) + +_This release is scheduled to be released on 2024-10-01._ + +### Added + +### Removed + +### Updated + +### Fixed + ## [2.28.0] - 2024-07-01 Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @WallysWellies. diff --git a/package-lock.json b/package-lock.json index 5ed883c35e..c30419db67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.28.0", + "version": "2.29.0-develop", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.28.0", + "version": "2.29.0-develop", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 55366ee296..9f1469c127 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.28.0", + "version": "2.29.0-develop", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From 160d95ac3404306493d7b6e174a124b6d9d025bb Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Mon, 1 Jul 2024 17:09:50 -0500 Subject: [PATCH 077/418] Cleanup folders for #3492 (#3493) remove installer only files. into installer addresses #3492 --- CHANGELOG.md | 2 ++ installers/mm.sh | 4 --- splashscreen/MagicMirror.plymouth | 8 ----- splashscreen/MagicMirror.script | 53 ------------------------------ splashscreen/splash.png | Bin 37062 -> 0 bytes splashscreen/splash_halt.png | Bin 22304 -> 0 bytes 6 files changed, 2 insertions(+), 65 deletions(-) delete mode 100755 installers/mm.sh delete mode 100644 splashscreen/MagicMirror.plymouth delete mode 100644 splashscreen/MagicMirror.script delete mode 100644 splashscreen/splash.png delete mode 100644 splashscreen/splash_halt.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 37a4de2971..f62d40b3cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ _This release is scheduled to be released on 2024-10-01._ ### Removed +- [core] removed installer only files, (#3492) + ### Updated ### Fixed diff --git a/installers/mm.sh b/installers/mm.sh deleted file mode 100755 index d56ffca359..0000000000 --- a/installers/mm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# This file is still here to keep PM2 working on older installations. -cd ~/MagicMirror -DISPLAY=:0 npm start diff --git a/splashscreen/MagicMirror.plymouth b/splashscreen/MagicMirror.plymouth deleted file mode 100644 index b6887bf56b..0000000000 --- a/splashscreen/MagicMirror.plymouth +++ /dev/null @@ -1,8 +0,0 @@ -[Plymouth Theme] -Name=MagicMirror -Description=Mirror Splash -ModuleName=script - -[script] -ImageDir=/usr/share/plymouth/themes/MagicMirror -ScriptFile=/usr/share/plymouth/themes/MagicMirror/MagicMirror.script diff --git a/splashscreen/MagicMirror.script b/splashscreen/MagicMirror.script deleted file mode 100644 index 6e2f5643a9..0000000000 --- a/splashscreen/MagicMirror.script +++ /dev/null @@ -1,53 +0,0 @@ -screen_width = Window.GetWidth(); -screen_height = Window.GetHeight(); - -if (Plymouth.GetMode() != "shutdown") -{ - theme_image = Image("splash.png"); -} -else -{ - theme_image = Image("splash_halt.png"); -} - -image_width = theme_image.GetWidth(); -image_height = theme_image.GetHeight(); - -scale_x = image_width / screen_width; -scale_y = image_height / screen_height; - -if (scale_x > 1 || scale_y > 1) -{ - if (scale_x > scale_y) - { - resized_image = theme_image.Scale (screen_width, image_height / scale_x); - image_x = 0; - image_y = (screen_height - ((image_height * screen_width) / image_width)) / 2; - } - else - { - resized_image = theme_image.Scale (image_width / scale_y, screen_height); - image_x = (screen_width - ((image_width * screen_height) / image_height)) / 2; - image_y = 0; - } -} -else -{ - resized_image = theme_image.Scale (image_width, image_height); - image_x = (screen_width - image_width) / 2; - image_y = (screen_height - image_height) / 2; -} - -sprite = Sprite (resized_image); -sprite.SetPosition (image_x, image_y, -100); - -message_sprite = Sprite(); -message_sprite.SetPosition(screen_width * 0.1, screen_height * 0.9, 10000); - -fun message_callback (text) { - my_image = Image.Text(text, 1, 1, 1); - message_sprite.SetImage(my_image); - sprite.SetImage (resized_image); -} - -Plymouth.SetUpdateStatusFunction(message_callback); diff --git a/splashscreen/splash.png b/splashscreen/splash.png deleted file mode 100644 index b2acc49539505c9bcc991e155f5b4decc9534069..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37062 zcmeFacUaR|7B?O%Dk#p1D578qV3dx4KmZjHBTYd?x|C3)M0!t9N7z9H4ZUWRHi&@I zdqe~b9g$u_?+^$j1OoZpFS@hr%~p?&B}lHB|QQ zIkE=^gY89Ky{rX;Z3o3|uw6UBufoEEd%>^W_pj@VrGMOK5mM(w6>Q&Nhud zWWm34qQ}2ICl&U964KG!LRRbYm2cgFzvNF^IXmB%6%lcBa}#!x5XLxK0&*D{5m9jw zad9C~L&(X)-r2-m$lmGH*GB%)&SkWdnWOc6XKRf8aj0DrQ;dtV{K=D0N54Pc=4E&P z_m1qHzF`MY6md7XFCr!^D)LuE=4QXs+;?%b-58p=nF!hzZHKmZb^>%_e@S=W3ge7% zvcmkEE`R^}-*ybvL|y&&zW;K(c6NW+wUe{5D}dk|q<=~2bkpNLT0{%&gmG~+Lo2(2 zshs+&**jZX{Bv>sr6uT_e>--xyY;^zgTDDnw!sQtR|pB_Dy!s(HgU!{-o#*R6~1!W z^?yKkTuBMyDoJ6<h&h74Q`V~**iI#*qfnImlePZVQXu1S#h)T(q>W?GD2u^aTB3)5)x=38PRj%Lg!_~ z&&ilei%UtHifw?XuD+T4PfcIOn7KeZ=3CR||6|je$p6%|rlU2Gb|$u)>OiCaU%U8= zX8zRGRcj}}qaK@h7jW=~Jkv%y{Oj9)d|_+7A(!r(I69%BT_=C?AKUJCLH4_xf@n5& zudIm~B+(SipiO}`M~eK*+kX!0cgk;M*8hJO@N4^<$p3vGZdPdf|FogLHnmaf-#6lf zv2b=XaYSFV1U&KI?)R@P|10SqyFiLSTEN!&Ul-%++kai7e{k)e*Axi}H(9_BU~DEE z>i}5%Pw)QO^Vj-!pmnu%*{ClqE(#tIG3fIf>E^HhNUHmvNjHD}N78>%-m(d*`w>*uzc`XNrl6pZiAj$FKg9 zRQI2x(o*L)Q*Qd^8|By4+N9Yx7W3;{U^f7hMdWvz!VkDMqw(GH54gSy z(dG(2;M$DFcgsKE`YuG9EBt_KGaBD5|A6be5N)pT1Fp?ze7F1quJ1y$xxx>)Hly*~ z@(;Ma3(@8ZKj7Mo#&^p<;QB5^n=AZ)Ycm?(E&qV)yAW-z@B^;RXneQ)1Fr8vw7J3$ zxHhBl-SQ8(z6;Uj3P0f5jK+7%Kj8W$?zbuJ8k{&1ihL`~$A< zLbSQU54bj?@!j$dxV{U~<_bUH+Kk3`%Rk`yE<~Fv{D5mS8s9Ddfa|*uZLaVGuFYtC zxBLUH??SY>!VkDMqw(GHe}rq#KW_n|?ZMSQH*m+VgJgFI+z&i%c2!Fq2J_^D!F(UV zV00$-cJzg<}XdjXFhB&X|I$JMo z-+KD^C*_M5_rAJbyyN2a-yFwoXxiB2%?x(8iS9pj{iktmjQ&qe9EU;AAIIst@%B$m{HOl@*aYl9_4mI_^}@zj{!`a~8s~rN z`j6xMpQd_zV=RAc;{VN5|1|6GLiB%cs^9JUPY_+$K=Qw&`=6%zKdsJ2<>MP;`7i1I z%OQWA-~YmhUm^OxH`V`T&%rh-|6iM`?*`!i6rPN_lD`* zmh_PuUz~vyuveq5qNJui;6{y+wd7Ty;nHba0eEDafdGF&f#BE`8&^E>s^dNU44fG< z#HukI8K03M;?Ik9pUEE#Tv%L8)Jl13DVY^)5H%D+og?zmtKc-L?Jxm8dOVeEEZne| zC%YBQz_(B}7-mDN!1F&Y~#T{5mN zL;ZAWexW&@Ck}TJUx4s)XSAG-W8Mugf}xsh?!JtNIKDmZRB%jbaIY5yu6pdDwRE@q z30@6qqkVpcs<`vc#qrGZ%Csrctg|0)_5Gk`kCE}|>AKc5eF>Y^H^ozEks4JaDt=*M zVam$!{WW}ZHIsRoWEk&Vw6Z_lLvGFh;-RTa^&Ke6DmC+}sppy{9=$gxkDq?swL$lz zoZA4sDHJ9kahi710=tOwGu^2%dQVhU0n_pG zOX&G?M2bfgHo5(|sqIRtw)0t{Bx$;6ZoO2vV!LOvd|AIaJEq_a>4{b?qZC2P%bM&h zFbQfRlL>(7`BcN;s4yY@Fz|q-mR8I;MLIFeBpfc+w^b7}zGg$;u^|k)Zc$!)*PSaJ zeK^I~-MM7W9c+;6KQ;LaDzIU}@2E=BVXSBeRuB7*HHCbzPg%tC2B(l-h`xOR-`U%5 zt|n@sY$h+%m8LM{yTgV?&F-vW_daHFrtJlAAEtVoQ?h)59X!VZvrNcW)-%Kfq>mN8 z74PT_F2+V}^OcZrcdSd+W>dNU*p+?XmX(zi$4@8x&F2OxbPF8O=_N~@Z}juhd%1rV zA+cA!n@~Ekb$kE*3$0Hcc3K z&2Vm4B!pUz|Dzn8&rU})`?i7sD- zxo>lS4i}O!TLveqi`B@njZII-TJ4&h;mBipAxYucr+tB0eLj>!r;FH|&3MDc6RvnG z>XDyKu%M<`|j*wf%P0&@7<&Yy96p)=qb+k@j6mMt6BjwO{_;b`7ioBtPznGQsmc`kif+s z3Ne0Gs>jLX=d<{@|88%whYXW3KaUSDhCksHx~5vQPq7q>Bz42j;u-O`x3^dF8u-5K z3`XLI{NTxwf{JpaLrJqf#?h~8?)3yC3T+yyzw{=T2$ANsyOq|)I3z3^gow1u9h`0g z1u_-3bMo5V>q3ai1VYSEJDeq~t2ugLV$pE;UBNqpR$DB-1CcJ6$FEB$bCR7JDql!#A zP=4ry<9%(JX~`tsiWVGDbMH^@Nr2O@X~V7)<;fEWPx1(fnJ&!wxIlXWJCA4F!{>!m zlv#DZ7l5$LSYk6z?LuLi9EwnwZcz=3ieji zc-8pC{e2K$EKzZcZy$HXymV;STnd~V^-(H4q(WD+qJ^etwcKkH%rMzW^Ny@-;Lfnq zTWaw$JIB@kfqagmT{Bd9#Y&)o@eEGE?1Gi*$0@n6!0A`<(xE07vy}1db5eo`LX z|HRmOkAAN~Dbu067;DYd&S*Q_HPlVD9RC9MqVyH`AS|kxqf`SjvTX1joP?7?+AHwH zqJ+`+aR+#7) z?A{&jgDm|!xMcl2GLfkW+pD>CO4lPF(!6|hZ!)G22QU*N#Ma|cVSBY3)jz&OrJs59 zIQR-Z>Ojq?aooT)&mIMI*-|aXgF1#7=cgyZf@g^PPAff_n^2>Mqp&x3!u+36U9z;d zUm~kfc~MKT39j}HxdnphpZd;HRFd+y${#ek87JqmhDwk5IPc}^@n)jRZtifK9MLx1 zGHlX1hBBA{Zxf&|{shL6uSG18QcN)E;zW1FupC1P3$wNiUUB!)42U}s?{X)g;GnSP zPv@uQ1KP6rJRI;1`~~)ZtAC`czFL&uFELu|*tPEc^MK+orRQSFr8A+|06siE3r#>F zzUZVAstKVg+CX(cV&kUrT`lM7HP>cZ(izzKjS8rHXT>uh+S}#d!Wzr|G;DI;NQ$6I%N{q#y= zbAO=^(IlY0U_N>eHM%B)q}5X<*8O6{DM6vRy9x0yzuawhWqQ%{x4l{Ni;GO9fYiRO zW-&jf<)@jxxV7z_)E%gGIc3TN5|XC`;i+R7_DZLGi7oPZrdCP<5L@gD%Y9dMm`p+C zzw4<|)5ZMwVP0%XFjy|d22uFAwWL_^<85GuooiTUKI6!P#n|$qnv}8U^AZjR`(OfQ z*1VGQGqJY0&v@;>#0?p1btm5KIG<;E5wEJf;Cndz@A-VnZ9`tcZx95Wxo$%7+it&v zd?F(eF|%6I#&#aFbcQun$2K_)qv{}6s**K*W^Om4@R~GvvHxcdohjqU{;H%P<+bX2 zn1W}|v2ISvA{J;GXrKNM}J3` zKfU+Vu*^G|it8aI+*=<_%kWja4e%)U#@Ge$D7wK5h_Y5L_=%gM zH+xx^4OhShn>az5dTPh>2uz7p;an{xN;7ec>)mUE+Xx(O%1ZdrBQ3UrkqSgNfvjf^z`(! zZjq~6>OKZ(&{k2~i$9BBm#kK|3UfRMXThJz=N%e{ew>!YjUokaB#<(LD z53t)3bUEYd*59(7OK(^zD$GEMDY&EP-6NM6Qx3MxPiihnt5@{#hM1HGdLHbKG5!4B z*yc1R_H0FHW9;}XuFkX~0a91>rAZb!t4V)6162?=632hYV$A%-0f#ElX+|Z=K4@gI z=XsgidG{;1i$f8Jz~!ovmguN|X#yX$RuRe!P)Mu~AG->}3tnCru2jl4n?+ZG2IR|8D; z5O1%i>$fdrQOye|)^>Jvg)Wnh6$f?9dkS5w?T&@yWQP*N_nm2*TT-iohe78K`A-MS zInq@$J{O+lLVo;p9s7*ebX5HkY_>GB@t*LyqHN{jn=?BforEh0lsKDFJq z92YyVZ^wam$GiAx-o>^J8I;*@vqb#T(o(l`v%1H?F9M%?72pCZ}`vx#+xDo-+N*h&q1@8l#$m}lOQtO%X$s(M$tcX(X^SaW&e&ikIv z#d#4WqU=&{o*5q-`^1i0E@wTtRw6EP+N3L*7IIAs8 z3XGQ+5z2Z9l&fMFyUq3Rb`nEvia#@_x3gxXisy5$Dj;UcFZ_VTw7gm&XDR(z&+9G z-kN=?!aRydY2bvkP%-Detf{l*94!seeXH4)Ry1Z!=HOhZS&KJru1dl^@WEWZJgHe7 zr&;Ov_^n6GdVreuK!Ff~e@nNnP6(|&cjl9ePGW?p{mE8yt2{a%SC`KW_q23v=7^Di zC34C?LRnOp?8*uXS1&2)IUhIw9Pka$YKH;`r45@1lmGvZO@b&d!crA%cAojVYA@a;>~>h3VD78B;2v%npNH zA=$yUTwy*~PDNN`rh6F%2p12Q3@{3lOl@_Ol2})B&}F>@Q+#1j)|&2^N_^ByS^%$| z98yjRBkfuapSHoc_O`q~AaVWUQ`3y%>NM9jI!F7I0bJd&})gJB%k0f2Ti+}IP8hq>otkP?h6DEaOm*X2 z(roZhUGm^&Zl{-D=)aZL-R#~omw(W)#Xy%^yjZX@zUy^u@!$Kxb5-EbbF`v z&!>aA4*TRFV80oc@oF}e;{1BkXD79tv6_#IB(hl<<|}3JH}M|3v}o|OyqWdPy+;HP z@(wYR6LqeaN+E6PP<4#HP9qXpTU+}rRy6~Pyu5Q6J@mVH&7^$oaw}Y~el_9c;(Evy z;9zG2=NX3|h%-IjvH zL;6~3&)r`rqQU0#ZQ?Wum)s6RiLt*Ym`@#`Nj79+dt3whO0vA_I;c;Rs!}DK&zGeq zmAt&4?&XeeC}FLkrG$=_7ovLo7ZI0!b2}%$bGbc?_-YCZO>ie+Rw++woxMFp%&srX=KZP)gvZGW_Kn8)G*}EW3hsU;pW+k+G zu(mpZPF}8I>$`1r<`0r@MKa`gr=Aj%o%|5L3CzcMdmpK%q(*J^4G&i)-?8s;+c=^Y zc^{G^S{APCe}08svuyPo?R2|zg`Jjwi{nS&%93#!VUr#qHYp}XB%7YRE#m^X3Raiv zh8_>(2wsf6t&pA&@xoJZ%X@27T+6I`&%Uj`v57W654^dJ#T4r-L>adQ|Dt&$s!ST^$8k@eS9Sg8O$M_&L392c&vufwNO~LPQ--d{1MtTkw36xSCwu*TUA9xC637$9n~kVgvCRi zh=|*AXS&nXsD}{gf&8SO5d4cpt{jtb!9%r4XyYE#s)rh$89cCuBG$ZITKBj{FS+}v zEKx+2I^%ZqvrK)I*vFQkgxrKBf0%Z*T8WkD(U@ z)45%_ZLBa~)bh5i@7sZY!rC}KONHL4lXO_yFi-YWL!iPf&V>BOtTYmlWXVOT(S3C*|H19QL$tN+_CYXv$tRwVv8>J?-`}Ltn&6qaB9{85Xml zj4ZtOX}OtttbOy~SqXYp0jA*>)Vic{IP=9D4Y5i$Gkn@9WHMjH^9Loddx~O9IeM13 zDH1r~m_1fu6aDCIP3ENL?5A^0tgs6(n5eeTsR}{Ld`*=KT&Bc80Z&I6Nvgp_4K)yC zOus03)g*wcFGH1T#RZ$P>Ry_b+x5407sI%rM|%keG!Q|H$GSY!eNL;HJ)d<^Cs{?Z z!tPE$=TU`JiG{G6meYNb8Kl15?L40vUvAeP?t?SM)aGzr0dZ`}{B-w#8S+_`8w@v% zKFp_daoygysX(^UEaj@x^^|#WcY~EoD#J8tV${$)7C7j3%s#b5p7QbW2|NR7)k>?l z?x|W^qAJ5fJt#vh(<3T(F&MQEoYE^eXdcWA>-AsB#SQZ@*Ca9{ir-jwOo~&_&#z32 zavQ$nO3vw{L_DOqUkT7>s*^RqpdlcX)->_A_68kFKD<*jW-U18UGScSaC58W**Z9; zu5r~{(?6%k8uqqm(Kes|k=MhRh!_6eM~$&Wd#5Bf_nNpQfeN;@x{4KZ?)2n_5Y5h% zLojHZ{CbLNFXk(Mid&81$fC6M#Jzg5;Oy>&Z}qF<#xpc5>W6HFIu3&ARbq>l z6?&q}@^Wo89oKg?`1tHJMgTwO{zFMuaDE!+Wxe+FCev>}@`?28a-G-#`Ew&u((idP zUMF3`CEV?s9QGeik&+{wjS4f28Y+!#x3G!gp+pZy=)bkH9psjii-+6_T?)S+YF-zu37ioH(Uc~*pQd|*D|d;OGnT7{5>Oa ztg}QyUP|pnQw}$Wd7WV|^YdzOx4)1g?*XBW% ztij!v1T0w=w?fhG+6z799A8Gy$s0wL1#j!cPm?w5#E-=Rw_={!pjVJNx_OX}n9+Kh zddM8iM5umfubq`D)e=?ud}w}{D4<@BO}i%6rfdj#51&N|urOQ$ip)iGqWte14J8p+ z`hH8Qs*#YF566#vg(yRr4_ zbXbWMeko6Jke#3ZH9d~TD)8>O-0?^LsD*_5BXY;qDGF4?@@cKF#`savG@7>g zrnsr@WN)|{p#MT6EIfSFFrHVPrtysltXKRH6Akvu7kcmH8xqE2eKY7Z@5$|ZXjhUg z$Cmq=JY`Ah>NWMBhPpA{#Hr%`?b7HmBrGE?!G-wiI8rZm=%saM#v-b;DSPTo5^geG zO^gMmO?d}bw9;GhW1I0g_tPP;S}%sGnoEM8mB4_PS}V2Xs0U=aXt;Uo40arD7KS3s0!fJE z7<^nD&xwuwm0WbH;<|6)W7PV|iqNjYy4KC0@gzy(kWr%_n%&$A_TfvR zxRU?FV!20@YEd3sWSRWqm0(6yeRmV^s0-?5!d1frf7%LZIM+fwKO?@i9JbO!j64bF zos1M$rYMD;$|Wn)XJr^NRC3B21N3h-M+yItl9MFNQ>UUOl$gZ&6f}_Fp=9-%UcxVr zg>i(kl3lkgSG@4H^?j+Uv8diSQ^yaLrp{T$JDMj_;JB`ATYEgNZrSTYv7%DOI!;o_ ze_D+q(yk{YFE4)y1}(``2bX}k>1RiZNH`w>TWz-j!)N<6sqe(nEj93(0`$w}3X)`Y z?>A1Y3?+P;dd<3&Qc)=769~zLMmh*Qm@(;eb;YZSyNiEnvQno?muFWoYwEcyaTVK% z4PTbKMJwpPApBSaj|>*}Mh^|D*GR$XjcV;TzAguUfe0xFOm$K8@v<}LE+7vveDq{^ zLwA|YAvk>zE)DlkDW?*-ER3sU>Ft_$Z`X+Z{Whp|Bqw7eX^k+nqR zdnEAuXuSjC(rY5m366YB($t&%u)C(6=eE30D3nzaSXaek_&gj1?3#g_71&~P#K-~r z9b^q^xgR^-4pA8^f@*Rp@yKOn2+%L!MWlojMU^SO@4SyNuhSKt(YP_1)G|0mm0Fki z)*GC`b&@2yJeBrv_z$q&$tCeyyW;f)vuy#QQkeWuMg_u+jpk(Kl0db+S zD-CMYR;o?*Ds3e5utCp4$!NmZOsNA~SI!9%Q$x&ky)lV$Ow`YAQs~JblT=@Hsduai zjuBMCkM7Gd#t0Ix*m&Tbf*IZdlr}V4tfTkKQaHVdJT9#M)B80iyskP~E|;;=Bld<8 zJp3;1#m_LH&rox4aYXWHQi*tP#3O-3?u^#mxh_4&5cVuGO|zp>9C=rZeeg?` zCr4>^D0@3SSDPz5M?~Z1i(HP{8FiE?XpT~R`*ZCw>r;-=P4S5bkUT-j5l`pWhI7c7j`i~YW6p_5NWJaf+Fn8)+#EdF4ox`v} z#Z0?k4HzlSY^8~PLTJ&(e06~!CtlnQKNv;bVf10sop95A4}vqN_pt@vFh};h)hvm; z)3#I{PuIpVvVLai1$ghoeuF8*llot78v5*2#K{jY z-4-x8X4cd->vY?=!8}Fk=%Zg4jKEeGgx~XGX_CB|drv&VvmqwrrIVA|f?KP5;CTKe z-+MVnU{`Lx2-)gY2u{TGzjF*4ry|mCrlF{xw%_h}G4zS!gbklEZF=v4JLDL)X&xfd zZ1Nu2);{1JEd%Ayf+cX2e>j7_Gj|^tVq|qk+OA0}5n5J`Agl|I410Cx<7L6C4#SLW zj&jbWy4?4k+Q3^WO``ejW|h^h{d;fwf&K=qrzO14S~--sI;(x|p~RN3nHD`bd)=6l z^A$)|)+0-4MQm*LYGNwy*#+*rVb4>vL%+=P+&bBPwgSoatiP`L0J8T<4S{%#P7x7z z9;klzCO$(DtDhoY>HceyC!K%)8*FmbH-!*j{opvaGzz6Oa5&cOyY=%1Fc7vlz&1$dJ2hab7rB0x?|- zA3Z0udV`-9HvnTiFArg!u(L)b zYIVrqKI-dz?(L0RT5`2)*05a#p>l*i?PduJ%qt1xr@Yso#>2@d$1CNT;UIR0&)}!$ z!4*-|A<+!O=R+Q-UIVP8&U+BrnR4dvoovf!F!GuX1>Q&~#H>Guq-u)|RUj>to$|BS#fz z1s+RTgxED2Sy4zxNZTl(<&l4Cdf^$Hw)DE{(6id9Et%#dC;{TB%=WRVsaj|(P#ysA zPkD^18p~e480XKi(LHOr*j4~oM_D&k7_!+af5pVF>vc|S8S5{+ry zC8uMFSJa@!J;m+wEi4K)cs{h0(%zVxn`_&hF9ywSvCWtOdQAY%ww8O6q1X7H91^Jq z$M}efCx?=WM8#mbbgt3g0fEJIXHLODz}Zaf+6t6Db2~LLIavVML0nSXt!!*mjg86A zUuC7G34t~g*XM$qCe!jP1}mSX+&tsa^u#DciCzAjex7}u!s=A;4pz>DygaueWv8_X z@4=-s!y+j_#mXu8sk^`_%c|+sQ5<6~QqFDWePOOntrTaaTaSwlH0w9UM1}d0x|-br zG0%fFWUc*6cqXbwU#Re)a`e=5^p3SBPw&_TngYJUg1JiWEN?pX;^a7mqN%Unb>V?g z+HIDAwQGs^N9+pclL^?B3q{ZPy;CS;u$+>%;Y@I#uO%oN?|K{Sl=yZ3LwOD=N5viH zDh}BQUVt|2-D2Lt$(~~FXIW2{Sc4f@e4FKz{1?w)hH3z5J0W6f?Ty>2y`Zg}tgN5V z=hrP07f$rH?;M=YHKJ@?Z&YF*1}v?acDn}R2f)#ZX?FS&lK!w~I>VkvlRevK>ewuqU^}FSOSog5c>R>xwvIu!7lDh`L+hn#(nT<&|Mn{)40VPWBw63jD-A@Og$K(T`DKb6yF zv`vYnQasCBzE=0`-HS^dmV^heU$Oh1S|+UkSLFKo`cc4G9_#Z20=!@{y@5m zooC-8YZZMYj|O%r*PQU)MOZ)Z=sQ5EaowJiY2%ZVsz4p}+f+FoohZ`;I0P!Jj6nfj z-4aii)(m4}`KA$F2^3c1!XM zU$n_6acvA;e6fT>D(hvf9PC@!?yx8}9>4nx|0L&qAZ~N?>@H2(6hBnd?P@!G=c#3E zUDvs=!B$3Zut%**XD-P~;sj8&cahyYV7}9w1R&+N^}Our?7ZT_SD2W{2eu55(2yyP ze|rA5mn8=iQh=d4Mv*x-ZGq#}E0?>(QMc0#WZoW&pI(yJoyhv4ncWyQ<@H%JyFKoc zl=|(Lim}rz?mWg06$gPGaE0lHIsg-msjsgGxiEZW<~nUYo_Eda?$+FQoH3v`dQ%WK zgo0zPLP774Lk8ssuPtVzr>8%7Wev1N^KAxup1f$}i3>iTw!>_LcwjI#EnaRS5PlDY znFkOdlPBIklkSZ$W(*v9#IMXvsa=j23Y?(XWdzM-H0WO^+}Y=vy#IpchH>)rT1gjn z@XdVaHT36nyqk*)y4-JX0fSoO-+ch}%}ojPmF4v}&9tPgKgy9oe;I!|JFx z#J;E>+ykPK+wzPir>0^Uin4ZgkRFq=ZGR33PAjgBYqD5W5@=B9Mqc!uwKE7pnXWg z>SkG}&lJzsBNrN#zKYxE&mVB-)6&wQXfcEq3y=G8$OZwT_FD?;LELYhosNvTDgn~3 z!$8Bxtc=CaHxt&+fkE&(lf4WX9l=Vzd%2~CGHZlufcb;m|3-a8lp6}f);?!vg8gTn zUNlqq%P3gfEllLw)w5CZ(~P_PEl7WMB_4cbwAeDg`LnT z=56%B4KBN-V;Bm!%s%hX1sj{mY~yM2i2Q$g ziYQv$3E7iLDa+(YS{{oaJQl@+a%?$gJIYjdw8ry3n_XM0nfLLb7fcxAYlXYK>eSYH zZZLi3Agv5k#wTEwiM!2oA9e40AOpmpf2`nJpliT(2b^#hX!7^5(i`*L3p7!d$NWg7 zDC>G&u%Ie6mpZ2?;Bkh;h2B#AWn84o-Am%M>r~&WTzL~pSdCihP`pG8wv9}h?!M8r zriTYsSe&^%{t?K>t?}M(Yon^KuP(ruFu+4< z;VaXn7QQOgIGqq?ul{;hw7CghQO(f+AH-j9iWKA6F#vDlryDe{Sb(f*I7?{R2gT4D zVL{e6r|{lo>=pvx{%{Yp?y^zTkaYDRqaR)qeDpdG8Dx0J4v~Y8 z>T*^Jgsi^JHfR$GugbJXbtEMx?0TUPIwUll%eaN_svcZ%_rS&m4<*2vH*&{QP)jK4 zx+6DPE4NMnkG!6aL*XsMt5SL3NTT=j4K(+O9xQ-V{9%OOPcI*G` zn{F5adhT66*ieUQ`diy?;U45=n*-zZtHz5Ii@dzkc#e!8+KZY&IeO`;<-+NM96bq& zp+mLs4Er-rnc0F=kRsQ^3^hGpMhM?A0Db8R3GDrSE(M7r0AMULMS7G`3>DqYc~o47g6iRx(hf-k_vt* z`W5%`mSJq%El$R^oSOw{83;1-4M$H^hQ{aMAzF3ra+f1cL4W75j5BTYez@^fu~x<> zcy!GxdgAa3yO7dzJ$g=x;N1q{ywOi^qHb=7aoCn}T6E`FQ1#t`fK2%!EjHS6i=#e4 z2TM^w@1J`~bzvIgbB4t{+;n&G8gcf6!=o-25Au#ZE*=yg!NWry&%5EfbvUbd5rnL4 zw!d+PQRe2UN4<3DD>c=F^P>pA-Q8LW8Hu*Rz;Bl$&iGAEh@@Y0-}DxjR048cGrVei zdbrdjtZL>L$F7-cVht6VHH{-H;+L0gxo&!=vxUV)553J?!`-x}vDExJAb~ziZ5Wp6 z2%B3BjL-t6F{EfAtBJ6_kSyml_7lu3fd%$n_$UmrQy|T&w!XjAP4_r9M=(klm1!Js zwi(xc{oI-s9wSve62YO9Cmpt9)?=6ke1A*?YfpG$zT@g*CTxw8Y1JuEacg#^dmBcr zY4Wa83B7vYT?X4Od!cQGl*`Tcpkf)x1(fi(zjlt$ukFK}Y|6K9oaVdZi|JIg46yD69+osgtg# zJ=5loM;iDE(?S|1Pb)oQ3bx^NbU!kS$79CNK6;1=ufiDx@N7@(XwAXe(2MIi3@J?G z0&i{I>*PB-FY8$7QyzwgSD8C;xqEv>%rDLlzspZy`)TRk`BvbJ@YK}pBfJ=xV2D)v z7#J$hnlkMOgjX!(yy26jCzXTzy|fqh)7u>B2Zp7{(L>APhgUrd;>Z!dD1HHp18guT z(CYZ*h6<3$700%3NW=~iN^UN4eR;5e*6U@tV#n0eGT5T7d)X!Yu|bIqqcu~Mm^qGV zt^`51>Ps#ewv&~;#_4WYIwMQV*#;xB?Quf>Rznf<)V({rt1r}uEHQn%WPrD#S31#%j*}*u|`eVfxUhwOBB2KKTZnfC8x3N)~mKFAPWAC z-LAdY(`)K#PIs?n*y_?0hfWJOEvH~VPDR&%5dKP938M>>-nk=4I{PAy9;1Z!e$(A+ z8M@kzFYD=$yRv*#i*P-ow=zg_yOK|NjIm9$k-p--1}k^FYS)-s3YO)&rnRlxX=%e= ztw)TQbD1Thl5gTmy2D3&I*Z2FbV9dWRxNk1x9c34@pF3Z6tNb2gZK#eQ-Y)I3rXG^ zKBc7W*Y?&VySyIg3XI`PR{Kd&oEMKOh(G7o_^qMuT({e^-Lsm~@}$Q{t5&8leBc_B z{Yb0BU3%e*$}7(1U9&$sX&FRfmFSFg>YD74Jrqxeuq4x>#Fuw%k^4nXvliV#Vfjvx zu^FG=23CvO-Kxt?ZA3LK5=AOn7JayLlZh|WysDYBb7`pp6^#L2)l0I{!1=bgX2q5C z>>jFKQ_Q)apv}fRhH0-Kv6~TjGN_1Z3LZ#@> zWH*+{DeLy!Kx%|e^?bh}+N(I8%>Y`7USJh!}Z6HGr9H7HiXNoZVMr#-m;*lq7fqs`PGdOf?2^v&6MEY~0LPh&np*kWx zy|hHo9jMQG4jq*7^C3P&dO|5uS!b%K+C^SM`OtcE^~r)%lUPG_6L6hHXD~eBaCwQQ zE~6*bbZTwOuq;KG?1l{}*cqrUwv(7_O`cH~OIqhcR94^$1!07%VsI0a0I{JesT>_0 zrMb3t*R)}&bdkJOA@px^BOK)ivG`Y$YyHDS)oN2u!vbc5@U}3|tBtzrb(phHTH>oO zxnh;ZnvRCmUTcyV%+5S!5#C^fX&)IG)F%^?YbddJQ+#o~->bs8^St4vSl^LLC222@ z$ws%5mt(^GC~dT?Qo97MEx`#UGS{O9LkAyTAb5$c6q`T?aM0(e!Pe$%^(xfNJogdW*+cvl&Q`6o3XlBJ>vj+`8v^U zEe*ZOG^3XcYAr;#7c&I!JNX$^^j^1LWvQNCuA-LA*td^V4tB+wzN!+a8C>FNQot?4d6|`d6DRWl@i=wQ-biDd^d&tZC80YX(<8IMRjC7l|p|8MN>W;%j8D z6L)>IUUNZ*_r7jjkSmTDiE=mP_k%%RvBg$>Cy?-!n3}380`uj1GZ236ZE_KPB-$-y zdU|T=X#PNJM@K=bH1mxu6FXzLx1#AHTFlKvH(M$wXr{IgMd5#yiV!{gq|#(td{0Bu z*r!JOwelRL>f`3(lm@A8h3PX_?!{XWb$H^RxGi)b9*qV^)Y`T4-AZk7c5xa0z$&7q zqtm7lx&JLNtb2NT3Wo5ipL=@b2ZZ*Dlr9gzrbr-1`L1Q>jT_x}er}^w^@?8-%W?Tz zUaHsDjI=;AMU{BV2=u9gp}{^*ONJf+v?k8p5-!7rPn{h0+hA%4kSyPR>kZ0b@&b+9 z?2N(d-H^rpzP2&iv=tYz$3}7stVj;jfk7uK@BnWNc)(c$^6Wtmu(Dw=U+4oO1P?el z{Y&uz^!IwO9yp{h&L1_dAxt1W@|=bIC;D>}#X~&kb^rtKpNX@ycf;IMdQe znpixzMF+h3CIsRsa3%(=fi@onFoA~xct{n46xZE>?`0TBQ!w-?g$bQDFHcX$b^7S& zSbR`@39UC;j#4a z-x|uXSzUVgr9V%#6JfO*9P(rCf7q=Q)|Qb;TU;FebSkL!o5&V{e3{-O5-hnH;DVpZ zF_)VfifaqC(b6I)M_P~DXf&B&!Q(mh@?t~Ap}9r7bYPPgI$O^aQA#0ePG%&+jM{D% zw9!+s$2{<8ip>^+2^RwgXdQ4Y&QqA{6v&IEm3A9M8t`g{8QWmLGSogt)NY&l1zg=7 zF}&v`_xsIVwX$s1gX^q^glkic7GKABj6@FVwE-`4MEO2BTmPEeJS3_$-7p%in}5Im zw_dk54H;ee4raiKnAJ0C;8Z7B0DO?mz^e*S2P2dNkZ*ecEAj(>0vT!G-v4-fV&Ynk zUhI;cm9;er`oE{a#sMx@aEW!KeSX z17h>LmDV#8xQ{=nY(yZ&ZZ|B&y0q#-suMCJ7AM;*fo~HG?r$I#4THff{8m0LmnUc=kU^y;hJ#PuZ?P(fn!ywjt4OgZFjgUm08^(sSlrn!+I@73=k^VNT<=cjyM;R38+?0D%F%a05KJHhn(JqV5}}xgCWrHY=;EPVcv{m^Zyr_L$TsM**kV zy$HikfOU8JSr(7VQ@F-{67^cLeYOn}Sxe@NXV*bq2y}1J>D%I+tHeoPr~EVV_#-vav(y2^)aOKRyqnx|<`CyQu0)#hM2B!{m`0i~R zm1o`nFhF#u>ZlVGd<9uSpMldpuXtFfl1>?!2$og=8yw~3&Fyhdk2 z1Fmen02rl6b&d!;OU2{rm}*_i*u;xVcP-;QMlN82QZq_rfglPOw`mnTu_1ulZ?#m> z!1jkaJY;bH!2sdn#ONa+pCQ@vp#lfC!x9d0cDnKfV@zi~~L-;56Lu zi@kaxEM7{u;SUQp@*ICIvqg;q%6*4f{Q8VrdIb1^>Y{rWk{~a({b*IhCExfU1zC`I zxNXaOsNDxeJAn$bhC@o?t;CnjJOLbuHC&c4FJ~UMC44g+FZm1;D zV--wr%OKOL>7*GWvh{f1P_SnGq0-sMkOwqKe(4Sfht~bH!Cy&*%RtzY2@rp9B-NF! z&P3BnX(b(RO_ZQZ#f*hy#X8_%eEzW!q%Q3hih}t@8q5N0(O~f*K9jQV{%zSZIa(TH zR4-5K_MUyjTMOMY2Z_dz?*ddwt=w|=O7k{gJLqn(G6(`fa(Euf(gdz`@IVaudfBq_ z{Cuqh6tV$W@Q{3HJ<|8vd~qWlk+gya z^=}LWMg3BBGBm*E{<`X4TJGgQp7K!wZvA~pJ3DgrLf*VtxHi$|{Q*tn3r#FF7`jGn z(GZtr0`cox%T%{TGMJule&53wAi$11?)d;=!|vU;jb86o8eAhnM1rA%VCBpa2uNS~ ztXT@UpZei3s}oRbmXP@H>!}8Vqxwk~pQz%+d1FDOV>D21<`aZxX{mzA2D7^2KnO>& zk|19VskHL{ubFF&YVt_KL8|Fl6>8O`tE_O=6tn^ADoOz*u$Hx<71~;as+g#CS&NVr zRKySxVQbIn*1E+Dmx7_t64nFdVJU%H*!gkRRkl5y zDzEP2c&fd$IVwiOteT#5e_H#n9E7|RhIi%N?@M8 zV!9`-J?QG$k(CsE_ba=cPmgwV*=B!?8Kv?%cK^F6VcUs%G>M^#7J5^J0a&lGx4TUB z!=|nflNQG8r+c;=-0}9v533~)V;Vs)5J|dM<3L)TBW>8qhgmBX8&w&ezy%s@!pFhf z1cA{{1C&V_~B{hAe)CA>?oUadat|Bw0MD*HWb zu?$g&4hWT+>d$}^j8?LzTxq zmNTcpAv`Mh6C^wGrG-ANGV5u>g>1G}c|bw>bNqDuXY2g$8_uC*?^O@eENf8?6nNvg zXjt>VIto*QEoW958r(k>$u4P=?*HD47N0Q1W!MUkjIh6_iO@L0Pr#g*^ZFz48@?=7 z)&TqFa^R270Az6%VkUb$G^{iDG1Hs3DsQNMV$TV`%ADmtOmK3~Tp}*rZG}D1a|j?R z9Qz(aZbR`tm*qvA>S2EWesNatzT<&KE;#Qp_|=Ma>Z}gtGKWu4@J@}|TNSk_Dw!8x zEagn>Z{0p1;NNf_M7fz0S98>gwW7d(Dyy<2bbnhq$L_)1Drt+U$Tfd%GebhDbSvOi zOPxIZS4`Rx(6lHleH>#q72=TOM(2o)*v_*WjgLcdP;rsy&f>5KF*}?7%&MF=pN-d; z=efZ($^%M2J!6niEuJ7-UE)NypZU(2`<>9;2{ZMe-0 z_EYKBdGo~CEbK#t;;lE8+Jt8t&n1qhbN$$-0N|=VNVKbH9Us?qG}rj(f^9e%n8z2V z?qkS32%~9p9 z4yIOiZ)w>XSK>|3KF?cSW-|@&09KQ2{B>d^ftga@ySo_S38vgL?n%S4UI?G7P;g;L zFd&^*Yz*RMB0F&7hUDANF_zhdg7?%e9o9>YSW+JHp=-I(JtyuT)9F3Kn7Fn4*dGPI zA%_BAm_}1yCoo?Z=wPjDp$GA>4jzn@p6=cYxUPPBg|G#K#_H zqIpn?7l=sJLpfNtb^G=l%nPBg8J;o5?_w)vQ?H1(*lXc+ybCAu8z%mU^-)~BKxuAP zW@?A>v^BMB`-?V3a9P490N7bMHzxCEU3trC+~)r{M~VPZ&J_{E#oFdQ$AW}DMem8d z5*OTJ5}07R@1O^h>I&dG<9WNY^BkVtyvz{6G;3m(Bl!xMye5rY{g)?iRi5tl^CK5H zG?dIi1H{Qz3BUUJlf;b;mrPJuaAOs5FwR1@U86s>whm zYsxbF@2@LD!cob!F6(+mhar<}yyieAT9`;3HAk|uXBS{?5O2z_ITjYNy=fNgJ|a;ol3UmvRdu*jWXmh%RshdJMQ!d-Q3a~?dv;a!`y)Ks{6W)+V~9Loyd zsZN`_d)#r2{pW(xsx-Ma9eYm25)u=zpF$6_#N!D;aPyWKvu$N}Lq#&)9(Jwnb`QB}rBF`|pn#v7x^j!e(5qN*>`Vzi-0$oW50 z^||!F4pm2J{n9CtF*7;FcCV!BONV~ZFftGOGO~=Z-55odF@3(u+mS7~W8ty3-9EoI S=!i^7&H4U;@8|zXnD}o3hzZO9 diff --git a/splashscreen/splash_halt.png b/splashscreen/splash_halt.png deleted file mode 100644 index dcf9d8be0de9cc11079c61ef6e57c5d52f9cab15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22304 zcmc$`2UwF?*ESllpeW#sC{h$lfI%rL0@58BOQ;ULgMxrm1(6a$bQF0lfClN1$k2u$ zARs{qNmLY!lqeWl2tf%TB?JN_goNbmIPdwd^MCI-@ArMzxxVX<7~- zYv=w&`}49g$}$iLL>6}8H%AC$6Zp6hvULmi)zY$C7W~?B+2;Ij5V7RXGeSisxU%iq z1&TMV88w996vlqhv)jlBJ@N& zwAWi5=z&908(I$>dG_qUmffviY&PprhxZHmaNNPp#pRb3)e((2+;D&Y@US1PFB@CE z;vBl0sX++Y{p+>^Qa^u^k-7WZ)}7HC&uGL9#faP)MbC#CH1j&qHe)M^=mZoYIEd9q z4D0R^wGQxl_o}FD2P0b;>@V2{exC+^A&{*<-Zx0z5B&HjnK9(nkB>Wlyh};m{~sSu z|G4_^p8J1q;{W5h|Fr9WdG6nJ{V(JEG5UXL;s8YQ`j6wh_2cTlH1Y5H`;SdP{#}3n zovEJwF_wSV^}mes-*x>T$NAry>VY3)`HxNfpPA~v%=$kS(f{03|I@DjMMS56NbH)|n z$R=L&o%uuTu0?DYzh?^v+rlzqW`8Lc@ z-6JQ^4)w&IacwkV%2?@^Wa!+V1nPV~)H0Jf6oFB(iFQIQp^^@f|C*Ena(F$utf|z$ zL+}(0wd;Oy%Alb8QCeE}P5txg{6JLB09ufYV!`BeFqVy*Ahj1bPO$ydHJ~rIvine~ zpSU9zP+|Hoquzw&E@*08e6k&?+n!#y`UFbythqmn5++93gd0g)=Y_0cVcdY;X;Rp;#k9-AIV;v1c zHK1C}$tf`1*gcTvQjo{Cqvp#an@4M1G8M%4uUE%RoDX}C>?}a3;%fVSrjs-YPneC{ zTcc{xrK^m*>DY10XN67nQ>e3(f0d+vyxy@dXQRB?vBQV^X8dErZ>E}I<}V5dB5ZaK zN9bfAYrL1h0@y*0RSuN5Y$shD{ie``w=ywnI_Wa-ts_50?o~@Hf>$v!{VCEiXX)GL zaKpZVft(nMxlvSNUjZk;k{e(wS{+~dUgESLEgpwumnnZ+>~LCL!#l1>UBLQoOf}gq zSz&Wy3$l&k_eS{(9OVlC(OA!29BJ5m@{awpSlhy15ya=VRCBz_e!HpS9Zk)JikPoo zzs`*`>kC*-e!d)34l_kB>C(M>_qc|}{)fp!6XF4AbL<1X0p+)`3sSzbk{%ErW);83 zQjVPcd15Zmrh=hGjl&0IsENO8t`zK4NOwr$|r z?EZl3VL4aVt|O7va{fP`zE!#B2yKcV%P5^ze1~%m==00MdhzXGk;yyM*t3py&x{zm zRByuLJIi3ck3%PU=TS*og87fK87d_uC07j#JQ_n?P=PBm)amJI7!rvT!|$@`it|`H6O($8MV!awp;#68y{+e>BbkT&Q`+gdxZB?J1UfuKSeNf z)#j``tE5`THtT)(>AdO_m8jO^v;EaJC7&-uv1{_zpK#!>^vFoNfTdKbjCh}?%4rDX z*w^(Cjh;R0*$HwGUv%jGm)W14eLlxtDxMQZ@h>WUZmRbFnJ%onI^GKT=ZLG7I~-BU71X%rBodTfua#d!L)fMPrL0 zOJ9wZ80$!Fa2{ot!|YGx*_$PM*b6n2E-)HKV`>e+ z(gh~47I9F;ob^A3hApX^5*W4S0~ZXG#**SA+T|@y?7ygBUSVKLicjwsH9r>ODhH$cVAw{oCq5)_$ zfrwbYhPndlSLcUSZ+%f<`3kaYMH666Bdn*!92tpn=>9rOG<3pck3(^*#m13hv~xhOgG2OX)ZtFij*1pIBFxxmAZuz^ z$06DuYuZVG;ev#Pa&S0HGn=h)G{dMOzmljT2aC48%C6{7*MS*69miWxe?v5N|1Qwg zVetr1hbTO;Hn(kQZS4_eT8wkHib!X_T_GT^(t@@bpL3$G6wSP1-}xA;@7cpohZdM5 z(e*#F@Af(A{50(Lpo^l>oFs4Qmzu@GrN=m7v&@GxzN%Mh)W8$5pQ6q;?-w})B`XT< za+Ypb^M@i=G=@=3=?PE#@m-p!g=y-*$cPzz{P@epql)SY)>rT7z=)nQyeCj4B_(pQ zfR&?2_x~l$cQS=HP)#}C{EzfQ`BP9ey|1T@Ry6pPP)oPB{~$EiDQv@NZ$8&4KnZ`- zfvjdiktXjEr(P(ib%wt0tbH1QPRm3I&tP|}rx&~(uyo{(>t!a@J&YLn<-LbKmCj>4 zN6a_EMhh0r{aX0RRz)Kx_6Hu6hCz^r0dNrp-y49TG6>hjI(|_@)z=q z+-7>XY5}wNXYE46_iW?Fr1i6v^QBFyjxspS3YqY1hlbO>dCY%s7E6DY>H30#B6FGf zKSNZF-m^`Qxg1zlgNd}ryIQ{VtPh#zynnBRoLXOXj(axscKgT1z7zROl&&vBIy;7H z5_PnqnLbhGgZ9QbVc6p@p?)?ThNhM%bH;uhJuJ)}ChmJekJ-NiYFw*;)wJWRTU93B zv!!0IoOFHli_6%J*9yc6J+czaBAfY9*IQc9xR3pD7~XTIlejK|zDIs!)2|cGD5ssv z?+%(L@J4}@$iw`oPRd6@rN)L$667sAbgZ(4n_S6?iP;TlC9=}i*5qpGI;1DqxVCK# zgYA8t1*=UrFCo!Ip*pK-=&w9X!OZ;Z=f=y&BHmBlcqxB9cbapl`plHMllEJUrCpVY z8=lYgHqu*Shbw8kjIPfHyh+?2!h4+0I^BfAHo{fXIZyp=bA6YcyqAO|F*@=1qu4=A zKUaK&>a$?3l-q6~pNLLhK1-`VG?SI?1@!4_STyC6#2ai&eHa(+;J(ImqT zlipuM{aT-~vj0G>))WG+NV|Mh}(!?Zn!q%_U+pvH)#<=bphuqAY+BjZ-P+51ir@x z$+AcI*&1vcIXJPnVWK<8C^$PgF=3Z)-0!J>MBtJyqrQnboOa=iZE};~#m{$Jja=f^ zv(;guL)25_`}7AZEVa&FFj4r2+NjNog;ppjm#Nt~?o!#ZTVCgn*~yYj1rxsq1cF#F; z3$esiTbSV-cSf=IsD7On?;;ALmC_IBu>LqrKE1w(i`Izhen&nO9AKAvGubAGR)T;J z1PNuN9lGYxst@09i+Ddntqj77S&q;9;TOzM(<}W-u-)^jZg|7wgVYlxet+#2S7TD` zrdx;4(*3R^9m|Pkwbsuq`M_641&*8Zs~lzDS9+nC?0Qp3QRR9kC3e<~kr|r%*7PI0 zMJK}YXhCOPMN^ZJ7cQLqUeT{m#|u~56zARF>z1sy&jq*G)71^lmbk1PPac{o)O5sM zrKLSmyZkAUuvRd52fq^{4Apu${7@`!7h|eo{h8Qob;%?X5h^xaE}lcbhhs&>bA1=F z_*4h)*I{K%3Tze_wa?(Rdr@dVpR2wDN$5n9Xtiv&3gytxveJRy;@OlYbKjP&jEusk zGd=NDtH_9!Chc)iWg-L$Kq4;iCVkEib3Z0?BnS9S0~K{ec&C&ntPKn&r|OHxRF2le zqbbtXa9`YjUwYcPHGv=otnt(vX*FA<_-^5M!bGASN}Lti>?q;i`g%vz`8G;OO1ne)g+ZTJpUOqVTVe0F27Qas->N_P zb|~*u;kc9jFCwp+?ssUF;GmhK>b4VWMCdp>L=7E!qB%08JMVM7IX+m-?q4y_*?+;{ zT_8<0LM*SJ+}t`n<6uAz^wFmlEffU5AVf^WtA)Tt$iQ!^2lNTt7 zs+MTN;P=GUGm-_3NOGs6tk(r>mV$_k(FLr*YuoLUEvfp~ZI@N>%brnPtMimFN4uQ^ zc2)K8d&2&Lg^Zs1g_e`!_&POIsO)@YqK}4sKkuvau9WUCYLpk>r^~s|CP3h7)EObd zI9vTbgTzyc-gCDM@2|Bph)JS1`-El~HJTF-(J`lEbP)$!#tamRMMJ5sdJc{6F4HTV zWYu#k@hG7^EvB=#s996j-XQhu(+6T|m0K`~D~dGMO%G9jezvhvqfZ!%#7P9N9~+W7 zWie3vS8|WGUxno^yx8wCA%j;`!(Dl=_F>g{OVGDTXa;WGJg;ZpTkiF>*%N~MQ#VWV zH(e{9|3&RFo&Lm2*UsS5NO*YHyU3-g6NK3LS-IH-Z+LBH%!%tAt#fWNbZ?KsJ>E-2@y3lCS-Zprj@=&D zys_k;kS1^p^e2gUOHFn^u5z;L8R#7-ewA0_{=Vn+lZXuD%RVd!O&#zwY>SAMk<)dkZ{)5%cFyeW zZttX>x!YYC)WUEpWTZ$TPR!~bcP^~C;~0CVR*(S&wpYBxsk_H7?y^bk;Bgl>Xmg~4 z-zNqGLnIQD!~zCI)@bChNF=gv5Q(F2N>`BbvC`l(_P^ zLcammN7X$eH!hL>RG2HN)Tk6ha?Q4{JD=3QUcFk0Yje`S-dq=kzwx}y;}!mPMNrZU z(T7nP^i}svdZuc*g1F=6Vq&u;nWV{I9FCbP&nNkp4{MeS&a}&4aql{JqA85*H<~iL z%&!b0)y_^@_~m2IccVD3G+ii}1wpR}Hr&;FFKhJ%{E&$G)}@{iq!`c&(=Z3hU4gTn zwL#Pw$CaMdSC)1XuxXCIj$-_^n^mEaFu#MbQ?L8o;^$040wyAd+j+vse0$LF=JnM_ zY-=;r{77RstMAN8WSCm$bua8hPs=65HU-blx|Ir<-&>US`V8)Yyqq7Sl!jQE?aDdY z8lGOmZeF0<&Pg%s{Mc^|hf@#8-n@#}iF<1JmxE*C%#J35Li4*xKp8w5g6wKqX0Xd# z?#+CbWu+@`)tygIa6@I3dRAV-TC&Y2f|*>@4<3nk}WA6Fk0~sxP?CdARs0(t$err^>y~SnhMqtK-rsOUQE1$;E$g;?H97 zt4O0e5riXT4h}MIlbOW2^l-tu#%8x|cUGFu;5k8Q0mCLPmGmf^k+AZo_-ff>bfo;B zLG5}GCiW$tKeWlaRr%OE3N@+j;$0ub@-TyuU=xxe+|lmwYMAKh20)9Jd*1cAxE+ED z-G7VGy{tJOhPkr-(Olt;G_%eixN{e6KLc~WZ5!8Mz42}HgtQNlJL>5h{M=jKt0ifN zms83`OFwvI`G(Vi6-0uDpLNvqAu|jirgc41Xx0=b7S|eY)gcaWty)iK-@AdF zxRbI9PrR7=M@zu~bK}xAgx~NUNTJIE;H~KkDOf2q7c6^&+`1roL%6|7!K}&_{yj!Vq%eAD0 zq|>MYsBx4s4H-eBeBzxDT+z&1)jtX7z_yqL6Pn2;c?a9Ld&lNZn3)ysvOjfD!sp$Q zx5y)vgIY%x3mXXvOq-ezrBLNaywc0hWj7nV+ZAFy_dl_@l& zyqVpRGyAG8bvCKLy}eyxJf~v#~PqyLR5}M&S;pSTEd1ki7S^u&n9PLLUKq6k1?#Y^Ul#RXWk&pEfJGWZk@690+DF!kyV^0$PRD^(i z>|fVnM%89lH}+uA%(4kSS=)j0QEtQQB;$tG(PH47$6}SnYHg#Vwn4atk%CFWrfqY0 zU2Be4BX3)9b_^j%p3$c)<0SvHZr@YetY#o>Gzd!cV~`rUu-G17;uKZMas#a>@6=QO z8r32u#zaAEQ~_4}8&u7nx(;7gcpz49SXHU7wawv#uB?|oQp+K>c>8rZ zt+!@`$7FaCAn4V1nn8hq?>rA&M_yBQ+jG3TeoxpNOR$L+-#OceyBWXcZHIse;l+jZ zV3cfQ$5AKQjo+CIP(8nAQqw7Udo6_LQJAiGvBasi@{SP5g8S^yLah>G7xRm)1#_Iq z;b*h*7+-ZVjI1hyzDMcxP{PZ5D9mv4A)cGm-kx{<<1Y}x+(^o5nT{Z{H33zN2xw<$5l>KeDo(bCXxN`h z98+zz7dYNIoR@mVbVW+Shikj$;LMY+cokcE9J}U`pl?1PXUlnjo3hAc!nY3wsnGUY z9u$a5UmngIEV#@MSXi?#+J(Q%t5}-Z(^d3U&hq?uKn9pKvldHW`}1=)e)(GzTYa9) z*k84&s1Y4?N^7hoC6N5lT((j~)VB`DSeEYvUhFR?vMsjA)N^%*&YN$kVcR&a+_-v` zJ%h1TReo_6a%`#{H3E3TzR58J-3fqf7QtcXaMAy2UiRiMfB7-Es|HGz#$#ziOVOe9 z<(H4xB2vJ9Klq7R+J4|>S-&CrKCTXfM_y?$dReSTmPREVA!~M$D!SXQM_e!%IBRp5 z8h9&~mANrli+V(6bk2~oCvG(w*j83Ljt^0d#0=uO@rEx@PNSbho563q8{aF zCb;m$i!fhr!HEB4T*6EHU#*Pht$ENP=S&nB0o(n3f`(q zHkuS1m?b~}e|*BwaI$M7fZ07GXO%1sxn-5}XabHkYhg(dP<cv~xRv^)YHEq(N zomjM=@fIYvXEd>4oIgDxm*i1qq_!n#hX5775AP=4CC6q9Vy#hro@29P`Vkp!8vF@x zlh!_|TYO@AP1ou{X$Lz_F|?x}jo06`apz>edfq7oX3mLZmwS1uZI9SmC-a$@J)G0$ z&z-9erDC6ZHd=4}u?E)y^5S!r_bHL~2y;$c-y&?jc|LVOIBi>~dJUVbL$0;uG*54W z%sQ>){{=sb!W4Z?-iHbe5^hvnHCY{iG9uyg^gN&M9C2`x-X8*eu{jJEETpfi!$$K$ zqu(YTZ=u)zk+5@LocZC%ajyPnl6DA&iwfJg^ZnKO%+93Jj*jsCB=KoPaNVf#w8V ze-1r1SR5g58=c(lu*G;cAk&{)!G&k{1Qo8oZxEWrjF0bouml1F`BRtkX=_$1maK)z%30>8aO!Z`1t1&Seq5(7>S4+la-ZrL8j0Zg@JL@%3ieU<25~!JhdKEB56(gCUQjw$j7&P zlsx@o?(QSML+o2nww@r~MXM*Wc6VfI>CF3UH?Q)zEOi^#8H03->xPIAmFmdbSAF1Kj zuTLwd-8=e&=Bm|&85j?9a8s7}*Mb!<7`kYt#-E;SjpxbcL~dEJxE6CEL``w z_<$_J;YhDDM1Kfuv5@&)Fm9M&1W zV9}YaO>4Pghn+YOtRfPIVby<*n(tlgnp_jPq6&u5c&$u%*Lp&V*q5&UekmK?2h-jj0>w4xVlp+5yQ7yI_601FsVK>g#l6JITIipE)WLtA#oIP)ST$ly*W9{4n(EM;BLG!J&V;TYT zVAR=4Y3<|jl~QFmquPUqae2_7@7Ue&;?JAmchrx)(xs|yaHG__vu~Io%0A(dduSt; zRI?o`3zMHc(Cn;&Y7S-o`}{kDh*u!=`Y*R^DrS^mM7NTKFiot+&_LyzyBe z&XVL5>)+h(iwZ@jwKc%cybeN1JLz~OT)`S^&9i!E`;o!j%Z2tf4h{~I(t=6{#F0C9 z?tpMRDPtDI-b?4@fxBeZvk{VZareDyh=0c+TGQ=%zcej{oieTPyWdKo zVwe<^whe~}MP}XKwQ5IIf+aVwnj2vvAAL|o2^<1j8ID~@(r7!|s4WGv*(fu7egPo4nI@U`@jQI9uo0?OkRf#qq`rp$&(Q~(1KH$+uvS3T zgpalw`-wO?4bc-H3$M2;DS?n_aB%QZhJ=QNwM46~u+q}g%ZI{mMikJ8M{Q{Ya9zbH zvdfLMMun1xf-yyHa;DlKd*2XB>Ni;VWF>#4JKvyr3Jve2(F)F$JZb1LIhv{({h`%2 zKr-!TUi&X_%Aw-IMe_~W(1bAltD`P%q7~S=%w-LaJmz<(Ls1}p7S*aBbCT~zxFBdZ zB0lkoY*wcv_BU|8R9G0KswKxKCMHg{UI^PPpW~Z&)i7fC>B{UtaCo?Om236KPoF-$ zw7R8klg%tn-TyJoXcWY|#MbX;^@d&iDW!w+v$K-4T+C9pQE=Nm*@U4^UtHB`G@0ue zLA=tLZMHggC*kcb^yA$}T?40jiuytuvZv>))&(Gbt-r|{9*OSM8G3a+02fKmudAyw z<9s-5Jo~(%H{>MviDo`IKc84M?dv4rl_Ci%{btLbtnl+|8R_XkG+abNo66|piO!tu z8z8xL?Y3+Mh?(n%q?+i`B^?;Y6efxbvXDOA8J8)HM-@z6J}+2X<1Dnv2ltiR@rMV9 z*=Z_9<=#n)?}u7q!vN!~ zZ)liZTwDx%AZ)ZZ|ruPB0nS5ss+;JFK(?2Xkcif#`3!p&dyP|SHFnL!PCK@H8bxm<+3C&E)OO|i^ z3PoZR=h&d=su1Mvb-}eHpU*1Gx97>+=r}b{_@W#3`II z)9g@<>AL%()S~sz{kR=Fc9eqM2WoFXE`BKXIry+^9%lrE$mIq}x?XHoX^5n^_;lR( z^s6-M_~{UkpWM6mgQP$$ab?D5s`+!sqp&5i1U11vEqdvW(M}qoxg!q(!~!690OJ1m z4^l-%@QC|Fzt801472DFpHU?Rt%?fe0Wk+k8EG3Z$Q;QI?YZRu&HH?RgtjRW$Urh< zNw;Rgg|=NX?3;k~lAuUlFgg$HkVilY6CblYaN$F*@I6j>uWBv&TdCcom81%(3YW3{ z3Ct(sEg4aRFAkpH7we1`3#WqloC%O#AZALoy}bGI#Y8xq7jFh+1Dt2$xfg95z#pAT z-JcjDDPxi7lJZ{+LZr{(%-#Mg_=%#oD0|wR^WLUm{>wi5POXYU)EzmKkTb`A*Bhgy zLcVOg%k?i85df#EpU9J`AQ}w5%|(%_YhEyS4OmIe7k1R4M*1+?>w-Nz(8X(=wIb8fQk?xI5y)# zV`6t3Z2p3Q(d!5pj>3!|WvSToJXVoF)u_hzRA7=5 z&z(QNbVp6-Kk(^xzv#Ii$zpb()&Xo?a6JZK&14OJ{^LDamHHdgy;^Es>y2JUL5CFbDI$fCRy3hw8KGeTkBn46Wmv)0HOZO!1$_i^njy^D8RA%}aD5zu)fEl~i`W8Vm z)2Y7y_=W`IY-XZt>H$_>1wBW2X^=tjRvfFt8IOpw3Cms^+T%(0%}mC<=Z14Dy;4L; zIJb2Z;_A1DDG-S5Ivb?{Dx83g3G7JU*F1x*itaWTn9IKv(Xx38`201^llk7UR2Pu$ z?kH6BE|Mwh@8~VFiQ8=lV6mv_8>vrp+Q{lw|Kn|t!CmGM$leMA!(`TQBfdpQDZdz* z0vYg$^C61Y*%<{25#{>h4vnWmt7)Ukn9Kt>z`!Fx5q@C-6pRNngI!50)o`RX!q4N0`- zV^a%CSxW`T8^GLrIGhm(nrIfxiT>1r+MW|-s4e$|ZtmG=!qV;%t1msK$g1e5&X z8UR}fj6qlY`pv-st6Mg@%}_nWv`x(N=ksjO(4Qp4bjIgz$qtz-p#4CJ-vUf-Wb;J! z2*BRIF}I-aEh%$!bQEmGNr?d|iW|*qpjem!nD}Si>PjlMR!?G|P>}#4Q=!(qHR<|N(xQRcu>wcK7zz~nR&rTjwk@T*OG7=XUMfLo1zo*B&h9@T0 zCoD~dgFXNGQEF7T`~shXB#uu3d()FnVSr*$ndFc@E%!c^AK`t#^Hl~gz`BIx-tgg< zS2G9@fMQeYk>b%VYU1=lJk^uS`SYRf$Is{0iX_8M-FMR+@FkPsE3%UQyPOtDk7sEc zA37Y}>W#k{VIk&Irrzyx=#rQbV37c1c(NSXP#(!V5^$ zWNK<^41Xdg7}z+l=iEQgL1`D|$opi}oNaUfst)Slz!CHe7Ear7QenyFWP<*x@XU~< z%juJuh_w_b588ZVKX=Ip1qz7`GLu9L(S#@+c9qD2e7lTbq}$KfSItlanj9xd*gbcz zJ0vlyPtNbpE6K2E84tV-><)-2$dW4nUcx5+7UUh^>V`9jh~r&rZpDHUNGlMk}0#(*bBqX&mr1ogOeM=ms9vk-z=V$2)(lOwv^yUgOpgCy|evh(HjU z7BW9U*>=&6D0y{{Oy)Dr$VaFflpjyya&0&?So)DSZyDKBqnV7usE3^cVp~*> zx(8+^lGg)`x7 z#2Gnmb7i7MQmMjyk|TFXEiTy| zkK~W;vQ`l#H>2|>4#Sd7$RH(9u}Y6FthM6^p>faznDL~a9Vd8VZM`~rUs8>?73G)O zm_(F=ribV7QdSv4tWU;&3?u51C;6)z&@)F=fzo&o5@S(JVC0UeLj2VN2GD~jeGC@Pj|Hsyv}%~>Pla_w4N#=0Svs>tR2p44_4E&2g*vf9 zfl(2{?XY_&Vf5998QJ4}_iZM=9yq=Tim^867p_8SHlKxm)~^THY(3#>v0rQRT=NxV zx&tSstXuSA(+;=B#?MhX{@=d!qHUaHd8^a)wG=H3zI@Y9?4t}G5*2=AikV}5Q25gE zE>edaXB~gdZAjc=q`~ioPUXDicfyEn560!QYZL6Y{Vbl6GcVc>T&b=$@t^6;WzonFgm{^i8RnFUznp{s3w8_XX#Hpdm`AAD| znK7d*il55^@zXOr^~(7XUsst=NWHUt2P^0QXqwy~Z-e!frg?U|J?MDy^Ue`xsat)S zLY}j^vLTdz8Wi+qWFImq3klD@ygCjOsZ;4o0#p(%sT<|^y(oXiesLXEqqljjtPwGY z0{$BY^M3R=kT|U6OHmZf~98XxEgVd>VN@=X;p z2RZT+eCbXL2AawI`H_z+ZmHqnVrt9hkkZ;(J;qvpQ}o+ynxz#L9Wqi97jSYeCk~)x z{MhXgP&xb%F+@T;$DMY1@Yfs14~;GDZ0!`jdIYjye~tO5s|ASw^XbJk<&isL{*Nc04XmM~@gc}Zs%D;lNbWCSeR?cGwG8zdx z#e7F^l9o%8{mFRiwWbfCt z;V)c5_0qz-VP5&m@#KjxoL#R)+Hf6PyVlrMAd=7FTD-!giK4Yx9XC$XW}|-D@S6k6 zjE7?_`Lpspd%wmjQrXXdGd#IATWh2S0nyhj<7zBCky9OoI0}Ls!5PJoQ8^@h-iBID z>WgUm{PUiZG^yLgoMzWL_yw%7^f^cRv^X(B1wc$ec=)^1H{~7T5m?hcOGjez)da$A z&#&|&J-x2sye~5CYxm=QwdR2C-nS(ReM@j@=TdQ@K|G)Dr88@msG0e-U7-Sf&#>8I zj<^^XAzP;GdEM)3tx;)yPI0WN`M%*0ZE}H=tk3Fi*smK)8rQ=aQ=c7G#gSOFLX!r6 z$&YovdNM)cxS4Tt(xT*PbL`_hBs^=PVC7VWh0R9duoYt_pRO3u#7snFV?X`x(s zzQT(uXLaWC!ZEzc;yg*fKe=(I6lCr&`=G&w*Tgd5u=40}encLDt<#PduTPZt&dGm~ zDOz`;*C9@l^~zhUMD5N2C0_esv2iO!Wn=4kpq#SBW~~*fXB(@z^4!^{E=q@%7>(5x z2Im|~xEfJlLwkE`-I1Q=mle8$cd%?#5Q(khIUJ!0BNONom6OV+j#Kvvi*W&Xb87CI zV!5)S*r*JWbd37=u9Z{TLCd;oLU#WHQX*|78!_U^6|mI5#Cu`C$}nuHE266t441Op zQO9&~rMmyslub4t8A77tbM!@-p^3&%CFa^gdM=bl4K}8#?!+1rj>4L1iZ#o~rWECc zqFU7(|7=M{J6Ic7o`x5Xx`m~xN6>1Kb`Gqi>hW+EZN@ofvza=z6z4qqQE#v&Skn?LeYJQTWf!OFPUQxzkpa?GsVf2Gb)U2|~1U%tr5`ne+w3 z5MlVuWIc(kn=pfeIVFU`{hk{Q6prl(?(I@NoZyl(r>XCN#wqTg_`H<>O46oa!K zo`| z@d0TCUck~oBpx?-fzH4SbRc1~Brgz40d$qTNrIIB?c;y`-2cymr!S(W`!+#NgK{`= z7<=?GQ+K;K0~r()9EY1fQLS@B(eu-wRGGW|ABq?69>}eJIPvN3y{+DV-QVjFVsOxV zXMpX+=Ev85z4$Ff`L27LUEiidJD~^BpY|Mk{(Ko?F10&xq^PJUkC7r)n)XX~xrP@c zs^6Ut42t7)1>HpRczg>+A^{CJT_^~O5*(84tEkouL$;O9C%#KW^Lp8(ikklYI-O3> z%gv3a(MD&u(CL}ADU66rCbvaOxYzkt7KpQ} zU1wjAkw9sJDCi=<#A^`qsv;)3d z6AZOouk~1lr6^u*zgez?C&u4oeH$6;0%y(T&*E?w!iS^@Kq4` zOUQN+i_86;3x-*k#32tghPeSQ%jp+|XyIZ<9NLfIOOepx5A}$rsG$b16X1NFv|7?J zz`U5xiCC~CfpL>(^$uCtD}Zc9@;m(`a5p#Hcof`V*XU^%7Z*2meInWzBU-NbL6A*Z ziWATYlX>94ih@iElugHOgp7$18VQIz>D>EhFocpBK6iPU2}1J^fZ@IL_J)F;5Tp(Y zI(6~dfX+SjC%X|a2T7}KYRP}gd8i@S0Tnnu(#-xoMWhLuSPYUSIM*7LfRW@e#@o}T z=jZJkhPuGvTkA4M&8^pNgcuf7Ivtfd6u*C{ICXcI{deuEscKny z`3mPFS0pJER^vcDoHy@$WcN=$He9aqu!_JyIZYg2DYi8_dGaa9KeTc_9&KLd(w4qG z)GPPa1&?}wn?cLMsF$AAAjXm~tSM&>zQ4R^={rNQ>@G0UlQ8i65zC(edBLQ*`86K; z(R#c%Eh7V*laQPe1w6Ci0ru_C#{8o-uMWZFyneb^>HHjgLkU2DQBzioFf(xR+k4}w z!k7~$PX_vrO0#xvkYpwRJBk5G3qXZQwgP;7?9H8?MX?&zwF>am9uhQeJ9Eoi>W3;H z?zb3bfb>piBanN{M3&nm%0{=YN~|EWfeYXU^du@Fivhp5N89~zSS`WO$Hzx2%i7~* z$dfmDmk*Amaksws=g4XIkw80FSL65Sdgp?8g`6%rf1kU51Fb2_p^EwuoQf&{bQJJ^ z+yHDz8ZP_amhkI6l@oFE-Wy{SDqX9J`t&1PrptRC+#-TwrW+-q)b|klL;UXDZ?4sz zS^r$BYw6;XpL~B>09mA|+tT|l)VbRhU%cSpknu)RlW;2!=t!)H9&&PS#xe~6f`qh` zNC3oH;05wsp2vR-q`bkkDhpsqnN3c)yLLG>w9H*w;=IP8#U}?wTNj@?*~6N>d)m`f z`l!?_5HvrvE>n=%d}q@w2sqbpg<}blP+>LA8f|TDTLQOuf&5W$V@FHutb{WLiAFG8 z$!JPk1VRb=0BrzX$}kht_7bV~+mA&*^*~b$v^>uenJfVteTtbR8L(vw&>`x?TAOVTBBeX*vWrkqi=Rn}5k^2#{y)A6zyABairQ1=!iJ=w6s+bDYUXJT}WRED750(*Q) zlA1)D!+Ys;olTGfKnDfK`D!XEonvFqVuT5PR<9GLigGaPbHPK+F~K11nB`a*nDMvz z*J_F-k(NXg?z|NQjkYH6B{@<8oHq%`#BM+F+5li2weCA@gq$)_klg@rN_cB&Y@Fv= zoeh501-t^`lBHX>dN>@H{|u10JG!}068!+`taF}@2Z;9fB8P-EdMW`SU|p(A1}1wqpGImh=fT5ENnpqI`K$> zVZ=u!vve;6=DkIOS1&$mc(`JzxHkseGF!Gu zx+w7zgov5UKybwIpL@`>1EW+)IDZ=T+^b1f64Y3ip{lk>R{YwsgQ%mULmw#;cA?Ep zgA1>p3+8Opr-RHUzq`*R%O;Dto~ZT#)L%ay*`P^+&^fFyIc< zxhJ{tqWnyvuvgU&8s*9;{m7dk*p4F2edu9XF8)RIcn!~vOE5T^`eg$p>IF~P{ zdTIe@dK>HxU=zWPJL=|r{j4t7A91_oM&-eFN?&b5z5zBRTH;JfvMpkfpaBrqz@%vL zy$ia7WKzIk(Dt7!ld*)H4WMP=fM%yAI{q?nKqcAd)`hp*!34y6q&%x#!M&1Q|K`mb zkSmo;0fB;dzk7Gr z=8&Z1ybsR7K!HI7jVAyeNnWrpBJwvscFg~qy#A?8sybDnK>WV(UsK`~j{1r%UIkP3 z>zxFuaBN*u908JsfY?5E`t|Qs>%@NF&&xqo8^BHRr4>KwmsGPdk+-H5Hmt3!)q^?A z(eXwSA8F?pVkcOhV|?jc4UmzS)L(#Ys3w_OHt$!UIR1%Yh6NVOQu>CQR8L)d)=+%a z&ku8Z18`W&E5NRcZk`h+`?sH%md;i7zOj1@0Su8Wz!>lYk*E@Qfsb9P_&9d5Ta(&- zuv$!D(YB~S%6}?=NWE5Qh+~f?Efp}j-llACh++^WF(4?=h!ibmAepI_!b@`dOrFXo zjcw$AbR(jGm?hG0o~^-0fB#hMTt!V%KYw1lGLNV=8g!DgZ)*@9zL6plFH{S2Z5mAs`;iGj!{=eZ zt(KG%NWM@bZshuTU6PP95 zT_vikiL}nT5f>+^0Re7h0!UlLOclieH8Y2yfb&s74V{pHG>C^eC2IdyJ69Xi)ER{l z6o1rcqKW)b&<)WUq%kB&$ApEWM9@Lq$Z5hKG5cPGYNL$wcrm5KL+>QR9(o?OOS z2vbAy#<0*}3Izm&Xt3cdWvEQaLy=1idcxjzv=G$>C0@I9J(F~6=n_Q~lm{@6dV6a# zFaE|krm79<(iF!?Z&b6xumDp0vVTk&tkwI)tdqE6^~k9>lnEF-K4ft6(!h}g2PvoJ zTZ_AQuzSm2Hrfp`eavzSi380bcEr#Cn6<*czyv1|=?tPOx5@VTiphA9d}x=;(gr9m zH>sZn93d7JEH@mCNJ0$i@bx_}-R>QD0hv%oY(=8b?E6;A@_Fr-idtM-EL=8`CBGw_ zi2`H2rkaqw$|P7C5Hn|nhUIyry*wr3=`0wYn{f z?>?*5N;}zg7_M@peQ_`51VD}q@(LF4`~A;jj=Qg6i<-*lIbUvaD3^9-1n~1xM3yx^& zE4}u*WNA*i_h)VBNP+d~qu)~{fNoz|f$N^CId5l^&8>Qkvi&E+u>CBSoSRs(goK0= zyF@pb*3abtb!dS!U_C+nT|lx1Rw^>IfiGT;lV;XmN`g}LKqS3|t?*f|0>bjv$ z%+c4Ds!5|;s~)?INEcmiu%R#o-s`fSi26*|RbW;rrKe2f9bDjbl|K1l>ZdXLj5)B!iAu3t$n`A$0qq3VLE)asY7i_De!FwaAGhC>y}_ z{^q}dcp4`Ew>g`bnZnmZVEgyG^9DoR4SmAE2tN1}P8~tx!}Y(-S;WkI&m1LAd*wU{ zpV_h5bP@V*I6V(X__U$UtvO%9!%*~;vgX#^DZPauJRC*OtMG6X{n11s=$bjrA5G*R cwGPx# From 3b22622054fa2b6155010feb9f7b1445b0d2cf43 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Thu, 4 Jul 2024 22:47:21 +0200 Subject: [PATCH 078/418] fixes `checks` badge in README.md (#3494) old url: ![grafik](https://github.com/MagicMirrorOrg/MagicMirror/assets/25914086/025597f2-c1f1-4879-a76c-5a20c7b7099e) new url: ![grafik](https://github.com/MagicMirrorOrg/MagicMirror/assets/25914086/f3b8850e-3fe4-4cb0-aa07-7525eb8f82eb) --- CHANGELOG.md | 2 ++ README.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f62d40b3cd..fb98a5d489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ _This release is scheduled to be released on 2024-10-01._ ### Fixed +- Fixed `checks` badge in README.md + ## [2.28.0] - 2024-07-01 Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @WallysWellies. diff --git a/README.md b/README.md index 0221b79f40..9734cccef7 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ License GitHub Actions - Build Status + Build Status From 4d14f4a2c17abec72b493d067ee2032b64bbaa2a Mon Sep 17 00:00:00 2001 From: jargordon <50050429+jargordon@users.noreply.github.com> Date: Sun, 7 Jul 2024 22:36:59 +0100 Subject: [PATCH 079/418] Fixes the UK Met Office Datahub provider (#3499) Fixes #3384 Changed the UKMetOfficeDataHub provider to the new API structure as per the documentation. API Base URL updated. Header information amended to the correct key name. API Secret no longer required so removed. Changelog updated to reflect the change. --- CHANGELOG.md | 1 + .../default/weather/providers/ukmetofficedatahub.js | 13 +++++-------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb98a5d489..dfe3202c0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ _This release is scheduled to be released on 2024-10-01._ ### Fixed - Fixed `checks` badge in README.md +- [weather] Fixed issue with the UK Met Office provider following a change in their API paths and header info. ## [2.28.0] - 2024-07-01 diff --git a/modules/default/weather/providers/ukmetofficedatahub.js b/modules/default/weather/providers/ukmetofficedatahub.js index 1ca4da5c01..33e33c50c6 100644 --- a/modules/default/weather/providers/ukmetofficedatahub.js +++ b/modules/default/weather/providers/ukmetofficedatahub.js @@ -11,9 +11,8 @@ * This provider requires longitude/latitude coordinates, rather than a location ID (as with the previous Met Office provider) * Provide the following in your config.js file: * weatherProvider: "ukmetofficedatahub", - * apiBase: "https://api-metoffice.apiconnect.ibmcloud.com/metoffice/production/v0/forecasts/point/", + * apiBase: "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/", * apiKey: "[YOUR API KEY]", - * apiSecret: "[YOUR API SECRET]", * lat: [LATITUDE (DECIMAL)], * lon: [LONGITUDE (DECIMAL)] * @@ -38,14 +37,13 @@ WeatherProvider.register("ukmetofficedatahub", { // Set the default config properties that is specific to this provider defaults: { - apiBase: "https://api-metoffice.apiconnect.ibmcloud.com/metoffice/production/v0/forecasts/point/", + apiBase: "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/", apiKey: "", - apiSecret: "", lat: 0, lon: 0 }, - // Build URL with query strings according to DataHub API (https://metoffice.apiconnect.ibmcloud.com/metoffice/production/api) + // Build URL with query strings according to DataHub API (https://datahub.metoffice.gov.uk/docs/f/category/site-specific/type/site-specific/api-documentation#get-/point/hourly) getUrl (forecastType) { let queryStrings = "?"; queryStrings += `latitude=${this.config.lat}`; @@ -58,12 +56,11 @@ WeatherProvider.register("ukmetofficedatahub", { // Build the list of headers for the request // For DataHub requests, the API key/secret are sent in the headers rather than as query strings. - // Headers defined according to Data Hub API (https://metoffice.apiconnect.ibmcloud.com/metoffice/production/api) + // Headers defined according to Data Hub API (https://datahub.metoffice.gov.uk/docs/f/category/site-specific/type/site-specific/api-documentation#get-/point/hourly) getHeaders () { return { accept: "application/json", - "x-ibm-client-id": this.config.apiKey, - "x-ibm-client-secret": this.config.apiSecret + apikey: this.config.apiKey }; }, From 974a1da9f0ab265237a5e967914e9ae818c5478b Mon Sep 17 00:00:00 2001 From: Daniel <32464403+dkallen78@users.noreply.github.com> Date: Thu, 11 Jul 2024 05:37:44 -0600 Subject: [PATCH 080/418] [weather] update provider openweathermap to new apiVersion (#3496) Co-authored-by: Karsten Hassel --- CHANGELOG.md | 2 ++ modules/default/weather/providers/openweathermap.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfe3202c0a..39b2d7e6e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ _This release is scheduled to be released on 2024-10-01._ ### Updated +- [weather] Updated `apiVersion` default from 2.5 to 3.0 + ### Fixed - Fixed `checks` badge in README.md diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index 0999c83f0a..11504bb521 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -11,7 +11,7 @@ WeatherProvider.register("openweathermap", { // Set the default config properties that is specific to this provider defaults: { - apiVersion: "2.5", + apiVersion: "3.0", apiBase: "https://api.openweathermap.org/data/", weatherEndpoint: "", // can be "onecall", "forecast" or "weather" (for current) locationID: false, From d9665b35df989bfb73f23a37f3ae26af67152362 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Mon, 15 Jul 2024 12:51:05 -0500 Subject: [PATCH 081/418] Update compliments with support for cron type date/time for selections, addition to just date. (#3481) > - What does the pull request accomplish? Use a list if needed. this change allows uses to configure date/time events for compliments.. also linked site that will build the cron entry.. and example was Happy hour in a pub, on fri/sat between 5 and 7 pm. or just after midnight on Halloween (Boooooo!) I also added testcases for #3478 (and added support for this in MMM-Config), with a custom, drop down selection list of the types.. ) | if this is approved I will update the module doc --- CHANGELOG.md | 1 + modules/default/compliments/compliments.js | 100 +++++++++++++++--- .../compliments/compliments_cron_entry.js | 18 ++++ .../compliments/compliments_e2e_cron_entry.js | 18 ++++ tests/e2e/modules/compliments_spec.js | 11 ++ tests/electron/modules/compliments_spec.js | 36 +++++++ vendor/package-lock.json | 9 ++ vendor/package.json | 1 + vendor/vendor.js | 3 +- 9 files changed, 180 insertions(+), 17 deletions(-) create mode 100644 tests/configs/modules/compliments/compliments_cron_entry.js create mode 100644 tests/configs/modules/compliments/compliments_e2e_cron_entry.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 39b2d7e6e9..67b593ac6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @W ### Added +- [compliments] Added support for cron type date/time format entries.. mm hh DD MM dow (minutes/hours/days/months and day of week) see https://crontab.cronhub.io for construction - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar - [compliments] Added `specialDayUnique` config option, defaults to `false` (#3465) - [weather] Provider weathergov: Use `precipitationLast3Hours` if `precipitationLastHour` is `null` (#3124) diff --git a/modules/default/compliments/compliments.js b/modules/default/compliments/compliments.js index c249f9915f..4c4bef471f 100644 --- a/modules/default/compliments/compliments.js +++ b/modules/default/compliments/compliments.js @@ -1,3 +1,5 @@ +/* global Cron */ + Module.register("compliments", { // Module config defaults. defaults: { @@ -21,10 +23,12 @@ Module.register("compliments", { lastIndexUsed: -1, // Set currentweather from module currentWeatherType: "", - + cron_regex: /^(((\d+,)+\d+|((\d+|[*])[/]\d+|((JAN|FEB|APR|MA[RY]|JU[LN]|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|APR|MA[RY]|JU[LN]|AUG|SEP|OCT|NOV|DEC))?))|(\d+-\d+)|\d+(-\d+)?[/]\d+(-\d+)?|\d+|[*]|(MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?) ?){5}$/i, + date_regex: "[1-9.][0-9.][0-9.]{2}-([0][1-9]|[1][0-2])-([1-2][0-9]|[0][1-9]|[3][0-1])", + pre_defined_types: ["anytime", "morning", "afternoon", "evening"], // Define required scripts. getScripts () { - return ["moment.js"]; + return ["croner.js", "moment.js"]; }, // Define start sequence. @@ -38,11 +42,45 @@ Module.register("compliments", { this.config.compliments = JSON.parse(response); this.updateDom(); } + let minute_sync_delay = 1; + // loop thru all the configured when events + for (let m of Object.keys(this.config.compliments)) { + // if it is a cron entry + if (this.isCronEntry(m)) { + // we need to synch our interval cycle to the minute + minute_sync_delay = (60 - (moment().second())) * 1000; + break; + } + } + // Schedule update timer. sync to the minute start (if needed), so minute based events happen on the minute start + setTimeout(() => { + setInterval(() => { + this.updateDom(this.config.fadeSpeed); + }, this.config.updateInterval); + }, + minute_sync_delay); + }, + + // check to see if this entry could be a cron entry wich contains spaces + isCronEntry (entry) { + return entry.includes(" "); + }, - // Schedule update timer. - setInterval(() => { - this.updateDom(this.config.fadeSpeed); - }, this.config.updateInterval); + /** + * @param {string} cronExpression The cron expression. See https://croner.56k.guru/usage/pattern/ + * @param {Date} [timestamp] The timestamp to check. Defaults to the current time. + * @returns {number} The number of seconds until the next cron run. + */ + getSecondsUntilNextCronRun (cronExpression, timestamp = new Date()) { + // Required for seconds precision + const adjustedTimestamp = new Date(timestamp.getTime() - 1000); + + // https://www.npmjs.com/package/croner + const cronJob = new Cron(cronExpression); + const nextRunTime = cronJob.nextRun(adjustedTimestamp); + + const secondsDelta = (nextRunTime - adjustedTimestamp) / 1000; + return secondsDelta; }, /** @@ -75,8 +113,9 @@ Module.register("compliments", { * @returns {string[]} array with compliments for the time of the day. */ complimentArray () { - const hour = moment().hour(); - const date = moment().format("YYYY-MM-DD"); + const now = moment(); + const hour = now.hour(); + const date = now.format("YYYY-MM-DD"); let compliments = []; // Add time of day compliments @@ -91,20 +130,49 @@ Module.register("compliments", { // Add compliments based on weather if (this.currentWeatherType in this.config.compliments) { Array.prototype.push.apply(compliments, this.config.compliments[this.currentWeatherType]); + // if the predefine list doesn't include it (yet) + if (!this.pre_defined_types.includes(this.currentWeatherType)) { + // add it + this.pre_defined_types.push(this.currentWeatherType); + } } // Add compliments for anytime Array.prototype.push.apply(compliments, this.config.compliments.anytime); - // Add compliments for special days - for (let entry in this.config.compliments) { - if (new RegExp(entry).test(date)) { - // Only display compliments configured for the day if specialDayUnique is set to true - if (this.config.specialDayUnique) { - compliments.length = 0; - } - Array.prototype.push.apply(compliments, this.config.compliments[entry]); + // get the list of just date entry keys + let temp_list = Object.keys(this.config.compliments).filter((k) => { + if (this.pre_defined_types.includes(k)) return false; + else return true; + }); + + let date_compliments = []; + // Add compliments for special day/times + for (let entry of temp_list) { + // check if this could be a cron type entry + if (this.isCronEntry(entry)) { + // make sure the regex is valid + if (new RegExp(this.cron_regex).test(entry)) { + // check if we are in the time range for the cron entry + if (this.getSecondsUntilNextCronRun(entry, now.set("seconds", 0).toDate()) <= 1) { + // if so, use its notice entries + Array.prototype.push.apply(date_compliments, this.config.compliments[entry]); + } + } else Log.error(`compliments cron syntax invalid=${JSON.stringify(entry)}`); + } else if (new RegExp(entry).test(date)) { + Array.prototype.push.apply(date_compliments, this.config.compliments[entry]); + } + } + + // if we found any date compliments + if (date_compliments.length) { + // and the special flag is true + if (this.config.specialDayUnique) { + // clear the non-date compliments if any + compliments.length = 0; } + // put the date based compliments on the list + Array.prototype.push.apply(compliments, date_compliments); } return compliments; diff --git a/tests/configs/modules/compliments/compliments_cron_entry.js b/tests/configs/modules/compliments/compliments_cron_entry.js new file mode 100644 index 0000000000..59a6659293 --- /dev/null +++ b/tests/configs/modules/compliments/compliments_cron_entry.js @@ -0,0 +1,18 @@ +let config = { + modules: [ + { + module: "compliments", + position: "middle_center", + config: { + specialDayUnique: true, + compliments: { + anytime: ["just a test"], + "00-10 16-19 * * fri": ["just pub time"] + } + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { module.exports = config; } diff --git a/tests/configs/modules/compliments/compliments_e2e_cron_entry.js b/tests/configs/modules/compliments/compliments_e2e_cron_entry.js new file mode 100644 index 0000000000..a4d1c5d8f2 --- /dev/null +++ b/tests/configs/modules/compliments/compliments_e2e_cron_entry.js @@ -0,0 +1,18 @@ +let config = { + modules: [ + { + module: "compliments", + position: "middle_center", + config: { + specialDayUnique: true, + compliments: { + anytime: ["just a test"], + "* * * * *": ["anytime cron"] + } + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { module.exports = config; } diff --git a/tests/e2e/modules/compliments_spec.js b/tests/e2e/modules/compliments_spec.js index 95b342577e..7763dc689b 100644 --- a/tests/e2e/modules/compliments_spec.js +++ b/tests/e2e/modules/compliments_spec.js @@ -77,5 +77,16 @@ describe("Compliments module", () => { await expect(doTest(["Special day message"])).resolves.toBe(true); }); }); + + describe("cron type key", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_e2e_cron_entry.js"); + await helpers.getDocument(); + }); + + it("compliments array contains only special value", async () => { + await expect(doTest(["anytime cron"])).resolves.toBe(true); + }); + }); }); }); diff --git a/tests/electron/modules/compliments_spec.js b/tests/electron/modules/compliments_spec.js index b4c4ed845b..ac162fd9ce 100644 --- a/tests/electron/modules/compliments_spec.js +++ b/tests/electron/modules/compliments_spec.js @@ -43,5 +43,41 @@ describe("Compliments module", () => { await expect(doTest(["Happy new year!"])).resolves.toBe(true); }); }); + + describe("Test only custom date events shown with new property", () => { + it("shows 'Special day message' on May 6", async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_specialDayUnique_true.js", "06 May 2022 10:00:00 GMT"); + await expect(doTest(["Special day message"])).resolves.toBe(true); + }); + }); + + describe("Test all date events shown without neww property", () => { + it("shows 'any message' on May 6", async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_specialDayUnique_false.js", "06 May 2022 10:00:00 GMT"); + await expect(doTest(["Special day message", "Typical message 1", "Typical message 2", "Typical message 3"])).resolves.toBe(true); + }); + }); + + describe("Test only custom cron date event shown with new property", () => { + it("shows 'any message' on May 6", async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_cron_entry.js", "06 May 2022 17:03:00 GMT"); + await expect(doTest(["just pub time"])).resolves.toBe(true); + }); + }); + + describe("Test any event shows after time window", () => { + it("shows 'any message' on May 6", async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_cron_entry.js", "06 May 2022 17:11:00 GMT"); + await expect(doTest(["just a test"])).resolves.toBe(true); + }); + }); + + describe("Test any event shows different day", () => { + it("shows 'any message' on May 5", async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_cron_entry.js", "05 May 2022 17:00:00 GMT"); + await expect(doTest(["just a test"])).resolves.toBe(true); + }); + }); + }); }); diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 2df570b22a..058dae08df 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.5.2", "animate.css": "^4.1.1", + "croner": "^8.0.2", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", @@ -50,6 +51,14 @@ "node": ">= 6" } }, + "node_modules/croner": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/croner/-/croner-8.0.2.tgz", + "integrity": "sha512-HgSdlSUX8mIgDTTiQpWUP4qY4IFRMsduPCYdca34Pelt8MVdxdaDOzreFtCscA6R+cRZd7UbD1CD3uyx6J3X1A==", + "engines": { + "node": ">=18.0" + } + }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", diff --git a/vendor/package.json b/vendor/package.json index efaa4f151e..e61f8bf380 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -13,6 +13,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.5.2", "animate.css": "^4.1.1", + "croner": "^8.0.2", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", diff --git a/vendor/vendor.js b/vendor/vendor.js index b2d912d4de..ee3f0bb777 100644 --- a/vendor/vendor.js +++ b/vendor/vendor.js @@ -5,7 +5,8 @@ const vendor = { "weather-icons-wind.css": "node_modules/weathericons/css/weather-icons-wind.css", "font-awesome.css": "css/font-awesome.css", "nunjucks.js": "node_modules/nunjucks/browser/nunjucks.min.js", - "suncalc.js": "node_modules/suncalc/suncalc.js" + "suncalc.js": "node_modules/suncalc/suncalc.js", + "croner.js": "node_modules/croner/dist/croner.umd.min.js" }; if (typeof module !== "undefined") { From d22d0e1f875481c3bcfd8f4c236dea832ea98c4d Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 29 Jul 2024 12:22:59 +0200 Subject: [PATCH 082/418] remove raspberry object from systeminformation (#3507) fixes #3505 --- CHANGELOG.md | 3 ++- js/utils.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67b593ac6e..a1c404d460 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,8 @@ _This release is scheduled to be released on 2024-10-01._ ### Removed -- [core] removed installer only files, (#3492) +- [core] removed installer only files (#3492) +- [core] removed raspberry object from systeminformation (#3505) ### Updated diff --git a/js/utils.js b/js/utils.js index 89784f6937..6e4b7eabef 100644 --- a/js/utils.js +++ b/js/utils.js @@ -14,7 +14,7 @@ module.exports = { versions: "kernel, node, npm, pm2" }); let systemDataString = "System information:"; - systemDataString += `\n### SYSTEM: manufacturer: ${staticData["system"]["manufacturer"]}; model: ${staticData["system"]["model"]}; raspberry: ${staticData["system"]["raspberry"]}; virtual: ${staticData["system"]["virtual"]}`; + systemDataString += `\n### SYSTEM: manufacturer: ${staticData["system"]["manufacturer"]}; model: ${staticData["system"]["model"]}; virtual: ${staticData["system"]["virtual"]}`; systemDataString += `\n### OS: platform: ${staticData["osInfo"]["platform"]}; distro: ${staticData["osInfo"]["distro"]}; release: ${staticData["osInfo"]["release"]}; arch: ${staticData["osInfo"]["arch"]}; kernel: ${staticData["versions"]["kernel"]}`; systemDataString += `\n### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData["versions"]["node"]}; installed node: ${installedNodeVersion}; npm: ${staticData["versions"]["npm"]}; pm2: ${staticData["versions"]["pm2"]}`; systemDataString += `\n### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}`; From 4182c2129f0386967e02d9ea13eb3099836636e1 Mon Sep 17 00:00:00 2001 From: Veeck Date: Thu, 1 Aug 2024 19:00:36 +0200 Subject: [PATCH 083/418] Update dependencies (#3515) its the start of the month so dependabot is waking up :-) --- CHANGELOG.md | 1 + package-lock.json | 529 +++++++++++++++------------------------ package.json | 28 +-- vendor/package-lock.json | 17 +- vendor/package.json | 4 +- 5 files changed, 233 insertions(+), 346 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1c404d460..8e9f38814a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ _This release is scheduled to be released on 2024-10-01._ ### Updated - [weather] Updated `apiVersion` default from 2.5 to 3.0 +- [core] Updated dependencies ### Fixed diff --git a/package-lock.json b/package-lock.json index c30419db67..dfa0d6d8ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "ajv": "^8.16.0", - "ansis": "^3.2.0", + "ajv": "^8.17.1", + "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", @@ -24,35 +24,35 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.18.0", - "pm2": "^5.4.1", + "pm2": "^5.4.2", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.22.11" + "systeminformation": "^5.23.2" }, "devDependencies": { "@stylistic/eslint-plugin": "^1.8.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.5.0", - "eslint-plugin-package-json": "^0.15.0", - "eslint-plugin-unicorn": "^54.0.0", + "eslint-plugin-jsdoc": "^48.10.2", + "eslint-plugin-package-json": "^0.15.2", + "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", - "husky": "^9.0.11", + "husky": "^9.1.4", "jest": "^29.7.0", - "jsdom": "^24.1.0", + "jsdom": "^24.1.1", "lint-staged": "^15.2.7", - "playwright": "^1.45.0", - "prettier": "^3.3.2", + "playwright": "^1.45.3", + "prettier": "^3.3.3", "sinon": "^18.0.0", - "stylelint": "^16.6.1", + "stylelint": "^16.8.1", "stylelint-config-standard": "^36.0.1", - "stylelint-prettier": "^5.0.0" + "stylelint-prettier": "^5.0.2" }, "engines": { "node": ">=20" }, "optionalDependencies": { - "electron": "^31.1.0" + "electron": "^31.3.1" } }, "node_modules/@ampproject/remapping": { @@ -713,9 +713,9 @@ "license": "MIT" }, "node_modules/@csstools/css-parser-algorithms": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.3.tgz", - "integrity": "sha512-xI/tL2zxzEbESvnSxwFgwvy5HS00oCXxL4MLs6HUiDcYfwowsoQaABKxUElp1ARITrINzBnsECOc1q0eg2GOrA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz", + "integrity": "sha512-2SJS42gxmACHgikc1WGesXLIT8d/q2l0UFM7TaEeIzdFCE/FPMtTiizcPGGJtlPo2xuQzY09OhrLTzRxqJqwGw==", "dev": true, "funding": [ { @@ -727,18 +727,17 @@ "url": "https://opencollective.com/csstools" } ], - "license": "MIT", "engines": { "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^2.3.1" + "@csstools/css-tokenizer": "^2.4.1" } }, "node_modules/@csstools/css-tokenizer": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.3.1.tgz", - "integrity": "sha512-iMNHTyxLbBlWIfGtabT157LH9DUx9X8+Y3oymFEuMj8HNc+rpE3dPFGFgHjpKfjeFDjLjYIAIhXPGvS2lKxL9g==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.4.1.tgz", + "integrity": "sha512-eQ9DIktFJBhGjioABJRtUucoWR2mwllurfnM8LuNGAqX3ViZXaUchqk+1s7jjtkFiT9ySdACsFEA3etErkALUg==", "dev": true, "funding": [ { @@ -750,15 +749,14 @@ "url": "https://opencollective.com/csstools" } ], - "license": "MIT", "engines": { "node": "^14 || ^16 || >=18" } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.11.tgz", - "integrity": "sha512-uox5MVhvNHqitPP+SynrB1o8oPxPMt2JLgp5ghJOWf54WGQ5OKu47efne49r1SWqs3wRP8xSWjnO9MBKxhB1dA==", + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.13.tgz", + "integrity": "sha512-XaHr+16KRU9Gf8XLi3q8kDlI18d5vzKSKCY510Vrtc9iNR0NJzbY9hhTmwhzYZj/ZwGL4VmB3TA9hJW0Um2qFA==", "dev": true, "funding": [ { @@ -770,13 +768,12 @@ "url": "https://opencollective.com/csstools" } ], - "license": "MIT", "engines": { "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.6.3", - "@csstools/css-tokenizer": "^2.3.1" + "@csstools/css-parser-algorithms": "^2.7.1", + "@csstools/css-tokenizer": "^2.4.1" } }, "node_modules/@csstools/selector-specificity": { @@ -846,37 +843,19 @@ } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz", - "integrity": "sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", + "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==", "dev": true, - "license": "MIT", "dependencies": { - "@types/eslint": "^8.56.5", - "@types/estree": "^1.0.5", - "@typescript-eslint/types": "^7.2.0", "comment-parser": "1.4.1", - "esquery": "^1.5.0", + "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.0.0" }, "engines": { "node": ">=16" } }, - "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1559,7 +1538,6 @@ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -1662,10 +1640,9 @@ "license": "ISC" }, "node_modules/@pm2/io": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.0.tgz", - "integrity": "sha512-sKUEgZoQ5/jRwTyMB1I7u2wXL6dG0j/F/M4ANJ7dJCApfW8nWC0RElMW2siEKvZ79iplIPAaWV27oyBoerEflw==", - "license": "Apache-2", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.1.tgz", + "integrity": "sha512-KiA+shC6sULQAr9mGZ1pg+6KVW9MF8NpG99x26Lf/082/Qy8qsTCtnJy+HQReW1A9Rdf0C/404cz0RZGZro+IA==", "dependencies": { "async": "~2.6.1", "debug": "~4.3.1", @@ -1684,7 +1661,6 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "license": "MIT", "dependencies": { "lodash": "^4.17.14" } @@ -1692,14 +1668,12 @@ "node_modules/@pm2/io/node_modules/eventemitter2": { "version": "6.4.9", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", - "license": "MIT" + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" }, "node_modules/@pm2/io/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -1711,7 +1685,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1725,8 +1698,7 @@ "node_modules/@pm2/io/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/@pm2/js-api": { "version": "0.8.0", @@ -2389,15 +2361,14 @@ } }, "node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "license": "MIT", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dependencies": { "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -2482,10 +2453,9 @@ } }, "node_modules/ansis": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.2.0.tgz", - "integrity": "sha512-Yk3BkHH9U7oPyCN3gL5Tc7CpahG/+UFv/6UG03C311Vy9lzRmA5uoxDTpU9CO3rGHL6KzJz/pdDeXZCZ5Mu/Sg==", - "license": "ISC", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.3.2.tgz", + "integrity": "sha512-cFthbBlt+Oi0i9Pv/j6YdVWJh54CtjGACaMPCIrEV4Ha7HWsIjXDwseYV79TIL0B4+KfSwD5S70PeQDkPUd1rA==", "engines": { "node": ">=15" } @@ -3519,7 +3489,6 @@ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 12.0.0" } @@ -3835,10 +3804,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "license": "MIT", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dependencies": { "ms": "2.1.2" }, @@ -4136,11 +4104,10 @@ "license": "MIT" }, "node_modules/electron": { - "version": "31.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.1.0.tgz", - "integrity": "sha512-TBOwqLxSxnx6+pH6GMri7R3JPH2AkuGJHfWZS0p1HsmN+Qr1T9b0IRJnnehSd/3NZAmAre4ft9Ljec7zjyKFJA==", + "version": "31.3.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.3.1.tgz", + "integrity": "sha512-9fiuWlRhBfygtcT+auRd/WdBK/f8LZZcrpx0RjpXhH2DPTP/PfnkC4JB1PW55qCbGbh4wAgkYbf4ExIag8oGCA==", "hasInstallScript": true, - "license": "MIT", "optional": true, "dependencies": { "@electron/get": "^2.0.0", @@ -4401,8 +4368,7 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -4734,22 +4700,22 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.5.0.tgz", - "integrity": "sha512-ukXPNpGby3KjCveCizIS8t1EbuJEHYEu/tBg8GCbn/YbHcXwphyvYCdvRZ/oMRfTscGSSzfsWoZ+ZkAP0/6YMQ==", + "version": "48.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.10.2.tgz", + "integrity": "sha512-xTkf/MmEeVrTbezc6kDqCJmK9RcseIKo8X4oyoDCMvV4LY8dqrQi8kmfRrv9n0gNBkCclevaOh2Lkmu6Fs8SLg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.43.1", + "@es-joy/jsdoccomment": "~0.46.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", - "debug": "^4.3.4", + "debug": "^4.3.5", "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "parse-imports": "^2.1.0", - "semver": "^7.6.2", + "espree": "^10.1.0", + "esquery": "^1.6.0", + "parse-imports": "^2.1.1", + "semver": "^7.6.3", "spdx-expression-parse": "^4.0.0", - "synckit": "^0.9.0" + "synckit": "^0.9.1" }, "engines": { "node": ">=18" @@ -4758,16 +4724,44 @@ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-plugin-package-json": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.0.tgz", - "integrity": "sha512-XPPehRGjoN2YPnwH/Vo9GTBTTSoJ9uveqKr7tCDskgKwXjtAfMIw4NyGvmTq4GLlnl+cw0VeKTC75863f2DBFw==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.2.tgz", + "integrity": "sha512-mls5O8zT3Sjl/lLmhT8xtNkLpj7b3uP6wwK9rgg9rtmAbPjlzkunCySlHQgEcB6ZUV+Qi3QabLaSub2IWr2VmA==", "dev": true, - "license": "MIT", "dependencies": { "detect-indent": "6.1.0", "detect-newline": "3.1.0", - "package-json-validator": "^0.6.3", + "package-json-validator": "^0.6.5", "semver": "^7.5.4", "sort-object-keys": "^1.1.3", "sort-package-json": "^1.57.0", @@ -4782,19 +4776,18 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "54.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-54.0.0.tgz", - "integrity": "sha512-XxYLRiYtAWiAjPv6z4JREby1TAE2byBC7wlh0V4vWDCpccOSU1KovWV//jqPXF6bq3WKxqX9rdjoRQ1EhdmNdQ==", + "version": "55.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", + "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.24.5", "@eslint-community/eslint-utils": "^4.4.0", - "@eslint/eslintrc": "^3.0.2", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.37.0", "esquery": "^1.5.0", + "globals": "^15.7.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", @@ -4815,95 +4808,11 @@ "eslint": ">=8.56.0" } }, - "node_modules/eslint-plugin-unicorn/node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/eslint-plugin-unicorn/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -4911,26 +4820,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-unicorn/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-unicorn/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -5034,10 +4923,9 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "license": "BSD-3-Clause", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dependencies": { "estraverse": "^5.1.0" }, @@ -5333,6 +5221,11 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -6266,13 +6159,12 @@ } }, "node_modules/husky": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", - "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "version": "9.1.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.4.tgz", + "integrity": "sha512-bho94YyReb4JV7LYWRWxZ/xr6TtOTt8cMfmQ39MQYJ7f/YE268s3GdghGwi+y4zAeqewE5zYLvuhV0M0ijsDEA==", "dev": true, - "license": "MIT", "bin": { - "husky": "bin.mjs" + "husky": "bin.js" }, "engines": { "node": ">=18" @@ -7543,17 +7435,15 @@ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12.0.0" } }, "node_modules/jsdom": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz", - "integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==", + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz", + "integrity": "sha512-5O1wWV99Jhq4DV7rCLIoZ/UIhyQeDR7wHVyZAHAshbrvZsLs+Xzz7gtwnlJTJDjleiTKh54F4dXrX70vJQTyJQ==", "dev": true, - "license": "MIT", "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", @@ -7561,11 +7451,11 @@ "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.4", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.10", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.4", @@ -7574,7 +7464,7 @@ "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.17.0", + "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "engines": { @@ -7589,6 +7479,27 @@ } } }, + "node_modules/jsdom/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", @@ -7714,11 +7625,10 @@ } }, "node_modules/known-css-properties": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.31.0.tgz", - "integrity": "sha512-sBPIUGTNF0czz0mwGGUoKKJC8Q7On1GPbCSFPfyEsfHb2DyBG0Y4QtV+EVWpINSaiGKZblDNuF5AezxSgOhesQ==", - "dev": true, - "license": "MIT" + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", + "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", + "dev": true }, "node_modules/lazy": { "version": "1.0.11", @@ -8410,8 +8320,7 @@ "node_modules/module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", - "license": "MIT" + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, "node_modules/moment": { "version": "2.30.1", @@ -8668,11 +8577,10 @@ "license": "MIT" }, "node_modules/nwsapi": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz", - "integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==", - "dev": true, - "license": "MIT" + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "dev": true }, "node_modules/object-assign": { "version": "4.1.1", @@ -8816,7 +8724,6 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", "dev": true, - "license": "MIT/X11", "dependencies": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" @@ -8826,15 +8733,13 @@ "version": "0.0.10", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/optimist/node_modules/wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -8939,9 +8844,9 @@ } }, "node_modules/package-json-validator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.4.tgz", - "integrity": "sha512-sp5bWr5eUoVgNV50vsJyil0XCluM+qMvtba8X4ug5Z/0YtYZsePka+tZgqiZnAyFyf5pwXaSDwYncFdSEzX7PA==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.5.tgz", + "integrity": "sha512-fEG8kM+EfX0j7TbTWAv6/0NRkid0fUHm2afJx35en3+IlrJ6dRQfKUCpuUl/bGM6MvQ0MxAlpaXkJtYVMp0F4A==", "dev": true, "dependencies": { "optimist": "~0.6.0" @@ -8969,11 +8874,10 @@ } }, "node_modules/parse-imports": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.1.0.tgz", - "integrity": "sha512-JQWgmK2o4w8leUkZeZPatWdAny6vXGU/3siIUvMF6J2rDCud9aTt8h/px9oZJ6U3EcfhngBJ635uPFI0q0VAeA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.1.1.tgz", + "integrity": "sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA==", "dev": true, - "license": "Apache 2.0", "dependencies": { "es-module-lexer": "^1.5.3", "slashes": "^3.0.12" @@ -9226,13 +9130,12 @@ } }, "node_modules/playwright": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.0.tgz", - "integrity": "sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA==", + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.3.tgz", + "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.45.0" + "playwright-core": "1.45.3" }, "bin": { "playwright": "cli.js" @@ -9245,11 +9148,10 @@ } }, "node_modules/playwright-core": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.0.tgz", - "integrity": "sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ==", + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.3.tgz", + "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", "dev": true, - "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -9283,13 +9185,12 @@ } }, "node_modules/pm2": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.1.tgz", - "integrity": "sha512-y9ndADjy78XfzdbVHISn4WiUTrcvmsO7ieCtM/oC80rwPgBDg+bHkkz1e4eaLOW5a7sJsnDfQjJe4AqxNnIw5Q==", - "license": "AGPL-3.0", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.2.tgz", + "integrity": "sha512-ynVpBwZampRH3YWLwRepZpQ7X3MvpwLIaqIdFEeBYEhaXbHmEx2KqOdxGV4T54wvKBhH3LixvU1j1bK4/sq7Tw==", "dependencies": { "@pm2/agent": "~2.0.0", - "@pm2/io": "~6.0.0", + "@pm2/io": "~6.0.1", "@pm2/js-api": "~0.8.0", "@pm2/pm2-version-check": "latest", "async": "~3.2.0", @@ -9446,9 +9347,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", "dev": true, "funding": [ { @@ -9464,10 +9365,9 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "source-map-js": "^1.2.0" }, "engines": { @@ -9475,11 +9375,10 @@ } }, "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", - "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", - "dev": true, - "license": "MIT" + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.4.tgz", + "integrity": "sha512-R6vHqZWgVnTAPq0C+xjyHfEZqfIYboCBVSy24MjxEDm+tIh1BU4O6o7DP7AA7kHzf136d+Qc5duI4tlpHjixDw==", + "dev": true }, "node_modules/postcss-safe-parser": { "version": "7.0.0", @@ -9509,11 +9408,10 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", - "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", "dev": true, - "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9539,11 +9437,10 @@ } }, "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, - "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -10058,7 +9955,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", - "license": "MIT", "dependencies": { "debug": "^4.1.1", "module-details-from-path": "^1.0.3", @@ -10380,10 +10276,9 @@ } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "license": "ISC", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -10549,8 +10444,7 @@ "node_modules/shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, "node_modules/side-channel": { "version": "1.0.6", @@ -10636,8 +10530,7 @@ "version": "3.0.12", "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/slice-ansi": { "version": "5.0.0", @@ -11112,9 +11005,9 @@ } }, "node_modules/stylelint": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.6.1.tgz", - "integrity": "sha512-yNgz2PqWLkhH2hw6X9AweV9YvoafbAD5ZsFdKN9BvSDVwGvPh+AUIrn7lYwy1S7IHmtFin75LLfX1m0D2tHu8Q==", + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.1.tgz", + "integrity": "sha512-O8aDyfdODSDNz/B3gW2HQ+8kv8pfhSu7ZR7xskQ93+vI6FhKKGUJMQ03Ydu+w3OvXXE0/u4hWU4hCPNOyld+OA==", "dev": true, "funding": [ { @@ -11126,11 +11019,10 @@ "url": "https://github.com/sponsors/stylelint" } ], - "license": "MIT", "dependencies": { - "@csstools/css-parser-algorithms": "^2.6.3", - "@csstools/css-tokenizer": "^2.3.1", - "@csstools/media-query-list-parser": "^2.1.11", + "@csstools/css-parser-algorithms": "^2.7.1", + "@csstools/css-tokenizer": "^2.4.1", + "@csstools/media-query-list-parser": "^2.1.13", "@csstools/selector-specificity": "^3.1.1", "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", @@ -11138,7 +11030,7 @@ "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.2", "css-tree": "^2.3.1", - "debug": "^4.3.4", + "debug": "^4.3.6", "fast-glob": "^3.3.2", "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^9.0.0", @@ -11149,16 +11041,16 @@ "ignore": "^5.3.1", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.31.0", + "known-css-properties": "^0.34.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", "micromatch": "^4.0.7", "normalize-path": "^3.0.0", "picocolors": "^1.0.1", - "postcss": "^8.4.38", - "postcss-resolve-nested-selector": "^0.1.1", + "postcss": "^8.4.40", + "postcss-resolve-nested-selector": "^0.1.4", "postcss-safe-parser": "^7.0.0", - "postcss-selector-parser": "^6.1.0", + "postcss-selector-parser": "^6.1.1", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", @@ -11225,11 +11117,10 @@ } }, "node_modules/stylelint-prettier": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.0.tgz", - "integrity": "sha512-RHfSlRJIsaVg5Br94gZVdWlz/rBTyQzZflNE6dXvSxt/GthWMY3gEHsWZEBaVGg7GM+XrtVSp4RznFlB7i0oyw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.2.tgz", + "integrity": "sha512-qJ+BN+1T2ZcKz9WIrv0x+eFGHzSUnXfXd5gL///T6XoJvr3D8/ztzz2fhtmXef7Vb8P33zBXmLTTveByr0nwBw==", "dev": true, - "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0" }, @@ -11456,11 +11347,10 @@ "license": "MIT" }, "node_modules/synckit": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.0.tgz", - "integrity": "sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, - "license": "MIT", "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" @@ -11476,14 +11366,12 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true, - "license": "0BSD" + "dev": true }, "node_modules/systeminformation": { - "version": "5.22.11", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.11.tgz", - "integrity": "sha512-aLws5yi4KCHTb0BVvbodQY5bY8eW4asMRDTxTW46hqw9lGjACX6TlLdJrkdoHYRB0qs+MekqEq1zG7WDnWE8Ug==", - "license": "MIT", + "version": "5.23.2", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.2.tgz", + "integrity": "sha512-FoipTSwzZR68ZAjXZ8DRH2DFEErMAOi9JvRMsn6i/hTp6Hd4W4nM1W6a+kUyMrp/pd1SIuUzUZvvkQ21yE6Dig==", "os": [ "darwin", "linux", @@ -11746,8 +11634,7 @@ "node_modules/tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "license": "Apache-2.0" + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "node_modules/tv4": { "version": "1.3.0", diff --git a/package.json b/package.json index 9f1469c127..3048aefaf7 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,8 @@ "*.css": "stylelint --fix" }, "dependencies": { - "ajv": "^8.16.0", - "ansis": "^3.2.0", + "ajv": "^8.17.1", + "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", @@ -68,32 +68,32 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.18.0", - "pm2": "^5.4.1", + "pm2": "^5.4.2", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.22.11" + "systeminformation": "^5.23.2" }, "devDependencies": { "@stylistic/eslint-plugin": "^1.8.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.5.0", - "eslint-plugin-package-json": "^0.15.0", - "eslint-plugin-unicorn": "^54.0.0", + "eslint-plugin-jsdoc": "^48.10.2", + "eslint-plugin-package-json": "^0.15.2", + "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", - "husky": "^9.0.11", + "husky": "^9.1.4", "jest": "^29.7.0", - "jsdom": "^24.1.0", + "jsdom": "^24.1.1", "lint-staged": "^15.2.7", - "playwright": "^1.45.0", - "prettier": "^3.3.2", + "playwright": "^1.45.3", + "prettier": "^3.3.3", "sinon": "^18.0.0", - "stylelint": "^16.6.1", + "stylelint": "^16.8.1", "stylelint-config-standard": "^36.0.1", - "stylelint-prettier": "^5.0.0" + "stylelint-prettier": "^5.0.2" }, "optionalDependencies": { - "electron": "^31.1.0" + "electron": "^31.3.1" }, "engines": { "node": ">=20" diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 058dae08df..c74b6f73a1 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -9,9 +9,9 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-free": "^6.5.2", + "@fortawesome/fontawesome-free": "^6.6.0", "animate.css": "^4.1.1", - "croner": "^8.0.2", + "croner": "^8.1.0", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", @@ -20,10 +20,9 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.2.tgz", - "integrity": "sha512-hRILoInAx8GNT5IMkrtIt9blOdrqHOnPBH+k70aWUAqPZPgopb9G5EQJFpaBx/S8zp2fC+mPW349Bziuk1o28Q==", - "hasInstallScript": true, + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz", + "integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==", "engines": { "node": ">=6" } @@ -52,9 +51,9 @@ } }, "node_modules/croner": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/croner/-/croner-8.0.2.tgz", - "integrity": "sha512-HgSdlSUX8mIgDTTiQpWUP4qY4IFRMsduPCYdca34Pelt8MVdxdaDOzreFtCscA6R+cRZd7UbD1CD3uyx6J3X1A==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/croner/-/croner-8.1.0.tgz", + "integrity": "sha512-sz990XOUPR8dG/r5BRKMBd15MYDDUu8oeSaxFD5DqvNgHSZw8Psd1s689/IGET7ezxRMiNlCIyGeY1Gvxp/MLg==", "engines": { "node": ">=18.0" } diff --git a/vendor/package.json b/vendor/package.json index e61f8bf380..be26ef0822 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -11,9 +11,9 @@ }, "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-free": "^6.5.2", + "@fortawesome/fontawesome-free": "^6.6.0", "animate.css": "^4.1.1", - "croner": "^8.0.2", + "croner": "^8.1.0", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", From 76d8f98969a9b480f93f32ee96e47ae7097348b2 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Thu, 1 Aug 2024 21:24:16 +0200 Subject: [PATCH 084/418] =?UTF-8?q?allow=20custom=20module=20positions=20b?= =?UTF-8?q?y=20setting=20`allowCustomModulePositions`=E2=80=A6=20(#3506)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … in `config.js` fixes #3504, related to https://github.com/MagicMirrorOrg/MagicMirror/pull/3445 --- CHANGELOG.md | 3 ++- js/defaults.js | 1 + js/loader.js | 2 +- js/utils.js | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e9f38814a..b0569cd369 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,8 +18,9 @@ _This release is scheduled to be released on 2024-10-01._ ### Updated -- [weather] Updated `apiVersion` default from 2.5 to 3.0 +- [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) - [core] Updated dependencies +- [core] Allow custom module positions by setting `allowCustomModulePositions` in `config.js` (fixes #3504, related to https://github.com/MagicMirrorOrg/MagicMirror/pull/3445) ### Fixed diff --git a/js/defaults.js b/js/defaults.js index c4efa77e95..1cbef63566 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -27,6 +27,7 @@ const defaults = { // (interval 30 seconds). If startup-timestamp has changed the client reloads the magicmirror webpage. checkServerInterval: 30 * 1000, reloadAfterServerRestart: false, + allowCustomModulePositions: false, modules: [ { diff --git a/js/loader.js b/js/loader.js index e8dff1907c..1ce6f27bd1 100644 --- a/js/loader.js +++ b/js/loader.js @@ -50,7 +50,7 @@ const Loader = (function () { * @returns {object[]} module data as configured in config */ const getAllModules = function () { - const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined")); + const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined" || config.allowCustomModulePositions)); return AllModules; }; diff --git a/js/utils.js b/js/utils.js index 6e4b7eabef..df2e91757d 100644 --- a/js/utils.js +++ b/js/utils.js @@ -34,6 +34,7 @@ module.exports = { // return if postion is on modulePositions Array (true/false) moduleHasValidPosition (position) { + if (config.allowCustomModulePositions) return true; if (this.getAvailableModulePositions().indexOf(position) === -1) return false; return true; } From 780e4e2e064b40ae10fb7faca536b440502433d3 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sun, 4 Aug 2024 14:28:20 -0500 Subject: [PATCH 085/418] Fix loading of multiple instances of node_helper when multiple instances of a module are in config.js (#3517) adds a check for already loaded/loading for node helper of a each module, only does once fixes #3502 --- CHANGELOG.md | 1 + js/app.js | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0569cd369..b14684ab66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ _This release is scheduled to be released on 2024-10-01._ - Fixed `checks` badge in README.md - [weather] Fixed issue with the UK Met Office provider following a change in their API paths and header info. +- [core] add check for node_helper loading for multiple instances of same module (#3502) ## [2.28.0] - 2024-07-01 diff --git a/js/app.js b/js/app.js index f9313ed403..7792750c48 100644 --- a/js/app.js +++ b/js/app.js @@ -9,6 +9,7 @@ const Log = require("logger"); const Server = require(`${__dirname}/server`); const Utils = require(`${__dirname}/utils`); const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`); +const helperhash = {}; // Get version number. global.version = require(`${__dirname}/../package.json`).version; @@ -175,14 +176,23 @@ function App () { const helperPath = `${moduleFolder}/node_helper.js`; - let loadHelper = true; - try { - fs.accessSync(helperPath, fs.R_OK); - } catch (e) { - loadHelper = false; - Log.log(`No helper found for module: ${moduleName}.`); - } + // find out if helper was loaded before for this module + // only load it once + let loadHelper = helperhash[moduleName] ? false : true; + // if this is the 1st time for this module, check for helper file + // otherwise, its already loaded, if found + if (loadHelper) { + try { + fs.accessSync(helperPath, fs.R_OK); + // indicte we found one to load for this module + helperhash[moduleName] = true; + } catch (e) { + loadHelper = false; + Log.log(`No helper found for module: ${moduleName}.`); + } + } + // if the helper was found, AND needed 1st time if (loadHelper) { const Module = require(helperPath); let m = new Module(); From 976c8ae00a63ae148f6610da13f62ef93e693ba0 Mon Sep 17 00:00:00 2001 From: Veeck Date: Mon, 12 Aug 2024 22:52:43 +0200 Subject: [PATCH 086/418] Bump stylistic-eslint (#3520) updates plugin and adjust docs and config for smooth cleaning :-D --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .eslintrc.json | 1 + CHANGELOG.md | 2 +- js/class.js | 21 +- js/electron.js | 50 +- js/module.js | 29 +- js/node_helper.js | 9 +- modules/default/calendar/calendar.js | 31 +- modules/default/calendar/debug.js | 3 +- modules/default/defaultmodules.js | 3 +- .../updatenotification/update_helper.js | 19 +- .../default/weather/providers/envcanada.js | 342 ++++++-------- .../default/weather/providers/openmeteo.js | 10 +- .../weather/providers/openweathermap.js | 46 +- .../weather/providers/pirateweather.js | 10 +- modules/default/weather/providers/smhi.js | 11 +- .../default/weather/providers/ukmetoffice.js | 39 +- .../weather/providers/ukmetofficedatahub.js | 53 ++- .../default/weather/providers/weatherbit.js | 10 +- .../default/weather/providers/weatherflow.js | 10 +- .../default/weather/providers/weathergov.js | 38 +- modules/default/weather/providers/yr.js | 17 +- package-lock.json | 428 ++++++++++-------- package.json | 12 +- .../calendar/exdate_la_at_midnight_dst.js | 3 +- .../calendar/exdate_la_at_midnight_std.js | 3 +- .../calendar/exdate_la_before_midnight.js | 3 +- .../calendar/exdate_syd_at_midnight_dst.js | 3 +- .../calendar/exdate_syd_at_midnight_std.js | 3 +- .../calendar/exdate_syd_before_midnight.js | 3 +- .../modules/calendar/long-fullday-event.js | 3 +- .../modules/calendar/single-fullday-event.js | 3 +- tests/electron/modules/calendar_spec.js | 45 +- 32 files changed, 699 insertions(+), 564 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index dccd2ee2dc..629c008246 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -49,6 +49,7 @@ "@stylistic/function-paren-newline": ["error", "consistent"], "@stylistic/implicit-arrow-linebreak": ["error", "beside"], "@stylistic/max-statements-per-line": ["error", { "max": 2 }], + "@stylistic/multiline-comment-style": "off", "@stylistic/multiline-ternary": ["error", "always-multiline"], "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 4 }], "@stylistic/no-extra-parens": "off", diff --git a/CHANGELOG.md b/CHANGELOG.md index b14684ab66..a41be65c64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ _This release is scheduled to be released on 2024-10-01._ ### Updated - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) -- [core] Updated dependencies +- [core] Updated dependencies including stylistic-eslint - [core] Allow custom module positions by setting `allowCustomModulePositions` in `config.js` (fixes #3504, related to https://github.com/MagicMirrorOrg/MagicMirror/pull/3445) ### Fixed diff --git a/js/class.js b/js/class.js index c3a0ab22eb..9cfeee4ceb 100644 --- a/js/class.js +++ b/js/class.js @@ -1,6 +1,7 @@ /* global Class, xyz */ -/* Simple JavaScript Inheritance +/* + * Simple JavaScript Inheritance * By John Resig https://johnresig.com/ * * Inspired by base2 and Prototype @@ -22,8 +23,10 @@ Class.extend = function (prop) { let _super = this.prototype; - // Instantiate a base class (but only create the instance, - // don't run the init constructor) + /* + * Instantiate a base class (but only create the instance, + * don't run the init constructor) + */ initializing = true; const prototype = new this(); initializing = false; @@ -42,12 +45,16 @@ return function () { const tmp = this._super; - // Add a new ._super() method that is the same method - // but on the super-class + /* + * Add a new ._super() method that is the same method + * but on the super-class + */ this._super = _super[name]; - // The method only need to be bound temporarily, so we - // remove it when we're done executing + /* + * The method only need to be bound temporarily, so we + * remove it when we're done executing + */ const ret = fn.apply(this, arguments); this._super = tmp; diff --git a/js/electron.js b/js/electron.js index 2dfde6728a..4bfe35427f 100644 --- a/js/electron.js +++ b/js/electron.js @@ -8,9 +8,12 @@ const Log = require("./logger"); let config = process.env.config ? JSON.parse(process.env.config) : {}; // Module to control application life. const app = electron.app; -// Per default electron is started with --disable-gpu flag, if you want the gpu enabled, -// you must set the env var ELECTRON_ENABLE_GPU=1 on startup. -// See https://www.electronjs.org/docs/latest/tutorial/offscreen-rendering for more info. + +/* + * Per default electron is started with --disable-gpu flag, if you want the gpu enabled, + * you must set the env var ELECTRON_ENABLE_GPU=1 on startup. + * See https://www.electronjs.org/docs/latest/tutorial/offscreen-rendering for more info. + */ if (process.env.ELECTRON_ENABLE_GPU !== "1") { app.disableHardwareAcceleration(); } @@ -18,16 +21,21 @@ if (process.env.ELECTRON_ENABLE_GPU !== "1") { // Module to create native browser window. const BrowserWindow = electron.BrowserWindow; -// Keep a global reference of the window object, if you don't, the window will -// be closed automatically when the JavaScript object is garbage collected. +/* + * Keep a global reference of the window object, if you don't, the window will + * be closed automatically when the JavaScript object is garbage collected. + */ let mainWindow; /** * */ function createWindow () { - // see https://www.electronjs.org/docs/latest/api/screen - // Create a window that fills the screen's available work area. + + /* + * see https://www.electronjs.org/docs/latest/api/screen + * Create a window that fills the screen's available work area. + */ let electronSize = (800, 600); try { electronSize = electron.screen.getPrimaryDisplay().workAreaSize; @@ -52,8 +60,10 @@ function createWindow () { backgroundColor: "#000000" }; - // DEPRECATED: "kioskmode" backwards compatibility, to be removed - // settings these options directly instead provides cleaner interface + /* + * DEPRECATED: "kioskmode" backwards compatibility, to be removed + * settings these options directly instead provides cleaner interface + */ if (config.kioskmode) { electronOptionsDefaults.kiosk = true; } else { @@ -69,8 +79,10 @@ function createWindow () { // Create the browser window. mainWindow = new BrowserWindow(electronOptions); - // and load the index.html of the app. - // If config.address is not defined or is an empty string (listening on all interfaces), connect to localhost + /* + * and load the index.html of the app. + * If config.address is not defined or is an empty string (listening on all interfaces), connect to localhost + */ let prefix; if ((config["tls"] !== null && config["tls"]) || config.useHttps) { @@ -149,14 +161,18 @@ app.on("window-all-closed", function () { }); app.on("activate", function () { - // On OS X it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. + + /* + * On OS X it's common to re-create a window in the app when the + * dock icon is clicked and there are no other windows open. + */ if (mainWindow === null) { createWindow(); } }); -/* This method will be called when SIGINT is received and will call +/* + * This method will be called when SIGINT is received and will call * each node_helper's stop function if it exists. Added to fix #1056 * * Note: this is only used if running Electron. Otherwise @@ -187,8 +203,10 @@ if (process.env.clientonly) { }); } -// Start the core application if server is run on localhost -// This starts all node helpers and starts the webserver. +/* + * Start the core application if server is run on localhost + * This starts all node helpers and starts the webserver. + */ if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].includes(config.address)) { core.start().then((c) => { config = c; diff --git a/js/module.js b/js/module.js index 71451763d0..3fc2cf3035 100644 --- a/js/module.js +++ b/js/module.js @@ -1,13 +1,16 @@ /* global Class, cloneObject, Loader, MMSocket, nunjucks, Translator */ -/* Module Blueprint. +/* + * Module Blueprint. * @typedef {Object} Module */ const Module = Class.extend({ - /********************************************************* + /** + ******************************************************** * All methods (and properties) below can be subclassed. * - *********************************************************/ + ******************************************************** + */ // Set the minimum MagicMirror² module version for this module. requiresVersion: "2.0.0", @@ -18,13 +21,17 @@ const Module = Class.extend({ // Timer reference used for showHide animation callbacks. showHideTimer: null, - // Array to store lockStrings. These strings are used to lock - // visibility when hiding and showing module. + /* + * Array to store lockStrings. These strings are used to lock + * visibility when hiding and showing module. + */ lockStrings: [], - // Storage of the nunjucks Environment, - // This should not be referenced directly. - // Use the nunjucksEnvironment() to get it. + /* + * Storage of the nunjucks Environment, + * This should not be referenced directly. + * Use the nunjucksEnvironment() to get it. + */ _nunjucksEnvironment: null, /** @@ -189,9 +196,11 @@ const Module = Class.extend({ Log.log(`${this.name} is resumed.`); }, - /********************************************* + /** + ******************************************** * The methods below don't need subclassing. * - *********************************************/ + ******************************************** + */ /** * Set the module data. diff --git a/js/node_helper.js b/js/node_helper.js index 42da0efcff..dd272c4e0f 100644 --- a/js/node_helper.js +++ b/js/node_helper.js @@ -49,7 +49,8 @@ const NodeHelper = Class.extend({ this.path = path; }, - /* sendSocketNotification(notification, payload) + /* + * sendSocketNotification(notification, payload) * Send a socket notification to the node helper. * * argument notification string - The identifier of the notification. @@ -59,7 +60,8 @@ const NodeHelper = Class.extend({ this.io.of(this.name).emit(notification, payload); }, - /* setExpressApp(app) + /* + * setExpressApp(app) * Sets the express app object for this module. * This allows you to host files from the created webserver. * @@ -71,7 +73,8 @@ const NodeHelper = Class.extend({ app.use(`/${this.name}`, express.static(`${this.path}/public`)); }, - /* setSocketIO(io) + /* + * setSocketIO(io) * Sets the socket io object for this module. * Binds message receiver. * diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 4b0409c01c..31ad4f5ea0 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -82,9 +82,12 @@ Module.register("calendar", { // Define required translations. getTranslations () { - // The translations for the default modules are defined in the core translation files. - // Therefore we can just return false. Otherwise we should have returned a dictionary. - // If you're trying to build your own module including translations, check out the documentation. + + /* + * The translations for the default modules are defined in the core translation files. + * Therefore we can just return false. Otherwise we should have returned a dictionary. + * If you're trying to build your own module including translations, check out the documentation. + */ return false; }, @@ -148,8 +151,10 @@ Module.register("calendar", { }; } - // tell helper to start a fetcher for this calendar - // fetcher till cycle + /* + * tell helper to start a fetcher for this calendar + * fetcher till cycle + */ this.addCalendar(calendar.url, calendar.auth, calendarConfig); }); @@ -627,7 +632,8 @@ Module.register("calendar", { event.tomorrow = !event.today && event.startDate >= today + ONE_DAY && event.startDate < today + 2 * ONE_DAY; event.dayAfterTomorrow = !event.tomorrow && event.startDate >= today + ONE_DAY * 2 && event.startDate < today + 3 * ONE_DAY; - /* if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days, + /* + * if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days, * otherwise, esp. in dateheaders mode it is not clear how long these events are. */ const maxCount = Math.ceil((event.endDate - 1 - moment(event.startDate, "x").endOf("day").format("x")) / ONE_DAY) + 1; @@ -677,16 +683,21 @@ Module.register("calendar", { return events; } - // Limit the number of days displayed - // If limitDays is set > 0, limit display to that number of days + /* + * Limit the number of days displayed + * If limitDays is set > 0, limit display to that number of days + */ if (this.config.limitDays > 0) { let newEvents = []; let lastDate = today.clone().subtract(1, "days").format("YYYYMMDD"); let days = 0; for (const ev of events) { let eventDate = moment(ev.startDate, "x").format("YYYYMMDD"); - // if date of event is later than lastdate - // check if we already are showing max unique days + + /* + * if date of event is later than lastdate + * check if we already are showing max unique days + */ if (eventDate > lastDate) { // if the only entry in the first day is a full day event that day is not counted as unique if (!this.config.limitDaysNeverSkip && newEvents.length === 1 && days === 1 && newEvents[0].fullDayEvent) { diff --git a/modules/default/calendar/debug.js b/modules/default/calendar/debug.js index 71ed2f4abd..74d48cd711 100644 --- a/modules/default/calendar/debug.js +++ b/modules/default/calendar/debug.js @@ -1,4 +1,5 @@ -/* CalendarFetcher Tester +/* + * CalendarFetcher Tester * use this script with `node debug.js` to test the fetcher without the need * of starting the MagicMirror² core. Adjust the values below to your desire. */ diff --git a/modules/default/defaultmodules.js b/modules/default/defaultmodules.js index e28413ff7b..695bba4476 100644 --- a/modules/default/defaultmodules.js +++ b/modules/default/defaultmodules.js @@ -1,4 +1,5 @@ -/* Default Modules List +/* + * Default Modules List * Modules listed below can be loaded without the 'default/' prefix. Omitting the default folder name. */ const defaultModules = ["alert", "calendar", "clock", "compliments", "helloworld", "newsfeed", "updatenotification", "weather"]; diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index 0bf3868e7c..122b6b3567 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -4,7 +4,8 @@ const fs = require("node:fs"); const Log = require("logger"); -/* class Updater +/* + * class Updater * Allow to self updating 3rd party modules from command defined in config * * [constructor] read value in config: @@ -84,13 +85,15 @@ class Updater { return updater; } - // module updater with his proper command - // return object as result - //{ - // error: , // if error detected - // updated: , // if updated successfully - // needRestart: // if magicmirror restart required - //}; + /* + * module updater with his proper command + * return object as result + * { + * error: , // if error detected + * updated: , // if updated successfully + * needRestart: // if magicmirror restart required + * }; + */ updateProcess (module) { let Result = { error: false, diff --git a/modules/default/weather/providers/envcanada.js b/modules/default/weather/providers/envcanada.js index 7372e17689..8255802628 100644 --- a/modules/default/weather/providers/envcanada.js +++ b/modules/default/weather/providers/envcanada.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* This class is a provider for Environment Canada MSC Datamart +/* + * This class is a provider for Environment Canada MSC Datamart * Note that this is only for Canadian locations and does not require an API key (access is anonymous) * * EC Documentation at following links: @@ -25,9 +26,7 @@ * * License to use Environment Canada (EC) data is detailed here: * https://eccc-msc.github.io/open-data/licence/readme_en/ - * */ - WeatherProvider.register("envcanada", { // Set the name of the provider for debugging and alerting purposes (eg. provide eye-catcher) providerName: "Environment Canada", @@ -39,10 +38,10 @@ WeatherProvider.register("envcanada", { provCode: "ON" }, - // - // Set config values (equates to weather module config values). Also set values pertaining to caching of - // Today's temperature forecast (for use in the Forecast functions below) - // + /* + * Set config values (equates to weather module config values). Also set values pertaining to caching of + * Today's temperature forecast (for use in the Forecast functions below) + */ setConfig (config) { this.config = config; @@ -52,17 +51,17 @@ WeatherProvider.register("envcanada", { this.cacheCurrentTemp = 999; }, - // - // Called when the weather provider is started - // + /* + * Called when the weather provider is started + */ start () { Log.info(`Weather provider: ${this.providerName} started.`); this.setFetchedLocation(this.config.location); }, - // - // Override the fetchCurrentWeather method to query EC and construct a Current weather object - // + /* + * Override the fetchCurrentWeather method to query EC and construct a Current weather object + */ fetchCurrentWeather () { this.fetchData(this.getUrl(), "xml") .then((data) => { @@ -80,9 +79,9 @@ WeatherProvider.register("envcanada", { .finally(() => this.updateAvailable()); }, - // - // Override the fetchWeatherForecast method to query EC and construct Forecast weather objects - // + /* + * Override the fetchWeatherForecast method to query EC and construct Forecast weather objects + */ fetchWeatherForecast () { this.fetchData(this.getUrl(), "xml") .then((data) => { @@ -100,9 +99,9 @@ WeatherProvider.register("envcanada", { .finally(() => this.updateAvailable()); }, - // - // Override the fetchWeatherHourly method to query EC and construct Forecast weather objects - // + /* + * Override the fetchWeatherHourly method to query EC and construct Forecast weather objects + */ fetchWeatherHourly () { this.fetchData(this.getUrl(), "xml") .then((data) => { @@ -120,36 +119,30 @@ WeatherProvider.register("envcanada", { .finally(() => this.updateAvailable()); }, - ////////////////////////////////////////////////////////////////////////////////// - // - // Environment Canada methods - not part of the standard Provider methods - // - ////////////////////////////////////////////////////////////////////////////////// - - // - // Build the EC URL based on the Site Code and Province Code specified in the config params. Note that the - // URL defaults to the English version simply because there is no language dependency in the data - // being accessed. This is only pertinent when using the EC data elements that contain a textual forecast. - // + /* + * Build the EC URL based on the Site Code and Province Code specified in the config params. Note that the + * URL defaults to the English version simply because there is no language dependency in the data + * being accessed. This is only pertinent when using the EC data elements that contain a textual forecast. + */ getUrl () { return `https://dd.weather.gc.ca/citypage_weather/xml/${this.config.provCode}/${this.config.siteCode}_e.xml`; }, - // - // Generate a WeatherObject based on current EC weather conditions - // - + /* + * Generate a WeatherObject based on current EC weather conditions + */ generateWeatherObjectFromCurrentWeather (ECdoc) { const currentWeather = new WeatherObject(); - // There are instances where EC will update weather data and current temperature will not be - // provided. While this is a defect in the EC systems, we need to accommodate to avoid a current temp - // of NaN being displayed. Therefore... whenever we get a valid current temp from EC, we will cache - // the value. Whenever EC data is missing current temp, we will provide the cached value - // instead. This is reasonable since the cached value will typically be accurate within the previous - // hour. The only time this does not work as expected is when MM is restarted and the first query to - // EC finds no current temp. In this scenario, MM will end up displaying a current temp of null; - + /* + * There are instances where EC will update weather data and current temperature will not be + * provided. While this is a defect in the EC systems, we need to accommodate to avoid a current temp + * of NaN being displayed. Therefore... whenever we get a valid current temp from EC, we will cache + * the value. Whenever EC data is missing current temp, we will provide the cached value + * instead. This is reasonable since the cached value will typically be accurate within the previous + * hour. The only time this does not work as expected is when MM is restarted and the first query to + * EC finds no current temp. In this scenario, MM will end up displaying a current temp of null; + */ if (ECdoc.querySelector("siteData currentConditions temperature").textContent) { currentWeather.temperature = ECdoc.querySelector("siteData currentConditions temperature").textContent; this.cacheCurrentTemp = currentWeather.temperature; @@ -163,19 +156,19 @@ WeatherProvider.register("envcanada", { currentWeather.humidity = ECdoc.querySelector("siteData currentConditions relativeHumidity").textContent; - // Ensure showPrecipitationAmount is forced to false. EC does not really provide POP for current day - // and this feature for the weather module (current only) is sort of broken in that it wants - // to say POP but will display precip as an accumulated amount vs. a percentage. - + /* + * Ensure showPrecipitationAmount is forced to false. EC does not really provide POP for current day + * and this feature for the weather module (current only) is sort of broken in that it wants + * to say POP but will display precip as an accumulated amount vs. a percentage. + */ this.config.showPrecipitationAmount = false; - // - // If the module config wants to showFeelsLike... default to the current temperature. - // Check for EC wind chill and humidex values and overwrite the feelsLikeTemp value. - // This assumes that the EC current conditions will never contain both a wind chill - // and humidex temperature. - // - + /* + * If the module config wants to showFeelsLike... default to the current temperature. + * Check for EC wind chill and humidex values and overwrite the feelsLikeTemp value. + * This assumes that the EC current conditions will never contain both a wind chill + * and humidex temperature. + */ if (this.config.showFeelsLike) { currentWeather.feelsLikeTemp = currentWeather.temperature; @@ -188,16 +181,10 @@ WeatherProvider.register("envcanada", { } } - // // Need to map EC weather icon to MM weatherType values - // - currentWeather.weatherType = this.convertWeatherType(ECdoc.querySelector("siteData currentConditions iconCode").textContent); - // // Capture the sunrise and sunset values from EC data - // - const sunList = ECdoc.querySelectorAll("siteData riseSet dateTime"); currentWeather.sunrise = moment(sunList[1].querySelector("timeStamp").textContent, "YYYYMMDDhhmmss"); @@ -206,13 +193,11 @@ WeatherProvider.register("envcanada", { return currentWeather; }, - // - // Generate an array of WeatherObjects based on EC weather forecast - // - + /* + * Generate an array of WeatherObjects based on EC weather forecast + */ generateWeatherObjectsFromForecast (ECdoc) { // Declare an array to hold each day's forecast object - const days = []; const weather = new WeatherObject(); @@ -226,37 +211,33 @@ WeatherProvider.register("envcanada", { weather.precipitationAmount = null; - // - // The EC forecast is held in a 12-element array - Elements 0 to 11 - with each day encompassing - // 2 elements. the first element for a day details the Today (daytime) forecast while the second - // element details the Tonight (nightime) forecast. Element 0 is always for the current day. - // - // However... the forecast is somewhat 'rolling'. - // - // If the EC forecast is queried in the morning, then Element 0 will contain Current - // Today and Element 1 will contain Current Tonight. From there, the next 5 days of forecast will be - // contained in Elements 2/3, 4/5, 6/7, 8/9, and 10/11. This module will create a 6-day forecast using - // all of these Elements. - // - // But, if the EC forecast is queried in late afternoon, the Current Today forecast will be rolled - // off and Element 0 will contain Current Tonight. From there, the next 5 days will be contained in - // Elements 1/2, 3/4, 5/6, 7/8, and 9/10. As well, Elelement 11 will contain a forecast for a 6th day, - // but only for the Today portion (not Tonight). This module will create a 6-day forecast using - // Elements 0 to 11, and will ignore the additional Todat forecast in Element 11. - // - // We need to determine if Element 0 is showing the forecast for Current Today or Current Tonight. - // This is required to understand how Min and Max temperature will be determined, and to understand - // where the next day's (aka Tomorrow's) forecast is located in the forecast array. - // - + /* + * The EC forecast is held in a 12-element array - Elements 0 to 11 - with each day encompassing + * 2 elements. the first element for a day details the Today (daytime) forecast while the second + * element details the Tonight (nightime) forecast. Element 0 is always for the current day. + * + * However... the forecast is somewhat 'rolling'. + * + * If the EC forecast is queried in the morning, then Element 0 will contain Current + * Today and Element 1 will contain Current Tonight. From there, the next 5 days of forecast will be + * contained in Elements 2/3, 4/5, 6/7, 8/9, and 10/11. This module will create a 6-day forecast using + * all of these Elements. + * + * But, if the EC forecast is queried in late afternoon, the Current Today forecast will be rolled + * off and Element 0 will contain Current Tonight. From there, the next 5 days will be contained in + * Elements 1/2, 3/4, 5/6, 7/8, and 9/10. As well, Elelement 11 will contain a forecast for a 6th day, + * but only for the Today portion (not Tonight). This module will create a 6-day forecast using + * Elements 0 to 11, and will ignore the additional Todat forecast in Element 11. + * + * We need to determine if Element 0 is showing the forecast for Current Today or Current Tonight. + * This is required to understand how Min and Max temperature will be determined, and to understand + * where the next day's (aka Tomorrow's) forecast is located in the forecast array. + */ let nextDay = 0; let lastDay = 0; const currentTemp = ECdoc.querySelector("siteData currentConditions temperature").textContent; - // // If the first Element is Current Today, look at Current Today and Current Tonight for the current day. - // - if (foreGroup[0].querySelector("period[textForecastName='Today']")) { this.todaytempCacheMin = 0; this.todaytempCacheMax = 0; @@ -266,167 +247,144 @@ WeatherProvider.register("envcanada", { this.setPrecipitation(weather, foreGroup, 0); - // - // Set the Element number that will reflect where the next day's forecast is located. Also set - // the Element number where the end of the forecast will be. This is important because of the - // rolling nature of the EC forecast. In the current scenario (Today and Tonight are present - // in elements 0 and 11, we know that we will have 6 full days of forecasts and we will use - // them. We will set lastDay such that we iterate through all 12 elements of the forecast. - // - + /* + * Set the Element number that will reflect where the next day's forecast is located. Also set + * the Element number where the end of the forecast will be. This is important because of the + * rolling nature of the EC forecast. In the current scenario (Today and Tonight are present + * in elements 0 and 11, we know that we will have 6 full days of forecasts and we will use + * them. We will set lastDay such that we iterate through all 12 elements of the forecast. + */ nextDay = 2; lastDay = 12; } - // // If the first Element is Current Tonight, look at Tonight only for the current day. - // if (foreGroup[0].querySelector("period[textForecastName='Tonight']")) { this.setMinMaxTemps(weather, foreGroup, 0, false, currentTemp); this.setPrecipitation(weather, foreGroup, 0); - // - // Set the Element number that will reflect where the next day's forecast is located. Also set - // the Element number where the end of the forecast will be. This is important because of the - // rolling nature of the EC forecast. In the current scenario (only Current Tonight is present - // in Element 0, we know that we will have 6 full days of forecasts PLUS a half-day and - // forecast in the final element. Because we will only use full day forecasts, we set the - // lastDay number to ensure we ignore that final half-day (in forecast Element 11). - // - + /* + * Set the Element number that will reflect where the next day's forecast is located. Also set + * the Element number where the end of the forecast will be. This is important because of the + * rolling nature of the EC forecast. In the current scenario (only Current Tonight is present + * in Element 0, we know that we will have 6 full days of forecasts PLUS a half-day and + * forecast in the final element. Because we will only use full day forecasts, we set the + * lastDay number to ensure we ignore that final half-day (in forecast Element 11). + */ nextDay = 1; lastDay = 11; } - // - // Need to map EC weather icon to MM weatherType values. Always pick the first Element's icon to - // reflect either Today or Tonight depending on what the forecast is showing in Element 0. - // - + /* + * Need to map EC weather icon to MM weatherType values. Always pick the first Element's icon to + * reflect either Today or Tonight depending on what the forecast is showing in Element 0. + */ weather.weatherType = this.convertWeatherType(foreGroup[0].querySelector("abbreviatedForecast iconCode").textContent); // Push the weather object into the forecast array. - days.push(weather); - // - // Now do the rest of the forecast starting at nextDay. We will process each day using 2 EC - // forecast Elements. This will address the fact that the EC forecast always includes Today and - // Tonight for each day. This is why we iterate through the forecast by a a count of 2, with each - // iteration looking at the current Element and the next Element. - // - + /* + * Now do the rest of the forecast starting at nextDay. We will process each day using 2 EC + * forecast Elements. This will address the fact that the EC forecast always includes Today and + * Tonight for each day. This is why we iterate through the forecast by a a count of 2, with each + * iteration looking at the current Element and the next Element. + */ let lastDate = moment(baseDate, "YYYYMMDDhhmmss"); for (let stepDay = nextDay; stepDay < lastDay; stepDay += 2) { let weather = new WeatherObject(); // Add 1 to the date to reflect the current forecast day we are building - lastDate = lastDate.add(1, "day"); weather.date = moment(lastDate); - // Capture the temperatures for the current Element and the next Element in order to set - // the Min and Max temperatures for the forecast - + /* + * Capture the temperatures for the current Element and the next Element in order to set + * the Min and Max temperatures for the forecast + */ this.setMinMaxTemps(weather, foreGroup, stepDay, true, currentTemp); weather.precipitationAmount = null; this.setPrecipitation(weather, foreGroup, stepDay); - // // Need to map EC weather icon to MM weatherType values. Always pick the first Element icon. - // - weather.weatherType = this.convertWeatherType(foreGroup[stepDay].querySelector("abbreviatedForecast iconCode").textContent); // Push the weather object into the forecast array. - days.push(weather); } return days; }, - // - // Generate an array of WeatherObjects based on EC hourly weather forecast - // - + /* + * Generate an array of WeatherObjects based on EC hourly weather forecast + */ generateWeatherObjectsFromHourly (ECdoc) { // Declare an array to hold each hour's forecast object - const hours = []; // Get local timezone UTC offset so that each hourly time can be calculated properly - const baseHours = ECdoc.querySelectorAll("siteData hourlyForecastGroup dateTime"); const hourOffset = baseHours[1].getAttribute("UTCOffset"); - // - // The EC hourly forecast is held in a 24-element array - Elements 0 to 23 - with Element 0 holding - // the forecast for the next 'on the hour' timeslot. This means the array is a rolling 24 hours. - // - + /* + * The EC hourly forecast is held in a 24-element array - Elements 0 to 23 - with Element 0 holding + * the forecast for the next 'on the hour' timeslot. This means the array is a rolling 24 hours. + */ const hourGroup = ECdoc.querySelectorAll("siteData hourlyForecastGroup hourlyForecast"); for (let stepHour = 0; stepHour < 24; stepHour += 1) { const weather = new WeatherObject(); // Determine local time by applying UTC offset to the forecast timestamp - const foreTime = moment(hourGroup[stepHour].getAttribute("dateTimeUTC"), "YYYYMMDDhhmmss"); const currTime = foreTime.add(hourOffset, "hours"); weather.date = moment(currTime); // Capture the temperature - weather.temperature = hourGroup[stepHour].querySelector("temperature").textContent; // Capture Likelihood of Precipitation (LOP) and unit-of-measure values - const precipLOP = hourGroup[stepHour].querySelector("lop").textContent * 1.0; if (precipLOP > 0) { weather.precipitationProbability = precipLOP; } - // // Need to map EC weather icon to MM weatherType values. Always pick the first Element icon. - // - weather.weatherType = this.convertWeatherType(hourGroup[stepHour].querySelector("iconCode").textContent); // Push the weather object into the forecast array. - hours.push(weather); } return hours; }, - // - // Determine Min and Max temp based on a supplied Forecast Element index and a boolen that denotes if - // the next Forecast element should be considered - i.e. look at Today *and* Tonight vs.Tonight-only - // + /* + * Determine Min and Max temp based on a supplied Forecast Element index and a boolen that denotes if + * the next Forecast element should be considered - i.e. look at Today *and* Tonight vs.Tonight-only + */ setMinMaxTemps (weather, foreGroup, today, fullDay, currentTemp) { const todayTemp = foreGroup[today].querySelector("temperatures temperature").textContent; const todayClass = foreGroup[today].querySelector("temperatures temperature").getAttribute("class"); - // - // The following logic is largely aimed at accommodating the Current day's forecast whereby we - // can have either Current Today+Current Tonight or only Current Tonight. - // - // If fullDay is false, then we only have Tonight for the current day's forecast - meaning we have - // lost a min or max temp value for the day. Therefore, we will see if we were able to cache the the - // Today forecast for the current day. If we have, we will use them. If we do not have the cached values, - // it means that MM or the Computer has been restarted since the time EC rolled off Today from the - // forecast. In this scenario, we will simply default to the Current Conditions temperature and then - // check the Tonight temperature. - // - + /* + * The following logic is largely aimed at accommodating the Current day's forecast whereby we + * can have either Current Today+Current Tonight or only Current Tonight. + * + * If fullDay is false, then we only have Tonight for the current day's forecast - meaning we have + * lost a min or max temp value for the day. Therefore, we will see if we were able to cache the the + * Today forecast for the current day. If we have, we will use them. If we do not have the cached values, + * it means that MM or the Computer has been restarted since the time EC rolled off Today from the + * forecast. In this scenario, we will simply default to the Current Conditions temperature and then + * check the Tonight temperature.x + */ if (fullDay === false) { if (this.todayCached === true) { weather.minTemperature = this.todayTempCacheMin; @@ -437,13 +395,12 @@ WeatherProvider.register("envcanada", { } } - // - // We will check to see if the current Element's temperature is Low or High and set weather values - // accordingly. We will also check the condition where fullDay is true *and* we are looking at forecast - // element 0. This is a special case where we will cache temperature values so that we have them later - // in the current day when the Current Today element rolls off and we have Current Tonight only. - // - + /* + * We will check to see if the current Element's temperature is Low or High and set weather values + * accordingly. We will also check the condition where fullDay is true *and* we are looking at forecast + * element 0. This is a special case where we will cache temperature values so that we have them later + * in the current day when the Current Today element rolls off and we have Current Tonight only. + */ if (todayClass === "low") { weather.minTemperature = todayTemp; if (today === 0 && fullDay === true) { @@ -473,25 +430,24 @@ WeatherProvider.register("envcanada", { } }, - // - // Check for a Precipitation forecast. EC can provide a forecast in 2 ways: either an accumulation figure - // or a POP percentage. If there is a POP, then that is what the module will show. If there is an accumulation, - // then it will be displayed ONLY if no POP is present. - // - // POP Logic: By default, we want to show the POP for 'daytime' since we are presuming that is what - // people are more interested in seeing. While EC provides a separate POP for daytime and nightime portions - // of each day, the weather module does not really allow for that view of a daily forecast. There we will - // ignore any nightime portion. There is an exception however! For the Current day, the EC data will only show - // the nightime forecast after a certain point in the afternoon. As such, we will be showing the nightime POP - // (if one exists) in that specific scenario. - // - // Accumulation Logic: Similar to POP, we want to show accumulation for 'daytime' since we presume that is what - // people are interested in seeing. While EC provides a separate accumulation for daytime and nightime portions - // of each day, the weather module does not really allow for that view of a daily forecast. There we will - // ignore any nightime portion. There is an exception however! For the Current day, the EC data will only show - // the nightime forecast after a certain point in that specific scenario. - // - + /* + * Check for a Precipitation forecast. EC can provide a forecast in 2 ways: either an accumulation figure + * or a POP percentage. If there is a POP, then that is what the module will show. If there is an accumulation, + * then it will be displayed ONLY if no POP is present. + * + * POP Logic: By default, we want to show the POP for 'daytime' since we are presuming that is what + * people are more interested in seeing. While EC provides a separate POP for daytime and nightime portions + * of each day, the weather module does not really allow for that view of a daily forecast. There we will + * ignore any nightime portion. There is an exception however! For the Current day, the EC data will only show + * the nightime forecast after a certain point in the afternoon. As such, we will be showing the nightime POP + * (if one exists) in that specific scenario. + * + * Accumulation Logic: Similar to POP, we want to show accumulation for 'daytime' since we presume that is what + * people are interested in seeing. While EC provides a separate accumulation for daytime and nightime portions + * of each day, the weather module does not really allow for that view of a daily forecast. There we will + * ignore any nightime portion. There is an exception however! For the Current day, the EC data will only show + * the nightime forecast after a certain point in that specific scenario. + */ setPrecipitation (weather, foreGroup, today) { if (foreGroup[today].querySelector("precipitation accumulation")) { weather.precipitationAmount = foreGroup[today].querySelector("precipitation accumulation amount").textContent * 1.0; @@ -505,9 +461,9 @@ WeatherProvider.register("envcanada", { } }, - // - // Convert the icons to a more usable name. - // + /* + * Convert the icons to a more usable name. + */ convertWeatherType (weatherType) { const weatherTypes = { "00": "day-sunny", diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index 6acddec763..07f17e935c 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Open-Meteo, +/* + * This class is a provider for Open-Meteo, * see https://open-meteo.com/ */ @@ -9,8 +10,11 @@ const GEOCODE_BASE = "https://api.bigdatacloud.net/data/reverse-geocode-client"; const OPEN_METEO_BASE = "https://api.open-meteo.com/v1"; WeatherProvider.register("openmeteo", { - // Set the name of the provider. - // Not strictly required, but helps for debugging. + + /* + * Set the name of the provider. + * Not strictly required, but helps for debugging. + */ providerName: "Open-Meteo", // Set the default config properties that is specific to this provider diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index 11504bb521..3f29ed5562 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -1,12 +1,16 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Openweathermap, +/* + * This class is a provider for Openweathermap, * see https://openweathermap.org/ */ WeatherProvider.register("openweathermap", { - // Set the name of the provider. - // This isn't strictly necessary, since it will fallback to the provider identifier - // But for debugging (and future alerts) it would be nice to have the real name. + + /* + * Set the name of the provider. + * This isn't strictly necessary, since it will fallback to the provider identifier + * But for debugging (and future alerts) it would be nice to have the real name. + */ providerName: "OpenWeatherMap", // Set the default config properties that is specific to this provider @@ -67,8 +71,11 @@ WeatherProvider.register("openweathermap", { this.fetchData(this.getUrl()) .then((data) => { if (!data) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ return; } @@ -206,8 +213,10 @@ WeatherProvider.register("openweathermap", { weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); } - // the same day as before - // add values from forecast to corresponding variables + /* + * the same day as before + * add values from forecast to corresponding variables + */ minTemp.push(forecast.main.temp_min); maxTemp.push(forecast.main.temp_max); @@ -220,8 +229,10 @@ WeatherProvider.register("openweathermap", { } } - // last day - // calculate minimum/maximum temperature, specify rain amount + /* + * last day + * calculate minimum/maximum temperature, specify rain amount + */ weather.minTemperature = Math.min.apply(null, minTemp); weather.maxTemperature = Math.max.apply(null, maxTemp); weather.rain = rain; @@ -250,14 +261,18 @@ WeatherProvider.register("openweathermap", { weather.rain = 0; weather.snow = 0; - // forecast.rain not available if amount is zero - // The API always returns in millimeters + /* + * forecast.rain not available if amount is zero + * The API always returns in millimeters + */ if (forecast.hasOwnProperty("rain") && !isNaN(forecast.rain)) { weather.rain = forecast.rain; } - // forecast.snow not available if amount is zero - // The API always returns in millimeters + /* + * forecast.snow not available if amount is zero + * The API always returns in millimeters + */ if (forecast.hasOwnProperty("snow") && !isNaN(forecast.snow)) { weather.snow = forecast.snow; } @@ -402,7 +417,8 @@ WeatherProvider.register("openweathermap", { return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; }, - /* getParams(compliments) + /* + * getParams(compliments) * Generates an url with api parameters based on the config. * * return String - URL params. diff --git a/modules/default/weather/providers/pirateweather.js b/modules/default/weather/providers/pirateweather.js index dd20ccf47d..969912f4e1 100644 --- a/modules/default/weather/providers/pirateweather.js +++ b/modules/default/weather/providers/pirateweather.js @@ -1,11 +1,15 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api), +/* + * This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api), * see http://pirateweather.net/en/latest/ */ WeatherProvider.register("pirateweather", { - // Set the name of the provider. - // Not strictly required, but helps for debugging. + + /* + * Set the name of the provider. + * Not strictly required, but helps for debugging. + */ providerName: "pirateweather", // Set the default config properties that is specific to this provider diff --git a/modules/default/weather/providers/smhi.js b/modules/default/weather/providers/smhi.js index d7dcdf1b6f..14185c8649 100644 --- a/modules/default/weather/providers/smhi.js +++ b/modules/default/weather/providers/smhi.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for SMHI (Sweden only). +/* + * This class is a provider for SMHI (Sweden only). * Metric system is the only supported unit, * see https://www.smhi.se/ */ @@ -138,9 +139,11 @@ WeatherProvider.register("smhi", { currentWeather.weatherType = this.convertWeatherType(this.paramValue(weatherData, "Wsymb2"), currentWeather.isDayTime()); currentWeather.feelsLikeTemp = this.calculateApparentTemperature(weatherData); - // Determine the precipitation amount and category and update the - // weatherObject with it, the valuetype to use can be configured or uses - // median as default. + /* + * Determine the precipitation amount and category and update the + * weatherObject with it, the valuetype to use can be configured or uses + * median as default. + */ let precipitationValue = this.paramValue(weatherData, this.config.precipitationValue); switch (this.paramValue(weatherData, "pcat")) { // 0 = No precipitation diff --git a/modules/default/weather/providers/ukmetoffice.js b/modules/default/weather/providers/ukmetoffice.js index c2db4cda37..32c1888fca 100644 --- a/modules/default/weather/providers/ukmetoffice.js +++ b/modules/default/weather/providers/ukmetoffice.js @@ -1,12 +1,16 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* This class is a provider for UK Met Office Datapoint, +/* + * This class is a provider for UK Met Office Datapoint, * see https://www.metoffice.gov.uk/ */ WeatherProvider.register("ukmetoffice", { - // Set the name of the provider. - // This isn't strictly necessary, since it will fallback to the provider identifier - // But for debugging (and future alerts) it would be nice to have the real name. + + /* + * Set the name of the provider. + * This isn't strictly necessary, since it will fallback to the provider identifier + * But for debugging (and future alerts) it would be nice to have the real name. + */ providerName: "UK Met Office", // Set the default config properties that is specific to this provider @@ -21,8 +25,11 @@ WeatherProvider.register("ukmetoffice", { this.fetchData(this.getUrl("3hourly")) .then((data) => { if (!data || !data.SiteRep || !data.SiteRep.DV || !data.SiteRep.DV.Location || !data.SiteRep.DV.Location.Period || data.SiteRep.DV.Location.Period.length === 0) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ return; } @@ -42,8 +49,11 @@ WeatherProvider.register("ukmetoffice", { this.fetchData(this.getUrl("daily")) .then((data) => { if (!data || !data.SiteRep || !data.SiteRep.DV || !data.SiteRep.DV.Location || !data.SiteRep.DV.Location.Period || data.SiteRep.DV.Location.Period.length === 0) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ return; } @@ -86,8 +96,11 @@ WeatherProvider.register("ukmetoffice", { if (periodDate.isSameOrAfter(moment.utc().startOf("day"))) { // check this is the period we want, after today the diff will be -ve if (moment().diff(periodDate, "minutes") > 0) { - // loop round the reports looking for the one we are in - // $ value specifies the time in minutes-of-the-day: 0, 180, 360,...1260 + + /* + * loop round the reports looking for the one we are in + * $ value specifies the time in minutes-of-the-day: 0, 180, 360,...1260 + */ for (const rep of period.Rep) { const p = rep.$; if (timeInMins >= p && timeInMins - 180 < p) { @@ -117,8 +130,10 @@ WeatherProvider.register("ukmetoffice", { generateWeatherObjectsFromForecast (forecasts) { const days = []; - // loop round the (5) periods getting the data - // for each period array, Day is [0], Night is [1] + /* + * loop round the (5) periods getting the data + * for each period array, Day is [0], Night is [1] + */ for (const period of forecasts.SiteRep.DV.Location.Period) { const weather = new WeatherObject(); diff --git a/modules/default/weather/providers/ukmetofficedatahub.js b/modules/default/weather/providers/ukmetofficedatahub.js index 33e33c50c6..0a9d872c5b 100644 --- a/modules/default/weather/providers/ukmetofficedatahub.js +++ b/modules/default/weather/providers/ukmetofficedatahub.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services). +/* + * This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services). * For more information on Data Hub, see https://www.metoffice.gov.uk/services/data/datapoint/notifications/weather-datahub * Data available: * Hourly data for next 2 days ("hourly") - https://www.metoffice.gov.uk/binaries/content/assets/metofficegovuk/pdf/data/global-spot-data-hourly.pdf @@ -54,9 +55,11 @@ WeatherProvider.register("ukmetofficedatahub", { return this.config.apiBase + (this.config.apiBase.endsWith("/") ? "" : "/") + forecastType + queryStrings; }, - // Build the list of headers for the request - // For DataHub requests, the API key/secret are sent in the headers rather than as query strings. - // Headers defined according to Data Hub API (https://datahub.metoffice.gov.uk/docs/f/category/site-specific/type/site-specific/api-documentation#get-/point/hourly) + /* + * Build the list of headers for the request + * For DataHub requests, the API key/secret are sent in the headers rather than as query strings. + * Headers defined according to Data Hub API (https://datahub.metoffice.gov.uk/docs/f/category/site-specific/type/site-specific/api-documentation#get-/point/hourly) + */ getHeaders () { return { accept: "application/json", @@ -78,8 +81,11 @@ WeatherProvider.register("ukmetofficedatahub", { .then((data) => { // Check data is usable if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ Log.error("Possibly bad current/hourly data?"); Log.error(data); return; @@ -127,15 +133,19 @@ WeatherProvider.register("ukmetofficedatahub", { currentWeather.precipitationProbability = forecastDataHours[hour].probOfPrecipitation; currentWeather.feelsLikeTemp = forecastDataHours[hour].feelsLikeTemperature; - // Pass on full details, so they can be used in custom templates - // Note the units of the supplied data when using this (see top of file) + /* + * Pass on full details, so they can be used in custom templates + * Note the units of the supplied data when using this (see top of file) + */ currentWeather.rawData = forecastDataHours[hour]; } } - // Determine the sunrise/sunset times - (still) not supplied in UK Met Office data - // Passes {longitude, latitude} to SunCalc, could pass height to, but - // SunCalc.getTimes doesn't take that into account + /* + * Determine the sunrise/sunset times - (still) not supplied in UK Met Office data + * Passes {longitude, latitude} to SunCalc, could pass height to, but + * SunCalc.getTimes doesn't take that into account + */ currentWeather.updateSunTime(this.config.lat, this.config.lon); return currentWeather; @@ -147,8 +157,11 @@ WeatherProvider.register("ukmetofficedatahub", { .then((data) => { // Check data is usable if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ Log.error("Possibly bad forecast data?"); Log.error(data); return; @@ -203,8 +216,10 @@ WeatherProvider.register("ukmetofficedatahub", { forecastWeather.snow = forecastDataDays[day].dayProbabilityOfSnow; forecastWeather.feelsLikeTemp = forecastDataDays[day].dayMaxFeelsLikeTemp; - // Pass on full details, so they can be used in custom templates - // Note the units of the supplied data when using this (see top of file) + /* + * Pass on full details, so they can be used in custom templates + * Note the units of the supplied data when using this (see top of file) + */ forecastWeather.rawData = forecastDataDays[day]; dailyForecasts.push(forecastWeather); @@ -219,9 +234,11 @@ WeatherProvider.register("ukmetofficedatahub", { this.fetchedLocationName = name; }, - // Match the Met Office "significant weather code" to a weathericons.css icon - // Use: https://metoffice.apiconnect.ibmcloud.com/metoffice/production/node/264 - // and: https://erikflowers.github.io/weather-icons/ + /* + * Match the Met Office "significant weather code" to a weathericons.css icon + * Use: https://metoffice.apiconnect.ibmcloud.com/metoffice/production/node/264 + * and: https://erikflowers.github.io/weather-icons/ + */ convertWeatherType (weatherType) { const weatherTypes = { 0: "night-clear", diff --git a/modules/default/weather/providers/weatherbit.js b/modules/default/weather/providers/weatherbit.js index 7c01f5d6be..a36b92bd86 100644 --- a/modules/default/weather/providers/weatherbit.js +++ b/modules/default/weather/providers/weatherbit.js @@ -1,11 +1,15 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Weatherbit, +/* + * This class is a provider for Weatherbit, * see https://www.weatherbit.io/ */ WeatherProvider.register("weatherbit", { - // Set the name of the provider. - // Not strictly required, but helps for debugging. + + /* + * Set the name of the provider. + * Not strictly required, but helps for debugging. + */ providerName: "Weatherbit", // Set the default config properties that is specific to this provider diff --git a/modules/default/weather/providers/weatherflow.js b/modules/default/weather/providers/weatherflow.js index 54066d7b40..6ffd5b669b 100644 --- a/modules/default/weather/providers/weatherflow.js +++ b/modules/default/weather/providers/weatherflow.js @@ -1,11 +1,15 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* This class is a provider for Weatherflow. +/* + * This class is a provider for Weatherflow. * Note that the Weatherflow API does not provide snowfall. */ WeatherProvider.register("weatherflow", { - // Set the name of the provider. - // Not strictly required, but helps for debugging + + /* + * Set the name of the provider. + * Not strictly required, but helps for debugging + */ providerName: "WeatherFlow", // Set the default config properties that is specific to this provider diff --git a/modules/default/weather/providers/weathergov.js b/modules/default/weather/providers/weathergov.js index 8a65478465..d8fa621a85 100644 --- a/modules/default/weather/providers/weathergov.js +++ b/modules/default/weather/providers/weathergov.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* Provider: weather.gov +/* + * Provider: weather.gov * https://weather-gov.github.io/api/general-faqs * * This class is a provider for weather.gov. @@ -9,9 +10,12 @@ */ WeatherProvider.register("weathergov", { - // Set the name of the provider. - // This isn't strictly necessary, since it will fallback to the provider identifier - // But for debugging (and future alerts) it would be nice to have the real name. + + /* + * Set the name of the provider. + * This isn't strictly necessary, since it will fallback to the provider identifier + * But for debugging (and future alerts) it would be nice to have the real name. + */ providerName: "Weather.gov", // Set the default config properties that is specific to this provider @@ -98,8 +102,11 @@ WeatherProvider.register("weathergov", { this.fetchData(this.forecastHourlyURL) .then((data) => { if (!data) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ return; } const hourly = this.generateWeatherObjectsFromHourly(data.properties.periods); @@ -282,14 +289,18 @@ WeatherProvider.register("weathergov", { weather.weatherType = this.convertWeatherType(forecast.shortForecast, forecast.isDaytime); } - // the same day as before - // add values from forecast to corresponding variables + /* + * the same day as before + * add values from forecast to corresponding variables + */ minTemp.push(forecast.temperature); maxTemp.push(forecast.temperature); } - // last day - // calculate minimum/maximum temperature + /* + * last day + * calculate minimum/maximum temperature + */ weather.minTemperature = Math.min.apply(null, minTemp); weather.maxTemperature = Math.max.apply(null, maxTemp); @@ -302,8 +313,11 @@ WeatherProvider.register("weathergov", { * Convert the icons to a more usable name. */ convertWeatherType (weatherType, isDaytime) { - //https://w1.weather.gov/xml/current_obs/weather.php - // There are way too many types to create, so lets just look for certain strings + + /* + * https://w1.weather.gov/xml/current_obs/weather.php + * There are way too many types to create, so lets just look for certain strings + */ if (weatherType.includes("Cloudy") || weatherType.includes("Partly")) { if (isDaytime) { diff --git a/modules/default/weather/providers/yr.js b/modules/default/weather/providers/yr.js index 35493a1653..f305a1c09d 100644 --- a/modules/default/weather/providers/yr.js +++ b/modules/default/weather/providers/yr.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Yr.no, a norwegian weather service. +/* + * This class is a provider for Yr.no, a norwegian weather service. * Terms of service: https://developer.yr.no/doc/TermsOfService/ */ WeatherProvider.register("yr", { @@ -67,8 +68,11 @@ WeatherProvider.register("yr", { getWeatherData () { return new Promise((resolve, reject) => { - // If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. - // This is to avoid multiple similar calls to the API. + + /* + * If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. + * This is to avoid multiple similar calls to the API. + */ let shouldWait = localStorage.getItem("yrIsFetchingWeatherData"); if (shouldWait) { const checkForGo = setInterval(function () { @@ -201,8 +205,11 @@ WeatherProvider.register("yr", { }, getStellarData () { - // If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. - // This is to avoid multiple similar calls to the API. + + /* + * If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. + * This is to avoid multiple similar calls to the API. + */ return new Promise((resolve, reject) => { let shouldWait = localStorage.getItem("yrIsFetchingStellarData"); if (shouldWait) { diff --git a/package-lock.json b/package-lock.json index dfa0d6d8ee..14bb1e1607 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,21 +27,21 @@ "pm2": "^5.4.2", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.23.2" + "systeminformation": "^5.23.4" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.8.1", + "@stylistic/eslint-plugin": "^2.6.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.10.2", + "eslint-plugin-jest": "^28.8.0", + "eslint-plugin-jsdoc": "^50.0.0", "eslint-plugin-package-json": "^0.15.2", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.4", "jest": "^29.7.0", "jsdom": "^24.1.1", - "lint-staged": "^15.2.7", - "playwright": "^1.45.3", + "lint-staged": "^15.2.8", + "playwright": "^1.46.0", "prettier": "^3.3.3", "sinon": "^18.0.0", "stylelint": "^16.8.1", @@ -1850,91 +1850,114 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.8.1.tgz", - "integrity": "sha512-64My6I7uCcmSQ//427Pfg2vjSf9SDzfsGIWohNFgISMLYdC5BzJqDo647iDDJzSxINh3WTC0Ql46ifiKuOoTyA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.6.2.tgz", + "integrity": "sha512-Ic5oFNM/25iuagob6LiIBkSI/A2y45TsyKtDtODXHRZDy52WfPfeexI6r+OH5+aWN9QGob2Bw+4JRM9/4areWw==", "dev": true, - "license": "MIT", "dependencies": { - "@stylistic/eslint-plugin-js": "1.8.1", - "@stylistic/eslint-plugin-jsx": "1.8.1", - "@stylistic/eslint-plugin-plus": "1.8.1", - "@stylistic/eslint-plugin-ts": "1.8.1", - "@types/eslint": "^8.56.10" + "@stylistic/eslint-plugin-js": "2.6.2", + "@stylistic/eslint-plugin-jsx": "2.6.2", + "@stylistic/eslint-plugin-plus": "2.6.2", + "@stylistic/eslint-plugin-ts": "2.6.2", + "@types/eslint": "^9.6.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.1.tgz", - "integrity": "sha512-c5c2C8Mos5tTQd+NWpqwEu7VT6SSRooAguFPMj1cp2RkTYl1ynKoXo8MWy3k4rkbzoeYHrqC2UlUzsroAN7wtQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.6.2.tgz", + "integrity": "sha512-wCr/kVctAPayMU3pcOI1MKR7MoKIh6VKZU89lPklAqtJoxT+Em6RueiiARbpznUYG5eg3LymiU+aMD+aIZXdqA==", "dev": true, - "license": "MIT", "dependencies": { - "@types/eslint": "^8.56.10", - "acorn": "^8.11.3", - "escape-string-regexp": "^4.0.0", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1" + "@types/eslint": "^9.6.0", + "acorn": "^8.12.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, + "node_modules/@stylistic/eslint-plugin-js/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/eslint-plugin-js/node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.8.1.tgz", - "integrity": "sha512-k1Eb6rcjMP+mmjvj+vd9y5KUdWn1OBkkPLHXhsrHt5lCDFZxJEs0aVQzE5lpYrtVZVkpc5esTtss/cPJux0lfA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.6.2.tgz", + "integrity": "sha512-dSXK/fSPA938J1fBi10QmhzLKtZ/2TuyVNHQMk8jUhWfKJDleAogaSqcWNAbN8fwcoe9UWmt/3StiIf2oYC1aQ==", "dev": true, - "license": "MIT", "dependencies": { - "@stylistic/eslint-plugin-js": "^1.8.1", - "@types/eslint": "^8.56.10", + "@stylistic/eslint-plugin-js": "^2.6.2", + "@types/eslint": "^9.6.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.8.1.tgz", - "integrity": "sha512-4+40H3lHYTN8OWz+US8CamVkO+2hxNLp9+CAjorI7top/lHqemhpJvKA1LD9Uh+WMY9DYWiWpL2+SZ2wAXY9fQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.6.2.tgz", + "integrity": "sha512-cANcPASfRvq3VTbbQCrSIXq+2AI0IW68PNYaZoXXS0ENlp7HDB8dmrsJnOgWCcoEvdCB8z/eWcG/eq/v5Qcl+Q==", "dev": true, - "license": "MIT", "dependencies": { - "@types/eslint": "^8.56.10", - "@typescript-eslint/utils": "^6.21.0" + "@types/eslint": "^9.6.0", + "@typescript-eslint/utils": "^8.0.0" }, "peerDependencies": { "eslint": "*" } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.8.1.tgz", - "integrity": "sha512-/q1m+ZuO1JHfiSF16EATFzv7XSJkc5W6DocfvH5o9oB6WWYFMF77fVoBWnKT3wGptPOc2hkRupRKhmeFROdfWA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.6.2.tgz", + "integrity": "sha512-6OEN3VtUNxjgOvWPavnC10MByr1H4zsgwNND3rQXr5lDFv93MLUnTsH+/SH15OkuqdyJgrQILI6b9lYecb1vIg==", "dev": true, - "license": "MIT", "dependencies": { - "@stylistic/eslint-plugin-js": "1.8.1", - "@types/eslint": "^8.56.10", - "@typescript-eslint/utils": "^6.21.0" + "@stylistic/eslint-plugin-js": "2.6.2", + "@types/eslint": "^9.6.0", + "@typescript-eslint/utils": "^8.0.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { "eslint": ">=8.40.0" @@ -2033,11 +2056,10 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", "dev": true, - "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2047,8 +2069,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/glob": { "version": "7.2.0", @@ -2162,13 +2183,6 @@ "@types/node": "*" } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -2204,17 +2218,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", + "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2222,13 +2235,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", + "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", "dev": true, - "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2236,23 +2248,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", + "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2265,43 +2276,38 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.1.tgz", + "integrity": "sha512-CBFR0G0sCt0+fzfnKaciu9IBsKvEKYwN9UZ+eeogK1fYHg4Qxk1yf/wLQkLXlq8wbU2dFlgAesxt8Gi76E8RTA==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/typescript-estree": "8.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", + "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.0.1", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2328,10 +2334,9 @@ } }, "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", - "license": "MIT", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { "acorn": "bin/acorn" }, @@ -2967,7 +2972,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -3279,16 +3283,15 @@ } }, "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, - "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3323,7 +3326,6 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, - "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" @@ -3460,8 +3462,7 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/combined-stream": { "version": "1.0.8", @@ -4145,8 +4146,7 @@ "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/encodeurl": { "version": "1.0.2", @@ -4240,6 +4240,18 @@ "node": ">=6" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/envsub": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/envsub/-/envsub-4.1.0.tgz", @@ -4674,19 +4686,18 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", - "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", + "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "engines": { "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0", "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "jest": "*" }, @@ -4700,9 +4711,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.10.2.tgz", - "integrity": "sha512-xTkf/MmEeVrTbezc6kDqCJmK9RcseIKo8X4oyoDCMvV4LY8dqrQi8kmfRrv9n0gNBkCclevaOh2Lkmu6Fs8SLg==", + "version": "50.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.0.0.tgz", + "integrity": "sha512-czyJ5F7/qY2LIhUD5Bl6q1CCZ8mjvfEA9HQN5nvIp/Pb8VLIlUNd+DMZdA2OKN74QQMS3pobC06hFqAOJyOv5Q==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.46.0", @@ -4982,8 +4993,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/execa": { "version": "5.1.1", @@ -5534,7 +5544,6 @@ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -6479,7 +6488,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7692,22 +7700,21 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.7", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz", - "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==", + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.8.tgz", + "integrity": "sha512-PUWFf2zQzsd9EFU+kM1d7UP+AZDbKFKuj+9JNVTBkhUFhbg4MAt6WfyMMwBfM4lYqd4D2Jwac5iuTu9rVj4zCQ==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "~5.3.0", "commander": "~12.1.0", - "debug": "~4.3.4", + "debug": "~4.3.6", "execa": "~8.0.1", - "lilconfig": "~3.1.1", - "listr2": "~8.2.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", "micromatch": "~4.0.7", "pidtree": "~0.6.0", "string-argv": "~0.3.2", - "yaml": "~2.4.2" + "yaml": "~2.5.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -7887,16 +7894,15 @@ } }, "node_modules/listr2": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz", - "integrity": "sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", + "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", "dev": true, - "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", + "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" }, @@ -7946,15 +7952,14 @@ "license": "MIT" }, "node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -7966,13 +7971,15 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, - "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7983,7 +7990,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7996,7 +8002,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -8009,7 +8014,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, - "license": "MIT", "dependencies": { "get-east-asian-width": "^1.0.0" }, @@ -8025,7 +8029,6 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -8042,7 +8045,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -8254,6 +8256,18 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -8275,11 +8289,10 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -9017,7 +9030,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -9130,12 +9142,12 @@ } }, "node_modules/playwright": { - "version": "1.45.3", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.3.tgz", - "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", + "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", "dev": true, "dependencies": { - "playwright-core": "1.45.3" + "playwright-core": "1.46.0" }, "bin": { "playwright": "cli.js" @@ -9148,9 +9160,9 @@ } }, "node_modules/playwright-core": { - "version": "1.45.3", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.3.tgz", - "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", + "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -10051,22 +10063,48 @@ } }, "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, - "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -10081,8 +10119,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/rimraf": { "version": "3.0.2", @@ -10537,7 +10574,6 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -10554,7 +10590,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -10826,11 +10861,10 @@ } }, "node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -10848,7 +10882,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -10861,7 +10894,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -11369,9 +11401,9 @@ "dev": true }, "node_modules/systeminformation": { - "version": "5.23.2", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.2.tgz", - "integrity": "sha512-FoipTSwzZR68ZAjXZ8DRH2DFEErMAOi9JvRMsn6i/hTp6Hd4W4nM1W6a+kUyMrp/pd1SIuUzUZvvkQ21yE6Dig==", + "version": "5.23.4", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.4.tgz", + "integrity": "sha512-mD2R9xnOzKOOmIVtxekosf/ghOE/DGLqAPmsEgQMWJK0pMKxBtX19riz1Ss0tN4omcfS2FQ2RDJ4lkxgADxIPw==", "os": [ "darwin", "linux", @@ -11587,7 +11619,6 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=16" }, @@ -12152,7 +12183,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -12170,7 +12200,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -12183,7 +12212,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -12196,7 +12224,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -12283,11 +12310,10 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", "dev": true, - "license": "ISC", "bin": { "yaml": "bin.mjs" }, diff --git a/package.json b/package.json index 3048aefaf7..b0eb77e937 100644 --- a/package.json +++ b/package.json @@ -71,21 +71,21 @@ "pm2": "^5.4.2", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.23.2" + "systeminformation": "^5.23.4" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.8.1", + "@stylistic/eslint-plugin": "^2.6.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.10.2", + "eslint-plugin-jest": "^28.8.0", + "eslint-plugin-jsdoc": "^50.0.0", "eslint-plugin-package-json": "^0.15.2", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.4", "jest": "^29.7.0", "jsdom": "^24.1.1", - "lint-staged": "^15.2.7", - "playwright": "^1.45.3", + "lint-staged": "^15.2.8", + "playwright": "^1.46.0", "prettier": "^3.3.3", "sinon": "^18.0.0", "stylelint": "^16.8.1", diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js index 608c71da96..fb431ad7e6 100644 --- a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js index 6128c97f50..b6ea3011dc 100644 --- a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_la_before_midnight.js b/tests/configs/modules/calendar/exdate_la_before_midnight.js index 8c886f775a..e5518df797 100644 --- a/tests/configs/modules/calendar/exdate_la_before_midnight.js +++ b/tests/configs/modules/calendar/exdate_la_before_midnight.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js index f98b75f4c7..e6287e2b02 100644 --- a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js index 06c7ff5319..9000387998 100644 --- a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_syd_before_midnight.js b/tests/configs/modules/calendar/exdate_syd_before_midnight.js index 849c1f5363..3b176329ec 100644 --- a/tests/configs/modules/calendar/exdate_syd_before_midnight.js +++ b/tests/configs/modules/calendar/exdate_syd_before_midnight.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/long-fullday-event.js b/tests/configs/modules/calendar/long-fullday-event.js index efbc244886..80137810d8 100644 --- a/tests/configs/modules/calendar/long-fullday-event.js +++ b/tests/configs/modules/calendar/long-fullday-event.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test config for fullday calendar entries over multiple days +/* + * MagicMirror² Test config for fullday calendar entries over multiple days * * By Paranoid93 https://github.com/Paranoid93/ * MIT Licensed. diff --git a/tests/configs/modules/calendar/single-fullday-event.js b/tests/configs/modules/calendar/single-fullday-event.js index 9149d2d9ab..7dae36115f 100644 --- a/tests/configs/modules/calendar/single-fullday-event.js +++ b/tests/configs/modules/calendar/single-fullday-event.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test config for fullday calendar entries over multiple days +/* + * MagicMirror² Test config for fullday calendar entries over multiple days * * By Paranoid93 https://github.com/Paranoid93/ * MIT Licensed. diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 4e6aee17a2..bf10ecd752 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -44,9 +44,10 @@ describe("Calendar module", () => { }); }); - /****************************/ - // RRULE TESTS: - // Add any tests that check rrule functionality here. + /* + * RRULE TESTS: + * Add any tests that check rrule functionality here. + */ describe("rrule", () => { it("Issue #3393 recurrence dates past rrule until date", async () => { await helpers.startApplication("tests/configs/modules/calendar/rrule_until.js", "07 Mar 2024 10:38:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); @@ -60,15 +61,16 @@ describe("Calendar module", () => { }); }); - /****************************/ - // LOS ANGELES TESTS: - // In 2023, DST (GMT-7) was until 5 Nov, after which is standard (STD) (GMT-8) time. - // Test takes place on Thu 19 Oct, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be - // 4 events (25 Oct, 1 Nov, (switch to STD), 8 Nov, Nov 15), but 1 Nov and 8 Nov are excluded. - // There are three separate tests: - // * before midnight GMT (3pm local time) - // * at midnight GMT in STD time (4pm local time) - // * at midnight GMT in DST time (5pm local time) + /* + * LOS ANGELES TESTS: + * In 2023, DST (GMT-7) was until 5 Nov, after which is standard (STD) (GMT-8) time. + * Test takes place on Thu 19 Oct, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be + * 4 events (25 Oct, 1 Nov, (switch to STD), 8 Nov, Nov 15), but 1 Nov and 8 Nov are excluded. + * There are three separate tests: + * * before midnight GMT (3pm local time) + * * at midnight GMT in STD time (4pm local time) + * * at midnight GMT in DST time (5pm local time) + */ describe("Exdate: LA crossover DST before midnight GMT", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_la_before_midnight.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); @@ -107,15 +109,16 @@ describe("Calendar module", () => { }); }); - /****************************/ - // SYDNEY TESTS: - // In 2023, standard time (STD) (GMT+10) was until 1 Oct, after which is DST (GMT+11). - // Test takes place on Thu 14 Sep, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be - // 4 events (20 Sep, 27 Sep, (switch to DST), 4 Oct, 11 Oct), but 27 Sep and 4 Oct are excluded. - // There are three separate tests: - // * before midnight GMT (9am local time) - // * at midnight GMT in STD time (10am local time) - // * at midnight GMT in DST time (11am local time) + /* + * SYDNEY TESTS: + * In 2023, standard time (STD) (GMT+10) was until 1 Oct, after which is DST (GMT+11). + * Test takes place on Thu 14 Sep, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be + * 4 events (20 Sep, 27 Sep, (switch to DST), 4 Oct, 11 Oct), but 27 Sep and 4 Oct are excluded. + * There are three separate tests: + * * before midnight GMT (9am local time) + * * at midnight GMT in STD time (10am local time) + * * at midnight GMT in DST time (11am local time) + */ describe("Exdate: SYD crossover DST before midnight GMT", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_before_midnight.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); From cc1d4ab240bd954990902495080643fb580453d5 Mon Sep 17 00:00:00 2001 From: Ryan Williams <65094007+ryan-d-williams@users.noreply.github.com> Date: Sun, 18 Aug 2024 03:25:01 -0400 Subject: [PATCH 087/418] Improve duplicate module filtering. Update SocketIO catch-all API. (#3523) - [x] Base your pull requests against the `develop` branch. - [x] Include these infos in the description: > - Does the pull request solve a **related** issue? Yes - solves #3521 > - If so, can you reference the issue like this `Fixes #`? Fixes #3521 (also mentioned in commit message) > - What does the pull request accomplish? Use a list if needed. > > - Updates duplicate module filter method (upstream vs downstream - see #3502) > > - Updates socket io catchall functionality to new API [[docs](https://socket.io/docs/v4/listening-to-events/)]. - [x] Please run `npm run lint:prettier` before submitting - [x] Don't forget to add an entry about your changes to the CHANGELOG.md file. --- CHANGELOG.md | 1 + js/app.js | 30 ++++++++++++------------------ js/node_helper.js | 15 ++------------- 3 files changed, 15 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a41be65c64..7c583b94ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) - [core] Updated dependencies including stylistic-eslint - [core] Allow custom module positions by setting `allowCustomModulePositions` in `config.js` (fixes #3504, related to https://github.com/MagicMirrorOrg/MagicMirror/pull/3445) +- [core] Updated SocketIO catch all to new API ### Fixed diff --git a/js/app.js b/js/app.js index 7792750c48..e18ff589da 100644 --- a/js/app.js +++ b/js/app.js @@ -9,7 +9,6 @@ const Log = require("logger"); const Server = require(`${__dirname}/server`); const Utils = require(`${__dirname}/utils`); const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`); -const helperhash = {}; // Get version number. global.version = require(`${__dirname}/../package.json`).version; @@ -176,23 +175,15 @@ function App () { const helperPath = `${moduleFolder}/node_helper.js`; - // find out if helper was loaded before for this module - // only load it once - let loadHelper = helperhash[moduleName] ? false : true; - - // if this is the 1st time for this module, check for helper file - // otherwise, its already loaded, if found - if (loadHelper) { - try { - fs.accessSync(helperPath, fs.R_OK); - // indicte we found one to load for this module - helperhash[moduleName] = true; - } catch (e) { - loadHelper = false; - Log.log(`No helper found for module: ${moduleName}.`); - } + let loadHelper = true; + try { + fs.accessSync(helperPath, fs.R_OK); + } catch (e) { + loadHelper = false; + Log.log(`No helper found for module: ${moduleName}.`); } - // if the helper was found, AND needed 1st time + + // if the helper was found if (loadHelper) { const Module = require(helperPath); let m = new Module(); @@ -270,7 +261,10 @@ function App () { if (module.disabled) continue; if (module.module) { if (Utils.moduleHasValidPosition(module.position) || typeof (module.position) === "undefined") { - modules.push(module.module); + // Only add this module to be loaded if it is not a duplicate (repeated instance of the same module) + if (!modules.includes(module.module)) { + modules.push(module.module); + } } else { Log.warn("Invalid module position found for this configuration:", module); } diff --git a/js/node_helper.js b/js/node_helper.js index dd272c4e0f..e1ecf632b5 100644 --- a/js/node_helper.js +++ b/js/node_helper.js @@ -86,20 +86,9 @@ const NodeHelper = Class.extend({ Log.log(`Connecting socket for: ${this.name}`); io.of(this.name).on("connection", (socket) => { - // add a catch all event. - const onevent = socket.onevent; - socket.onevent = function (packet) { - const args = packet.data || []; - onevent.call(this, packet); // original call - packet.data = ["*"].concat(args); - onevent.call(this, packet); // additional call to catch-all - }; - // register catch all. - socket.on("*", (notification, payload) => { - if (notification !== "*") { - this.socketNotificationReceived(notification, payload); - } + socket.onAny((notification, payload) => { + this.socketNotificationReceived(notification, payload); }); }); } From 56736786fd3d2c0f5112eb2a82102f38a7f908c3 Mon Sep 17 00:00:00 2001 From: Panagiotis Skias Date: Sun, 18 Aug 2024 11:04:51 +0300 Subject: [PATCH 088/418] Bug in Weather Units for Broadcasted Notification (#3519) This PR resolve Issue number #3419 . I have added the method `convertWeatherObjectToImperial()` which converts the units of the `notificationPayload` to imperial if needed, in order to pass the object in `sendNotification()`. --------- Co-authored-by: veeck --- CHANGELOG.md | 1 + modules/default/weather/weather.js | 13 ++++++--- modules/default/weather/weatherutils.js | 36 +++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c583b94ab..9db5f2669a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ _This release is scheduled to be released on 2024-10-01._ - Fixed `checks` badge in README.md - [weather] Fixed issue with the UK Met Office provider following a change in their API paths and header info. - [core] add check for node_helper loading for multiple instances of same module (#3502) +- [weather] Fixed issue for respecting unit config on broadcasted notifications ## [2.28.0] - 2024-07-01 diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index 224aba0647..369a720101 100644 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -170,12 +170,19 @@ Module.register("weather", { } const notificationPayload = { - currentWeather: this.weatherProvider?.currentWeatherObject?.simpleClone() ?? null, - forecastArray: this.weatherProvider?.weatherForecastArray?.map((ar) => ar.simpleClone()) ?? [], - hourlyArray: this.weatherProvider?.weatherHourlyArray?.map((ar) => ar.simpleClone()) ?? [], + currentWeather: this.config.units === "imperial" + ? WeatherUtils.convertWeatherObjectToImperial(this.weatherProvider?.currentWeatherObject?.simpleClone()) ?? null + : this.weatherProvider?.currentWeatherObject?.simpleClone() ?? null, + forecastArray: this.config.units === "imperial" + ? this.weatherProvider?.weatherForecastArray?.map((ar) => WeatherUtils.convertWeatherObjectToImperial(ar.simpleClone())) ?? [] + : this.weatherProvider?.weatherForecastArray?.map((ar) => ar.simpleClone()) ?? [], + hourlyArray: this.config.units === "imperial" + ? this.weatherProvider?.weatherHourlyArray?.map((ar) => WeatherUtils.convertWeatherObjectToImperial(ar.simpleClone())) ?? [] + : this.weatherProvider?.weatherHourlyArray?.map((ar) => ar.simpleClone()) ?? [], locationName: this.weatherProvider?.fetchedLocationName, providerName: this.weatherProvider.providerName }; + this.sendNotification("WEATHER_UPDATED", notificationPayload); }, diff --git a/modules/default/weather/weatherutils.js b/modules/default/weather/weatherutils.js index e75baf20f7..4d6ce45bf9 100644 --- a/modules/default/weather/weatherutils.js +++ b/modules/default/weather/weatherutils.js @@ -30,8 +30,7 @@ const WeatherUtils = { let convertedValue = value; let conversionUnit = valueUnit; if (outputUnit === "imperial") { - if (valueUnit && valueUnit.toLowerCase() === "cm") convertedValue = convertedValue * 0.3937007874; - else convertedValue = convertedValue * 0.03937007874; + convertedValue = this.convertPrecipitationToInch(value, valueUnit); conversionUnit = "in"; } else { conversionUnit = valueUnit ? valueUnit : "mm"; @@ -40,6 +39,17 @@ const WeatherUtils = { return `${convertedValue.toFixed(2)} ${conversionUnit}`; }, + /** + * Convert precipitation value into inch + * @param {number} value the precipitation value for convert + * @param {string} valueUnit can be 'mm' or 'cm' + * @returns {number} the converted precipitation value + */ + convertPrecipitationToInch (value, valueUnit) { + if (valueUnit && valueUnit.toLowerCase() === "cm") return value * 0.3937007874; + else return value * 0.03937007874; + }, + /** * Convert temp (from degrees C) into imperial or metric unit depending on * your config @@ -129,6 +139,28 @@ const WeatherUtils = { } return ((feelsLike - 32) * 5) / 9; + }, + + /** + * Converts the Weather Object's values into imperial unit + * @param {object} weatherObject the weather object + * @returns {object} the weather object with converted values to imperial + */ + convertWeatherObjectToImperial (weatherObject) { + if (!weatherObject || Object.keys(weatherObject).length === 0) return null; + + let imperialWeatherObject = { ...weatherObject }; + + if (imperialWeatherObject) { + if (imperialWeatherObject.feelsLikeTemp) imperialWeatherObject.feelsLikeTemp = this.convertTemp(imperialWeatherObject.feelsLikeTemp, "imperial"); + if (imperialWeatherObject.maxTemperature) imperialWeatherObject.maxTemperature = this.convertTemp(imperialWeatherObject.maxTemperature, "imperial"); + if (imperialWeatherObject.minTemperature) imperialWeatherObject.minTemperature = this.convertTemp(imperialWeatherObject.minTemperature, "imperial"); + if (imperialWeatherObject.precipitationAmount) imperialWeatherObject.precipitationAmount = this.convertPrecipitationToInch(imperialWeatherObject.precipitationAmount, imperialWeatherObject.precipitationUnits); + if (imperialWeatherObject.temperature) imperialWeatherObject.temperature = this.convertTemp(imperialWeatherObject.temperature, "imperial"); + if (imperialWeatherObject.windSpeed) imperialWeatherObject.windSpeed = this.convertWind(imperialWeatherObject.windSpeed, "imperial"); + } + + return imperialWeatherObject; } }; From 2b97e0d26ee925688031097f1d928c1f37f62cb0 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Tue, 27 Aug 2024 15:52:59 -0500 Subject: [PATCH 089/418] add support for custom regions, by detecting what is used in index.html (#3518) read index.html to discover the regions used, make them the list checked by app.js and check:config test fixes #3504 supercedes #3506 no config.js param required --- CHANGELOG.md | 2 +- index.html | 1 + js/app.js | 7 ++- js/check_config.js | 22 +++------- js/defaults.js | 1 - js/loader.js | 2 +- js/main.js | 3 +- js/utils.js | 35 +++++++++++++-- tests/configs/customregions.js | 23 ++++++++++ tests/e2e/custom_module_regions_spec.js | 30 +++++++++++++ tests/e2e/helpers/global-setup.js | 57 ++++++++++++++++++++++++- 11 files changed, 154 insertions(+), 29 deletions(-) create mode 100644 tests/configs/customregions.js create mode 100644 tests/e2e/custom_module_regions_spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 9db5f2669a..c06146ae71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,8 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) - [core] Updated dependencies including stylistic-eslint -- [core] Allow custom module positions by setting `allowCustomModulePositions` in `config.js` (fixes #3504, related to https://github.com/MagicMirrorOrg/MagicMirror/pull/3445) - [core] Updated SocketIO catch all to new API +- [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded(fixes #3504) ### Fixed diff --git a/index.html b/index.html index b97124be10..09addfe37f 100644 --- a/index.html +++ b/index.html @@ -55,6 +55,7 @@ + diff --git a/js/app.js b/js/app.js index e18ff589da..f6d510a64a 100644 --- a/js/app.js +++ b/js/app.js @@ -256,6 +256,9 @@ function App () { Log.setLogLevel(config.logLevel); + // get the used module positions + Utils.getModulePositions(); + let modules = []; for (const module of config.modules) { if (module.disabled) continue; @@ -266,10 +269,10 @@ function App () { modules.push(module.module); } } else { - Log.warn("Invalid module position found for this configuration:", module); + Log.warn("Invalid module position found for this configuration:" + `\n${JSON.stringify(module, null, 2)}`); } } else { - Log.warn("No module name found for this configuration:", module); + Log.warn("No module name found for this configuration:" + `\n${JSON.stringify(module, null, 2)}`); } } diff --git a/js/check_config.js b/js/check_config.js index 6a514de3eb..2df47b7df8 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -11,6 +11,7 @@ const ajv = new Ajv(); const rootPath = path.resolve(`${__dirname}/../`); const Log = require(`${rootPath}/js/logger.js`); +const Utils = require(`${rootPath}/js/utils.js`); /** * Returns a string with path of configuration file. @@ -68,6 +69,7 @@ function checkConfigFile () { Log.info("Checking modules structure configuration... "); + const position_list = Utils.getModulePositions(); // Make Ajv schema confguration of modules config // only scan "module" and "position" const schema = { @@ -83,21 +85,7 @@ function checkConfigFile () { }, position: { type: "string", - enum: [ - "top_bar", - "top_left", - "top_center", - "top_right", - "upper_third", - "middle_center", - "lower_third", - "bottom_left", - "bottom_center", - "bottom_right", - "bottom_bar", - "fullscreen_above", - "fullscreen_below" - ] + enum: position_list } }, required: ["module"] @@ -116,10 +104,10 @@ function checkConfigFile () { let position = validate.errors[0].instancePath.split("/")[3]; Log.error(colors.red("This module configuration contains errors:")); - Log.error(data.modules[module]); + Log.error(`\n${JSON.stringify(data.modules[module], null, 2)}`); if (position) { Log.error(colors.red(`${position}: ${validate.errors[0].message}`)); - Log.error(validate.errors[0].params.allowedValues); + Log.error(`\n${JSON.stringify(validate.errors[0].params.allowedValues, null, 2).slice(1, -1)}`); } else { Log.error(colors.red(validate.errors[0].message)); } diff --git a/js/defaults.js b/js/defaults.js index 1cbef63566..c4efa77e95 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -27,7 +27,6 @@ const defaults = { // (interval 30 seconds). If startup-timestamp has changed the client reloads the magicmirror webpage. checkServerInterval: 30 * 1000, reloadAfterServerRestart: false, - allowCustomModulePositions: false, modules: [ { diff --git a/js/loader.js b/js/loader.js index 1ce6f27bd1..e8dff1907c 100644 --- a/js/loader.js +++ b/js/loader.js @@ -50,7 +50,7 @@ const Loader = (function () { * @returns {object[]} module data as configured in config */ const getAllModules = function () { - const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined" || config.allowCustomModulePositions)); + const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined")); return AllModules; }; diff --git a/js/main.js b/js/main.js index bc69f0bb93..e50a67f0fc 100644 --- a/js/main.js +++ b/js/main.js @@ -1,4 +1,4 @@ -/* global Loader, defaults, Translator, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut */ +/* global Loader, defaults, Translator, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut, modulePositions */ const MM = (function () { let modules = []; @@ -450,7 +450,6 @@ const MM = (function () { * an ugly top margin. By using this function, the top bar will be hidden if the * update notification is not visible. */ - const modulePositions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"]; const updateWrapperStates = function () { modulePositions.forEach(function (position) { diff --git a/js/utils.js b/js/utils.js index df2e91757d..a8211a3a7b 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,7 +1,17 @@ const execSync = require("node:child_process").execSync; -const Log = require("logger"); +const path = require("node:path"); + +const rootPath = path.resolve(`${__dirname}/../`); +const Log = require(`${rootPath}/js/logger.js`); +const os = require("node:os"); +const fs = require("node:fs"); const si = require("systeminformation"); +const modulePositions = []; // will get list from index.html +const regionRegEx = /"region ([^"]*)/i; +const indexFileName = "index.html"; +const discoveredPositionsJSFilename = "js/positions.js"; + module.exports = { async logSystemInformation () { @@ -29,13 +39,32 @@ module.exports = { // return all available module positions getAvailableModulePositions () { - return ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"]; + return modulePositions; }, // return if postion is on modulePositions Array (true/false) moduleHasValidPosition (position) { - if (config.allowCustomModulePositions) return true; if (this.getAvailableModulePositions().indexOf(position) === -1) return false; return true; + }, + + getModulePositions () { + // get the lines of the index.html + const lines = fs.readFileSync(indexFileName).toString().split(os.EOL); + // loop thru the lines + lines.forEach((line) => { + // run the regex on each line + const results = regionRegEx.exec(line); + // if the regex returned something + if (results && results.length > 0) { + // get the postition parts and replace space with underscore + const positionName = results[1].replace(" ", "_"); + // add it to the list + modulePositions.push(positionName); + } + }); + fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`); + // return the list to the caller + return modulePositions; } }; diff --git a/tests/configs/customregions.js b/tests/configs/customregions.js new file mode 100644 index 0000000000..5fe4ee28c4 --- /dev/null +++ b/tests/configs/customregions.js @@ -0,0 +1,23 @@ +let config = { + modules: + // Using exotic content. This is why don't accept go to JSON configuration file + (() => { + let positions = ["row3_left", "top3_left1"]; + let modules = Array(); + for (let idx in positions) { + modules.push({ + module: "helloworld", + position: positions[idx], + config: { + text: `Text in ${positions[idx]}` + } + }); + } + return modules; + })() +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/e2e/custom_module_regions_spec.js b/tests/e2e/custom_module_regions_spec.js new file mode 100644 index 0000000000..48d09712da --- /dev/null +++ b/tests/e2e/custom_module_regions_spec.js @@ -0,0 +1,30 @@ +const helpers = require("./helpers/global-setup"); + +describe("Custom Position of modules", () => { + beforeAll(async () => { + await helpers.fixupIndex(); + await helpers.startApplication("tests/configs/customregions.js"); + await helpers.getDocument(); + }); + afterAll(async () => { + await helpers.stopApplication(); + await helpers.restoreIndex(); + }); + + const positions = ["row3_left", "top3_left1"]; + let i = 0; + const className1 = positions[i].replace("_", "."); + let message1 = positions[i]; + it(`should show text in ${message1}`, async () => { + const elem = await helpers.waitForElement(`.${className1}`); + expect(elem).not.toBeNull(); + expect(elem.textContent).toContain(`Text in ${message1}`); + }); + i = 1; + const className2 = positions[i].replace("_", "."); + let message2 = positions[i]; + it(`should NOT show text in ${message2}`, async () => { + const elem = await helpers.waitForElement(`.${className2}`, "", 1500); + expect(elem).toBeNull(); + }, 1510); +}); diff --git a/tests/e2e/helpers/global-setup.js b/tests/e2e/helpers/global-setup.js index 31a3e036c2..ef90c0fdd9 100644 --- a/tests/e2e/helpers/global-setup.js +++ b/tests/e2e/helpers/global-setup.js @@ -1,5 +1,20 @@ +const os = require("node:os"); +const fs = require("node:fs"); const jsdom = require("jsdom"); +const indexFile = `${__dirname}/../../../index.html`; +const cssFile = `${__dirname}/../../../css/custom.css`; +const sampleCss = [ + ".region.row3 {", + " top: 0;", + "}", + ".region.row3.left {", + " top: 100%;", + "}" +]; +var indexData = []; +var cssData = []; + exports.startApplication = async (configFilename, exec) => { jest.resetModules(); if (global.app) { @@ -45,11 +60,12 @@ exports.getDocument = () => { }); }; -exports.waitForElement = (selector, ignoreValue = "") => { +exports.waitForElement = (selector, ignoreValue = "", timeout = 0) => { return new Promise((resolve) => { let oldVal = "dummy12345"; + let element = null; const interval = setInterval(() => { - const element = document.querySelector(selector); + element = document.querySelector(selector); if (element) { let newVal = element.textContent; if (newVal === oldVal) { @@ -64,6 +80,12 @@ exports.waitForElement = (selector, ignoreValue = "") => { } } }, 100); + if (timeout !== 0) { + setTimeout(() => { + if (interval) clearInterval(interval); + resolve(null); + }, timeout); + } }); }; @@ -91,3 +113,34 @@ exports.testMatch = async (element, regex) => { expect(elem.textContent).toMatch(regex); return true; }; + +exports.fixupIndex = async () => { + // read and save the git level index file + indexData = (await fs.promises.readFile(indexFile)).toString(); + // make lines of the content + let workIndexLines = indexData.split(os.EOL); + // loop thru the lines to find place to insert new region + for (let l in workIndexLines) { + if (workIndexLines[l].includes("region top right")) { + // insert a new line with new region definition + workIndexLines.splice(l, 0, "
"); + break; + } + } + // write out the new index.html file, not append + await fs.promises.writeFile(indexFile, workIndexLines.join(os.EOL), { flush: true }); + // read in the current custom.css + cssData = (await fs.promises.readFile(cssFile)).toString(); + // write out the custom.css for this testcase, matching the new region name + await fs.promises.writeFile(cssFile, sampleCss.join(os.EOL), { flush: true }); +}; + +exports.restoreIndex = async () => { + // if we read in data + if (indexData.length > 1) { + //write out saved index.html + await fs.promises.writeFile(indexFile, indexData, { flush: true }); + // write out saved custom.css + await fs.promises.writeFile(cssFile, cssData, { flush: true }); + } +}; From 7915de31498ab2266a90765d19fd68cf5584d3e9 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 31 Aug 2024 07:14:30 +0200 Subject: [PATCH 090/418] update dependencies (#3527) We cannot upgrade to electron v32 because electron-rebuild is failing with epoll, so staying at v31. --- CHANGELOG.md | 1 + fonts/package-lock.json | 18 +- fonts/package.json | 4 +- package-lock.json | 1243 +++++++++++++++++++++----------------- package.json | 20 +- vendor/package-lock.json | 26 +- vendor/package.json | 2 +- 7 files changed, 720 insertions(+), 594 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c06146ae71..03a61342d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Updated dependencies including stylistic-eslint - [core] Updated SocketIO catch all to new API - [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded(fixes #3504) +- [core] Update dependencies ### Fixed diff --git a/fonts/package-lock.json b/fonts/package-lock.json index 287cd90e62..49947cf48c 100644 --- a/fonts/package-lock.json +++ b/fonts/package-lock.json @@ -9,19 +9,21 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.0.13", - "@fontsource/roboto-condensed": "^5.0.16" + "@fontsource/roboto": "^5.0.14", + "@fontsource/roboto-condensed": "^5.0.17" } }, "node_modules/@fontsource/roboto": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.13.tgz", - "integrity": "sha512-j61DHjsdUCKMXSdNLTOxcG701FWnF0jcqNNQi2iPCDxU8seN/sMxeh62dC++UiagCWq9ghTypX+Pcy7kX+QOeQ==" + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.14.tgz", + "integrity": "sha512-zHAxlTTm9RuRn9/StwclFJChf3z9+fBrOxC3fw71htjHP1BgXNISwRjdJtAKAmMe5S2BzgpnjkQR93P9EZYI/Q==", + "license": "Apache-2.0" }, "node_modules/@fontsource/roboto-condensed": { - "version": "5.0.16", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.16.tgz", - "integrity": "sha512-pjO80g5x/hkqzWCIafvkS3JrkBDxSiTjEy4LdqQKJYrmoGx8x2AlhSUMgzIzG/ge4kT98bA7+gmm7yquzrrZ/w==" + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.17.tgz", + "integrity": "sha512-rLsnIPjYP8Csa7o0nCDDPW6xC+kWnlM7iYbZmqxEfuI9LzA2z7jQnHVhOuivuwMyE+snmzxQfWhFUoY+SfbU0A==", + "license": "OFL-1.1" } } } diff --git a/fonts/package.json b/fonts/package.json index 09d7c153e6..029458b752 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.0.13", - "@fontsource/roboto-condensed": "^5.0.16" + "@fontsource/roboto": "^5.0.14", + "@fontsource/roboto-condensed": "^5.0.17" } } diff --git a/package-lock.json b/package-lock.json index 14bb1e1607..99f3d05c4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,24 +27,24 @@ "pm2": "^5.4.2", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.23.4" + "systeminformation": "^5.23.5" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.6.2", + "@stylistic/eslint-plugin": "^2.7.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.8.0", - "eslint-plugin-jsdoc": "^50.0.0", + "eslint-plugin-jest": "^28.8.1", + "eslint-plugin-jsdoc": "^50.2.2", "eslint-plugin-package-json": "^0.15.2", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", - "husky": "^9.1.4", + "husky": "^9.1.5", "jest": "^29.7.0", - "jsdom": "^24.1.1", - "lint-staged": "^15.2.8", - "playwright": "^1.46.0", + "jsdom": "^25.0.0", + "lint-staged": "^15.2.9", + "playwright": "^1.46.1", "prettier": "^3.3.3", "sinon": "^18.0.0", - "stylelint": "^16.8.1", + "stylelint": "^16.9.0", "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.2" }, @@ -52,7 +52,7 @@ "node": ">=20" }, "optionalDependencies": { - "electron": "^31.3.1" + "electron": "^31.4.0" } }, "node_modules/@ampproject/remapping": { @@ -84,9 +84,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", - "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", "dev": true, "license": "MIT", "engines": { @@ -94,22 +94,22 @@ } }, "node_modules/@babel/core": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", - "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helpers": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -135,13 +135,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7", + "@babel/types": "^7.25.6", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -164,15 +164,15 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", - "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -190,46 +190,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", @@ -245,17 +205,16 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", - "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -265,9 +224,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", - "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "dev": true, "license": "MIT", "engines": { @@ -288,23 +247,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", - "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "dev": true, "license": "MIT", "engines": { @@ -322,9 +268,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", - "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "dev": true, "license": "MIT", "engines": { @@ -332,14 +278,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", - "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" }, "engines": { "node": ">=6.9.0" @@ -440,11 +386,14 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", - "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -491,6 +440,38 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -611,6 +592,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -628,13 +625,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -644,35 +641,32 @@ } }, "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", - "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -691,13 +685,13 @@ } }, "node_modules/@babel/types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", - "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, @@ -713,9 +707,9 @@ "license": "MIT" }, "node_modules/@csstools/css-parser-algorithms": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz", - "integrity": "sha512-2SJS42gxmACHgikc1WGesXLIT8d/q2l0UFM7TaEeIzdFCE/FPMtTiizcPGGJtlPo2xuQzY09OhrLTzRxqJqwGw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", + "integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==", "dev": true, "funding": [ { @@ -727,17 +721,18 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-tokenizer": "^3.0.1" } }, "node_modules/@csstools/css-tokenizer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.4.1.tgz", - "integrity": "sha512-eQ9DIktFJBhGjioABJRtUucoWR2mwllurfnM8LuNGAqX3ViZXaUchqk+1s7jjtkFiT9ySdACsFEA3etErkALUg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz", + "integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==", "dev": true, "funding": [ { @@ -749,14 +744,15 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.13.tgz", - "integrity": "sha512-XaHr+16KRU9Gf8XLi3q8kDlI18d5vzKSKCY510Vrtc9iNR0NJzbY9hhTmwhzYZj/ZwGL4VmB3TA9hJW0Um2qFA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", + "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", "dev": true, "funding": [ { @@ -768,18 +764,19 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "@csstools/css-parser-algorithms": "^3.0.1", + "@csstools/css-tokenizer": "^3.0.1" } }, "node_modules/@csstools/selector-specificity": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.1.tgz", - "integrity": "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", + "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", "dev": true, "funding": [ { @@ -793,10 +790,10 @@ ], "license": "MIT-0", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=18" }, "peerDependencies": { - "postcss-selector-parser": "^6.0.13" + "postcss-selector-parser": "^6.1.0" } }, "node_modules/@dual-bundle/import-meta-resolve": { @@ -843,14 +840,15 @@ } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", - "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==", + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.48.0.tgz", + "integrity": "sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw==", "dev": true, + "license": "MIT", "dependencies": { "comment-parser": "1.4.1", "esquery": "^1.6.0", - "jsdoc-type-pratt-parser": "~4.0.0" + "jsdoc-type-pratt-parser": "~4.1.0" }, "engines": { "node": ">=16" @@ -871,6 +869,18 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { "version": "4.11.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", @@ -929,6 +939,35 @@ "concat-map": "0.0.1" } }, + "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1481,9 +1520,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, "license": "MIT" }, @@ -1538,6 +1577,7 @@ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -1643,6 +1683,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.1.tgz", "integrity": "sha512-KiA+shC6sULQAr9mGZ1pg+6KVW9MF8NpG99x26Lf/082/Qy8qsTCtnJy+HQReW1A9Rdf0C/404cz0RZGZro+IA==", + "license": "Apache-2", "dependencies": { "async": "~2.6.1", "debug": "~4.3.1", @@ -1661,6 +1702,7 @@ "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", "dependencies": { "lodash": "^4.17.14" } @@ -1668,12 +1710,14 @@ "node_modules/@pm2/io/node_modules/eventemitter2": { "version": "6.4.9", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", - "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", + "license": "MIT" }, "node_modules/@pm2/io/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -1685,6 +1729,7 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1698,7 +1743,8 @@ "node_modules/@pm2/io/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, "node_modules/@pm2/js-api": { "version": "0.8.0", @@ -1837,9 +1883,9 @@ } }, "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", "dev": true, "license": "(Unlicense OR Apache-2.0)" }, @@ -1850,79 +1896,16 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.6.2.tgz", - "integrity": "sha512-Ic5oFNM/25iuagob6LiIBkSI/A2y45TsyKtDtODXHRZDy52WfPfeexI6r+OH5+aWN9QGob2Bw+4JRM9/4areWw==", - "dev": true, - "dependencies": { - "@stylistic/eslint-plugin-js": "2.6.2", - "@stylistic/eslint-plugin-jsx": "2.6.2", - "@stylistic/eslint-plugin-plus": "2.6.2", - "@stylistic/eslint-plugin-ts": "2.6.2", - "@types/eslint": "^9.6.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, - "node_modules/@stylistic/eslint-plugin-js": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.6.2.tgz", - "integrity": "sha512-wCr/kVctAPayMU3pcOI1MKR7MoKIh6VKZU89lPklAqtJoxT+Em6RueiiARbpznUYG5eg3LymiU+aMD+aIZXdqA==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.7.2.tgz", + "integrity": "sha512-3DVLU5HEuk2pQoBmXJlzvrxbKNpu2mJ0SRqz5O/CJjyNCr12ZiPcYMEtuArTyPOk5i7bsAU44nywh1rGfe3gKQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/eslint": "^9.6.0", - "acorn": "^8.12.1", + "@types/eslint": "^9.6.1", + "@typescript-eslint/utils": "^8.3.0", "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, - "node_modules/@stylistic/eslint-plugin-js/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@stylistic/eslint-plugin-js/node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, - "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.6.2.tgz", - "integrity": "sha512-dSXK/fSPA938J1fBi10QmhzLKtZ/2TuyVNHQMk8jUhWfKJDleAogaSqcWNAbN8fwcoe9UWmt/3StiIf2oYC1aQ==", - "dev": true, - "dependencies": { - "@stylistic/eslint-plugin-js": "^2.6.2", - "@types/eslint": "^9.6.0", + "espree": "^10.1.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -1933,36 +1916,6 @@ "eslint": ">=8.40.0" } }, - "node_modules/@stylistic/eslint-plugin-plus": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.6.2.tgz", - "integrity": "sha512-cANcPASfRvq3VTbbQCrSIXq+2AI0IW68PNYaZoXXS0ENlp7HDB8dmrsJnOgWCcoEvdCB8z/eWcG/eq/v5Qcl+Q==", - "dev": true, - "dependencies": { - "@types/eslint": "^9.6.0", - "@typescript-eslint/utils": "^8.0.0" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@stylistic/eslint-plugin-ts": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.6.2.tgz", - "integrity": "sha512-6OEN3VtUNxjgOvWPavnC10MByr1H4zsgwNND3rQXr5lDFv93MLUnTsH+/SH15OkuqdyJgrQILI6b9lYecb1vIg==", - "dev": true, - "dependencies": { - "@stylistic/eslint-plugin-js": "2.6.2", - "@types/eslint": "^9.6.0", - "@typescript-eslint/utils": "^8.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=8.40.0" - } - }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -2056,10 +2009,11 @@ } }, "node_modules/@types/eslint": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", - "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2069,7 +2023,8 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/glob": { "version": "7.2.0", @@ -2158,12 +2113,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.14.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", - "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", + "version": "20.16.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.2.tgz", + "integrity": "sha512-91s/n4qUPV/wg8eE9KHYW1kouTfDk2FPGjXbBMfRWP/2vg1rCXNQL1OCabwGs0XSdukuK+MwCDXE30QpSeMUhQ==", "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/normalize-package-data": { @@ -2191,9 +2146,9 @@ "license": "MIT" }, "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "license": "MIT", "dependencies": { @@ -2218,13 +2173,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", - "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", + "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1" + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2235,10 +2191,11 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", - "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", + "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -2248,15 +2205,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", - "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", + "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1", + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/visitor-keys": "8.3.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", @@ -2276,15 +2234,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.1.tgz", - "integrity": "sha512-CBFR0G0sCt0+fzfnKaciu9IBsKvEKYwN9UZ+eeogK1fYHg4Qxk1yf/wLQkLXlq8wbU2dFlgAesxt8Gi76E8RTA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", + "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.0.1", - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/typescript-estree": "8.0.1" + "@typescript-eslint/scope-manager": "8.3.0", + "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/typescript-estree": "8.3.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2298,12 +2257,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", - "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", + "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/types": "8.3.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2314,6 +2274,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -2337,6 +2310,7 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -2369,6 +2343,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -2461,6 +2436,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.3.2.tgz", "integrity": "sha512-cFthbBlt+Oi0i9Pv/j6YdVWJh54CtjGACaMPCIrEV4Ha7HWsIjXDwseYV79TIL0B4+KfSwD5S70PeQDkPUd1rA==", + "license": "ISC", "engines": { "node": ">=15" } @@ -2653,9 +2629,9 @@ } }, "node_modules/ast-types/node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, "node_modules/astral-regex": { @@ -2669,9 +2645,9 @@ } }, "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "license": "MIT" }, "node_modules/asynckit": { @@ -2789,24 +2765,27 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -2972,6 +2951,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -2989,9 +2969,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "funding": [ { @@ -3009,10 +2989,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -3137,9 +3117,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001638", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001638.tgz", - "integrity": "sha512-5SuJUJ7cZnhPpeLHaH0c/HPAnAHZvS6ElWyHK9GSIbVOQABLzowiI2pjmpvZ1WEbkyz46iFd4UXlOHR5SqgfMQ==", + "version": "1.0.30001655", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", + "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", "dev": true, "funding": [ { @@ -3242,9 +3222,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz", + "integrity": "sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==", "dev": true, "license": "MIT" }, @@ -3287,6 +3267,7 @@ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, + "license": "MIT", "dependencies": { "restore-cursor": "^5.0.0" }, @@ -3326,6 +3307,7 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, + "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" @@ -3462,7 +3444,8 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", @@ -3490,6 +3473,7 @@ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12.0.0" } @@ -3557,13 +3541,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.23.0" + "browserslist": "^4.23.3" }, "funding": { "type": "opencollective", @@ -3799,15 +3783,16 @@ } }, "node_modules/dayjs": { - "version": "1.11.11", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", - "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", "license": "MIT" }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -4105,10 +4090,11 @@ "license": "MIT" }, "node_modules/electron": { - "version": "31.3.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.3.1.tgz", - "integrity": "sha512-9fiuWlRhBfygtcT+auRd/WdBK/f8LZZcrpx0RjpXhH2DPTP/PfnkC4JB1PW55qCbGbh4wAgkYbf4ExIag8oGCA==", + "version": "31.4.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.4.0.tgz", + "integrity": "sha512-YTwKoAA+nrJMlI1TTHnIXLYWoQLKnhbkz0qxZcI7Hadcy0UaFMFs9xzwvH2MnrRpVJy7RKo49kVGuvSdRl8zMA==", "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "@electron/get": "^2.0.0", @@ -4123,9 +4109,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.814", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.814.tgz", - "integrity": "sha512-GVulpHjFu1Y9ZvikvbArHmAhZXtm3wHlpjTMcXNGKl4IQ4jMQjlnz8yMQYYqdLHKi/jEL2+CBC2akWVCoIGUdw==", + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", + "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", "dev": true, "license": "ISC" }, @@ -4143,10 +4129,11 @@ } }, "node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -4189,9 +4176,9 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -4206,6 +4193,27 @@ "node": ">= 0.6" } }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -4245,6 +4253,7 @@ "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -4380,7 +4389,8 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -4443,9 +4453,9 @@ "optional": true }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -4569,9 +4579,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", + "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", "dev": true, "license": "MIT", "dependencies": { @@ -4686,10 +4696,11 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", - "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", + "version": "28.8.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.1.tgz", + "integrity": "sha512-G46XMyYu6PtSNJUkQ0hsPjzXYpzq/O4vpCciMizTKRJG8kNsRreGoMRDG6H9FIB/xVgfFuclVnuX4XRvFUzrZQ==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" }, @@ -4711,15 +4722,16 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.0.0.tgz", - "integrity": "sha512-czyJ5F7/qY2LIhUD5Bl6q1CCZ8mjvfEA9HQN5nvIp/Pb8VLIlUNd+DMZdA2OKN74QQMS3pobC06hFqAOJyOv5Q==", + "version": "50.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.2.2.tgz", + "integrity": "sha512-i0ZMWA199DG7sjxlzXn5AeYZxpRfMJjDPUl7lL9eJJX8TPRoIaxJU4ys/joP5faM5AXE1eqW/dslCj3uj4Nqpg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.46.0", + "@es-joy/jsdoccomment": "~0.48.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", - "debug": "^4.3.5", + "debug": "^4.3.6", "escape-string-regexp": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.6.0", @@ -4735,40 +4747,12 @@ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-jsdoc/node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, - "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/eslint-plugin-package-json": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.2.tgz", "integrity": "sha512-mls5O8zT3Sjl/lLmhT8xtNkLpj7b3uP6wwK9rgg9rtmAbPjlzkunCySlHQgEcB6ZUV+Qi3QabLaSub2IWr2VmA==", "dev": true, + "license": "MIT", "dependencies": { "detect-indent": "6.1.0", "detect-newline": "3.1.0", @@ -4791,6 +4775,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.24.5", "@eslint-community/eslint-utils": "^4.4.0", @@ -4824,6 +4809,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -4848,12 +4834,13 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4885,6 +4872,35 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4904,17 +4920,18 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -4937,6 +4954,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -4993,7 +5011,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/execa": { "version": "5.1.1", @@ -5234,7 +5253,8 @@ "node_modules/fast-uri": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "license": "MIT" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -5544,6 +5564,7 @@ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -5831,24 +5852,23 @@ } }, "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", + "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", "dev": true, "license": "MIT", "dependencies": { + "@types/glob": "^7.1.1", "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", "slash": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/globjoin": { @@ -6168,10 +6188,11 @@ } }, "node_modules/husky": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.4.tgz", - "integrity": "sha512-bho94YyReb4JV7LYWRWxZ/xr6TtOTt8cMfmQ39MQYJ7f/YE268s3GdghGwi+y4zAeqewE5zYLvuhV0M0ijsDEA==", + "version": "9.1.5", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.5.tgz", + "integrity": "sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag==", "dev": true, + "license": "MIT", "bin": { "husky": "bin.js" }, @@ -6195,9 +6216,9 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "license": "MIT", "engines": { "node": ">= 4" @@ -6220,9 +6241,9 @@ } }, "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "license": "MIT", "dependencies": { @@ -6430,9 +6451,9 @@ } }, "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -6488,6 +6509,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -6713,9 +6735,9 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", - "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -7439,19 +7461,21 @@ "license": "MIT" }, "node_modules/jsdoc-type-pratt-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", - "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" } }, "node_modules/jsdom": { - "version": "24.1.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz", - "integrity": "sha512-5O1wWV99Jhq4DV7rCLIoZ/UIhyQeDR7wHVyZAHAshbrvZsLs+Xzz7gtwnlJTJDjleiTKh54F4dXrX70vJQTyJQ==", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.0.tgz", + "integrity": "sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ==", "dev": true, + "license": "MIT", "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", @@ -7487,27 +7511,6 @@ } } }, - "node_modules/jsdom/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/jsesc": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", @@ -7586,6 +7589,39 @@ "url": "https://github.com/sponsors/ota-meshi" } }, + "node_modules/jsonc-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -7636,7 +7672,8 @@ "version": "0.34.0", "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lazy": { "version": "1.0.11", @@ -7700,10 +7737,11 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.8", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.8.tgz", - "integrity": "sha512-PUWFf2zQzsd9EFU+kM1d7UP+AZDbKFKuj+9JNVTBkhUFhbg4MAt6WfyMMwBfM4lYqd4D2Jwac5iuTu9rVj4zCQ==", + "version": "15.2.9", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.9.tgz", + "integrity": "sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "~5.3.0", "commander": "~12.1.0", @@ -7898,6 +7936,7 @@ "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", "dev": true, + "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", @@ -7956,6 +7995,7 @@ "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", @@ -7975,6 +8015,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, + "license": "MIT", "dependencies": { "environment": "^1.0.0" }, @@ -7990,6 +8031,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -8002,6 +8044,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -8014,6 +8057,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, + "license": "MIT", "dependencies": { "get-east-asian-width": "^1.0.0" }, @@ -8029,6 +8073,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -8045,6 +8090,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -8187,9 +8233,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -8261,6 +8307,7 @@ "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -8293,6 +8340,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8333,7 +8381,8 @@ "node_modules/module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", + "license": "MIT" }, "node_modules/moment": { "version": "2.30.1", @@ -8470,13 +8519,13 @@ } }, "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", - "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", + "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@sinonjs/commons": "^3.0.1" } }, "node_modules/nise/node_modules/path-to-regexp": { @@ -8506,9 +8555,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true, "license": "MIT" }, @@ -8593,7 +8642,8 @@ "version": "2.2.12", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/object-assign": { "version": "4.1.1", @@ -8737,6 +8787,7 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", "dev": true, + "license": "MIT/X11", "dependencies": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" @@ -8746,13 +8797,15 @@ "version": "0.0.10", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/optimist/node_modules/wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -8891,6 +8944,7 @@ "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.1.1.tgz", "integrity": "sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "es-module-lexer": "^1.5.3", "slashes": "^3.0.12" @@ -9030,6 +9084,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -9142,12 +9197,13 @@ } }, "node_modules/playwright": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", - "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", + "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.46.0" + "playwright-core": "1.46.1" }, "bin": { "playwright": "cli.js" @@ -9160,10 +9216,11 @@ } }, "node_modules/playwright-core": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", - "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", + "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -9200,6 +9257,7 @@ "version": "5.4.2", "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.2.tgz", "integrity": "sha512-ynVpBwZampRH3YWLwRepZpQ7X3MvpwLIaqIdFEeBYEhaXbHmEx2KqOdxGV4T54wvKBhH3LixvU1j1bK4/sq7Tw==", + "license": "AGPL-3.0", "dependencies": { "@pm2/agent": "~2.0.0", "@pm2/io": "~6.0.1", @@ -9359,9 +9417,9 @@ } }, "node_modules/postcss": { - "version": "8.4.40", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", - "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "dev": true, "funding": [ { @@ -9377,6 +9435,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", @@ -9387,10 +9446,11 @@ } }, "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.4.tgz", - "integrity": "sha512-R6vHqZWgVnTAPq0C+xjyHfEZqfIYboCBVSy24MjxEDm+tIh1BU4O6o7DP7AA7kHzf136d+Qc5duI4tlpHjixDw==", - "dev": true + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "dev": true, + "license": "MIT" }, "node_modules/postcss-safe-parser": { "version": "7.0.0", @@ -9420,10 +9480,11 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", - "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9453,6 +9514,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -9967,6 +10029,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", + "license": "MIT", "dependencies": { "debug": "^4.1.1", "module-details-from-path": "^1.0.3", @@ -10067,6 +10130,7 @@ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, + "license": "MIT", "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" @@ -10083,6 +10147,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-function": "^5.0.0" }, @@ -10098,6 +10163,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "engines": { "node": ">=14" }, @@ -10119,7 +10185,8 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/rimraf": { "version": "3.0.2", @@ -10165,9 +10232,9 @@ } }, "node_modules/rrule/node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, "node_modules/rrweb-cssom": { @@ -10316,6 +10383,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -10481,7 +10549,8 @@ "node_modules/shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" }, "node_modules/side-channel": { "version": "1.0.6", @@ -10527,13 +10596,13 @@ } }, "node_modules/sinon/node_modules/@sinonjs/fake-timers": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", - "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", + "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^3.0.0" + "@sinonjs/commons": "^3.0.1" } }, "node_modules/sinon/node_modules/diff": { @@ -10567,13 +10636,15 @@ "version": "3.0.12", "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -10590,6 +10661,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10635,6 +10707,27 @@ "ws": "~8.17.1" } }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -10701,26 +10794,6 @@ "sort-package-json": "cli.js" } }, - "node_modules/sort-package-json/node_modules/globby": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", - "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -10792,9 +10865,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", - "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", "dev": true, "license": "CC0-1.0" }, @@ -10865,6 +10938,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -10882,6 +10956,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -10894,6 +10969,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -11037,9 +11113,9 @@ } }, "node_modules/stylelint": { - "version": "16.8.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.8.1.tgz", - "integrity": "sha512-O8aDyfdODSDNz/B3gW2HQ+8kv8pfhSu7ZR7xskQ93+vI6FhKKGUJMQ03Ydu+w3OvXXE0/u4hWU4hCPNOyld+OA==", + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.9.0.tgz", + "integrity": "sha512-31Nm3WjxGOBGpQqF43o3wO9L5AC36TPIe6030Lnm13H3vDMTcS21DrLh69bMX+DBilKqMMVLian4iG6ybBoNRQ==", "dev": true, "funding": [ { @@ -11051,11 +11127,12 @@ "url": "https://github.com/sponsors/stylelint" } ], + "license": "MIT", "dependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1", - "@csstools/media-query-list-parser": "^2.1.13", - "@csstools/selector-specificity": "^3.1.1", + "@csstools/css-parser-algorithms": "^3.0.1", + "@csstools/css-tokenizer": "^3.0.1", + "@csstools/media-query-list-parser": "^3.0.1", + "@csstools/selector-specificity": "^4.0.0", "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", @@ -11070,24 +11147,24 @@ "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", - "ignore": "^5.3.1", + "ignore": "^5.3.2", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", "known-css-properties": "^0.34.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", - "micromatch": "^4.0.7", + "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.0.1", - "postcss": "^8.4.40", - "postcss-resolve-nested-selector": "^0.1.4", + "postcss": "^8.4.41", + "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.0", - "postcss-selector-parser": "^6.1.1", + "postcss-selector-parser": "^6.1.2", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", "strip-ansi": "^7.1.0", - "supports-hyperlinks": "^3.0.0", + "supports-hyperlinks": "^3.1.0", "svg-tags": "^1.0.0", "table": "^6.8.2", "write-file-atomic": "^5.0.1" @@ -11153,6 +11230,7 @@ "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.2.tgz", "integrity": "sha512-qJ+BN+1T2ZcKz9WIrv0x+eFGHzSUnXfXd5gL///T6XoJvr3D8/ztzz2fhtmXef7Vb8P33zBXmLTTveByr0nwBw==", "dev": true, + "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0" }, @@ -11179,9 +11257,9 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.0.0.tgz", - "integrity": "sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", "dev": true, "license": "MIT", "dependencies": { @@ -11205,6 +11283,27 @@ "node": ">=18" } }, + "node_modules/stylelint/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/stylelint/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", @@ -11340,9 +11439,9 @@ } }, "node_modules/supports-hyperlinks": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", - "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", + "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", "dev": true, "license": "MIT", "dependencies": { @@ -11351,6 +11450,9 @@ }, "engines": { "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -11383,6 +11485,7 @@ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, + "license": "MIT", "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" @@ -11395,15 +11498,17 @@ } }, "node_modules/synckit/node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" }, "node_modules/systeminformation": { - "version": "5.23.4", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.4.tgz", - "integrity": "sha512-mD2R9xnOzKOOmIVtxekosf/ghOE/DGLqAPmsEgQMWJK0pMKxBtX19riz1Ss0tN4omcfS2FQ2RDJ4lkxgADxIPw==", + "version": "5.23.5", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.5.tgz", + "integrity": "sha512-PEpJwhRYxZgBCAlWZhWIgfMTjXLqfcaZ1pJsJn9snWNfBW/Z1YQg1mbIUSWrEV3ErAHF7l/OoVLQeaZDlPzkpA==", + "license": "MIT", "os": [ "darwin", "linux", @@ -11619,6 +11724,7 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -11665,7 +11771,8 @@ "node_modules/tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "license": "Apache-2.0" }, "node_modules/tv4": { "version": "1.3.0", @@ -11816,9 +11923,9 @@ } }, "node_modules/typescript": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", - "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -11831,9 +11938,9 @@ } }, "node_modules/uglify-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", - "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "license": "BSD-2-Clause", "optional": true, "bin": { @@ -11859,9 +11966,9 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, "node_modules/universalify": { @@ -11884,9 +11991,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", - "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { @@ -12183,6 +12290,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -12200,6 +12308,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -12212,6 +12321,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -12224,6 +12334,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -12255,9 +12366,10 @@ } }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -12314,6 +12426,7 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", "dev": true, + "license": "ISC", "bin": { "yaml": "bin.mjs" }, diff --git a/package.json b/package.json index b0eb77e937..5d19595455 100644 --- a/package.json +++ b/package.json @@ -71,29 +71,29 @@ "pm2": "^5.4.2", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.23.4" + "systeminformation": "^5.23.5" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.6.2", + "@stylistic/eslint-plugin": "^2.7.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.8.0", - "eslint-plugin-jsdoc": "^50.0.0", + "eslint-plugin-jest": "^28.8.1", + "eslint-plugin-jsdoc": "^50.2.2", "eslint-plugin-package-json": "^0.15.2", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", - "husky": "^9.1.4", + "husky": "^9.1.5", "jest": "^29.7.0", - "jsdom": "^24.1.1", - "lint-staged": "^15.2.8", - "playwright": "^1.46.0", + "jsdom": "^25.0.0", + "lint-staged": "^15.2.9", + "playwright": "^1.46.1", "prettier": "^3.3.3", "sinon": "^18.0.0", - "stylelint": "^16.8.1", + "stylelint": "^16.9.0", "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.2" }, "optionalDependencies": { - "electron": "^31.3.1" + "electron": "^31.4.0" }, "engines": { "node": ">=20" diff --git a/vendor/package-lock.json b/vendor/package-lock.json index c74b6f73a1..b4370bf642 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.6.0", "animate.css": "^4.1.1", - "croner": "^8.1.0", + "croner": "^8.1.1", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", @@ -23,6 +23,7 @@ "version": "6.6.0", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz", "integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==", + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", "engines": { "node": ">=6" } @@ -30,30 +31,35 @@ "node_modules/a-sync-waterfall": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "license": "MIT" }, "node_modules/animate.css": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", - "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==" + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==", + "license": "MIT" }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" }, "node_modules/commander": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/croner": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/croner/-/croner-8.1.0.tgz", - "integrity": "sha512-sz990XOUPR8dG/r5BRKMBd15MYDDUu8oeSaxFD5DqvNgHSZw8Psd1s689/IGET7ezxRMiNlCIyGeY1Gvxp/MLg==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/croner/-/croner-8.1.1.tgz", + "integrity": "sha512-1VdUuRnQP4drdFkS8NKvDR1NBgevm8TOuflcaZEKsxw42CxonjW/2vkj1AKlinJb4ZLwBcuWF9GiPr7FQc6AQA==", + "license": "MIT", "engines": { "node": ">=18.0" } @@ -62,6 +68,7 @@ "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } @@ -70,6 +77,7 @@ "version": "0.5.45", "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "license": "MIT", "dependencies": { "moment": "^2.29.4" }, @@ -81,6 +89,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "license": "BSD-2-Clause", "dependencies": { "a-sync-waterfall": "^1.0.0", "asap": "^2.0.3", @@ -109,7 +118,8 @@ "node_modules/weathericons": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/weathericons/-/weathericons-2.1.0.tgz", - "integrity": "sha512-V45viuyuQQOuoePTqzxvP/wBpYALWkD695fkFvqpn+BiMyo64fFlyDbP2A8umZyFyz1cXFPNw1pWqeaSaQqJlQ==" + "integrity": "sha512-V45viuyuQQOuoePTqzxvP/wBpYALWkD695fkFvqpn+BiMyo64fFlyDbP2A8umZyFyz1cXFPNw1pWqeaSaQqJlQ==", + "license": "MIT" } } } diff --git a/vendor/package.json b/vendor/package.json index be26ef0822..d303ee7ae2 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -13,7 +13,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.6.0", "animate.css": "^4.1.1", - "croner": "^8.1.0", + "croner": "^8.1.1", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", From bca5d9c8454382e67ea7112600259285fdf8dc67 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:12:34 +0200 Subject: [PATCH 091/418] Ignore positions.js (#3531) This file is generated when MM is started. As I understand it, it should not be included in the repository. Should probably have been part of #3518. --- .gitignore | 3 +++ CHANGELOG.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 945c6c244b..7301472cce 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,6 @@ Temporary Items *.orig *.rej *.bak + +# Ignore positions file (#3518) +js/positions.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 03a61342d0..febf68ed29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) - [core] Updated dependencies including stylistic-eslint - [core] Updated SocketIO catch all to new API -- [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded(fixes #3504) +- [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded (PR #3518 fixes issue #3504) - [core] Update dependencies ### Fixed From 3380314c11fef4a163ccd28a766e1f54727bd665 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 13 Sep 2024 23:52:34 +0200 Subject: [PATCH 092/418] hotfix for calendar_spec.js (used data now returns 20 events) (#3533) fixes #3532 --- CHANGELOG.md | 1 + tests/e2e/modules/calendar_spec.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index febf68ed29..56db0c20bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Fixed issue with the UK Met Office provider following a change in their API paths and header info. - [core] add check for node_helper loading for multiple instances of same module (#3502) - [weather] Fixed issue for respecting unit config on broadcasted notifications +- [tests] Fixes calendar e2e test (#3532) ## [2.28.0] - 2024-07-01 diff --git a/tests/e2e/modules/calendar_spec.js b/tests/e2e/modules/calendar_spec.js index 0dcd562cd1..e2f9266c3e 100644 --- a/tests/e2e/modules/calendar_spec.js +++ b/tests/e2e/modules/calendar_spec.js @@ -95,7 +95,7 @@ describe("Calendar module", () => { }); it("should show multiple events with the same title and start time from different calendars", async () => { - await expect(testElementLength(".calendar .event", 22)).resolves.toBe(true); + await expect(testElementLength(".calendar .event", 20)).resolves.toBe(true); }); }); From 81351fb4cca48cd506ec41fc339f673ec38d100f Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 14 Sep 2024 22:05:20 +0200 Subject: [PATCH 093/418] update dependencies (#3536) --- CHANGELOG.md | 1 - fonts/package-lock.json | 16 +- fonts/package.json | 4 +- package-lock.json | 502 ++++++++++++++++++++-------------------- package.json | 22 +- 5 files changed, 268 insertions(+), 277 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56db0c20bc..7b824b7795 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,6 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Updated dependencies including stylistic-eslint - [core] Updated SocketIO catch all to new API - [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded (PR #3518 fixes issue #3504) -- [core] Update dependencies ### Fixed diff --git a/fonts/package-lock.json b/fonts/package-lock.json index 49947cf48c..3acdd8c0a7 100644 --- a/fonts/package-lock.json +++ b/fonts/package-lock.json @@ -9,20 +9,20 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.0.14", - "@fontsource/roboto-condensed": "^5.0.17" + "@fontsource/roboto": "^5.1.0", + "@fontsource/roboto-condensed": "^5.1.0" } }, "node_modules/@fontsource/roboto": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.14.tgz", - "integrity": "sha512-zHAxlTTm9RuRn9/StwclFJChf3z9+fBrOxC3fw71htjHP1BgXNISwRjdJtAKAmMe5S2BzgpnjkQR93P9EZYI/Q==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.1.0.tgz", + "integrity": "sha512-cFRRC1s6RqPygeZ8Uw/acwVHqih8Czjt6Q0MwoUoDe9U3m4dH1HmNDRBZyqlMSFwgNAUKgFImncKdmDHyKpwdg==", "license": "Apache-2.0" }, "node_modules/@fontsource/roboto-condensed": { - "version": "5.0.17", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.17.tgz", - "integrity": "sha512-rLsnIPjYP8Csa7o0nCDDPW6xC+kWnlM7iYbZmqxEfuI9LzA2z7jQnHVhOuivuwMyE+snmzxQfWhFUoY+SfbU0A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.1.0.tgz", + "integrity": "sha512-cTS62X9bgR6H+3qRtaDwt0I+3ocitMPalyr2OrzJtilIcuEo4my8UA4VVhOgr0OI2Sk9JNrNYcSxkv0k4XuKtQ==", "license": "OFL-1.1" } } diff --git a/fonts/package.json b/fonts/package.json index 029458b752..0b6576f2f6 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.0.14", - "@fontsource/roboto-condensed": "^5.0.17" + "@fontsource/roboto": "^5.1.0", + "@fontsource/roboto-condensed": "^5.1.0" } } diff --git a/package-lock.json b/package-lock.json index 99f3d05c4a..2acfed7408 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", - "express": "^4.19.2", + "express": "^4.21.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", @@ -30,20 +30,20 @@ "systeminformation": "^5.23.5" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.7.2", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.8.1", - "eslint-plugin-jsdoc": "^50.2.2", - "eslint-plugin-package-json": "^0.15.2", + "@stylistic/eslint-plugin": "^2.8.0", + "eslint-plugin-import": "^2.30.0", + "eslint-plugin-jest": "^28.8.3", + "eslint-plugin-jsdoc": "^50.2.3", + "eslint-plugin-package-json": "^0.15.3", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", - "husky": "^9.1.5", + "husky": "^9.1.6", "jest": "^29.7.0", "jsdom": "^25.0.0", - "lint-staged": "^15.2.9", - "playwright": "^1.46.1", + "lint-staged": "^15.2.10", + "playwright": "^1.47.1", "prettier": "^3.3.3", - "sinon": "^18.0.0", + "sinon": "^19.0.2", "stylelint": "^16.9.0", "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.2" @@ -52,9 +52,16 @@ "node": ">=20" }, "optionalDependencies": { - "electron": "^31.4.0" + "electron": "^31.6.0" } }, + "node_modules/@altano/repository-tools": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@altano/repository-tools/-/repository-tools-0.1.1.tgz", + "integrity": "sha512-5vbUs2A98CC3g1AlOBdkBE0BMukkLjLIsMHAtuxg6Pt9dQXxYWdLKOf66v6c/vIqtNcgTMv0oGtddLdMuH9X6w==", + "dev": true, + "license": "ISC" + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1807,6 +1814,13 @@ "debug": "^4.3.1" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", @@ -1861,25 +1875,25 @@ } }, "node_modules/@sinonjs/samsam": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", + "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^2.0.0", + "@sinonjs/commons": "^3.0.1", "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" + "type-detect": "^4.1.0" } }, - "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "node_modules/@sinonjs/samsam/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" + "license": "MIT", + "engines": { + "node": ">=4" } }, "node_modules/@sinonjs/text-encoding": { @@ -1896,14 +1910,13 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.7.2.tgz", - "integrity": "sha512-3DVLU5HEuk2pQoBmXJlzvrxbKNpu2mJ0SRqz5O/CJjyNCr12ZiPcYMEtuArTyPOk5i7bsAU44nywh1rGfe3gKQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.8.0.tgz", + "integrity": "sha512-Ufvk7hP+bf+pD35R/QfunF793XlSRIC7USr3/EdgduK9j13i2JjmsM0LUz3/foS+jDYp2fzyWZA9N44CPur0Ow==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint": "^9.6.1", - "@typescript-eslint/utils": "^8.3.0", + "@typescript-eslint/utils": "^8.4.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.1.0", "estraverse": "^5.3.0", @@ -2008,24 +2021,6 @@ "@types/node": "*" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -2081,13 +2076,6 @@ "@types/istanbul-lib-report": "*" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -2113,9 +2101,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.16.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.2.tgz", - "integrity": "sha512-91s/n4qUPV/wg8eE9KHYW1kouTfDk2FPGjXbBMfRWP/2vg1rCXNQL1OCabwGs0XSdukuK+MwCDXE30QpSeMUhQ==", + "version": "20.16.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz", + "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -2173,14 +2161,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", - "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", + "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0" + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2191,9 +2179,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", - "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", + "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", "dev": true, "license": "MIT", "engines": { @@ -2205,14 +2193,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", - "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", + "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/visitor-keys": "8.5.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2234,16 +2222,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0" + "@typescript-eslint/scope-manager": "8.5.0", + "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/typescript-estree": "8.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2257,13 +2245,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", - "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", + "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/types": "8.5.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2889,9 +2877,9 @@ "license": "MIT" }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -2902,7 +2890,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -3117,9 +3105,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001655", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", - "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", + "version": "1.0.30001660", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", + "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", "dev": true, "funding": [ { @@ -3222,9 +3210,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz", - "integrity": "sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", "dev": true, "license": "MIT" }, @@ -3674,25 +3662,18 @@ } }, "node_modules/cssstyle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", - "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dev": true, "license": "MIT", "dependencies": { - "rrweb-cssom": "^0.6.0" + "rrweb-cssom": "^0.7.1" }, "engines": { "node": ">=18" } }, - "node_modules/cssstyle/node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "dev": true, - "license": "MIT" - }, "node_modules/culvert": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", @@ -3789,12 +3770,12 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -4090,9 +4071,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "31.4.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.4.0.tgz", - "integrity": "sha512-YTwKoAA+nrJMlI1TTHnIXLYWoQLKnhbkz0qxZcI7Hadcy0UaFMFs9xzwvH2MnrRpVJy7RKo49kVGuvSdRl8zMA==", + "version": "31.6.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.6.0.tgz", + "integrity": "sha512-J64VtIF8DI/zsGgoYd3p5LbxAWjt59tk2cBSHJNzVhzgiVgDyPFkBwsqmN4gUvyv+6l6+WoYpYmYdapr2o4bPw==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4109,9 +4090,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", - "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", + "version": "1.5.23", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.23.tgz", + "integrity": "sha512-mBhODedOXg4v5QWwl21DjM5amzjmI1zw9EPrPK/5Wx7C8jt33bpZNrC7OhHUG3pxRtbLpr3W2dXT+Ph1SsfRZA==", "dev": true, "license": "ISC" }, @@ -4136,9 +4117,9 @@ "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -4579,9 +4560,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", - "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", + "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4607,27 +4588,28 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", + "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", "dev": true, "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", + "eslint-module-utils": "^2.9.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", "tsconfig-paths": "^3.15.0" }, @@ -4696,9 +4678,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.8.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.1.tgz", - "integrity": "sha512-G46XMyYu6PtSNJUkQ0hsPjzXYpzq/O4vpCciMizTKRJG8kNsRreGoMRDG6H9FIB/xVgfFuclVnuX4XRvFUzrZQ==", + "version": "28.8.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", + "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4722,9 +4704,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.2.2.tgz", - "integrity": "sha512-i0ZMWA199DG7sjxlzXn5AeYZxpRfMJjDPUl7lL9eJJX8TPRoIaxJU4ys/joP5faM5AXE1eqW/dslCj3uj4Nqpg==", + "version": "50.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.2.3.tgz", + "integrity": "sha512-aNh/dz3wSkyo53y2KWDCrA8fDuXDMtMVflcbesd8AFPgcF8ugOv9mJxC7qKB95R96nzCB91iEwU7MMznh/7okQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -4748,12 +4730,13 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.2.tgz", - "integrity": "sha512-mls5O8zT3Sjl/lLmhT8xtNkLpj7b3uP6wwK9rgg9rtmAbPjlzkunCySlHQgEcB6ZUV+Qi3QabLaSub2IWr2VmA==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.3.tgz", + "integrity": "sha512-NRUh+f5orM2/SynPjZqqNqSahdG3qzG5nf8s2S5nEwkhRbEE78S6sSMVGoSmrrtbhcbvZmLVHguVds4lY3Cwkw==", "dev": true, "license": "MIT", "dependencies": { + "@altano/repository-tools": "^0.1.1", "detect-indent": "6.1.0", "detect-newline": "3.1.0", "package-json-validator": "^0.6.5", @@ -5078,37 +5061,37 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -5339,13 +5322,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -5408,9 +5391,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -6188,9 +6171,9 @@ } }, "node_modules/husky": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.5.tgz", - "integrity": "sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag==", + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", "dev": true, "license": "MIT", "bin": { @@ -7737,9 +7720,9 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.9", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.9.tgz", - "integrity": "sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", "dev": true, "license": "MIT", "dependencies": { @@ -7749,7 +7732,7 @@ "execa": "~8.0.1", "lilconfig": "~3.1.2", "listr2": "~8.2.4", - "micromatch": "~4.0.7", + "micromatch": "~4.0.8", "pidtree": "~0.6.0", "string-argv": "~0.3.2", "yaml": "~2.5.0" @@ -8027,9 +8010,9 @@ } }, "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { @@ -8201,10 +8184,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "license": "MIT" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -8406,9 +8392,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/mute-stream": { @@ -8505,23 +8491,23 @@ } }, "node_modules/nise": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-6.0.0.tgz", - "integrity": "sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", + "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^11.2.2", - "@sinonjs/text-encoding": "^0.7.2", + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.1", + "@sinonjs/text-encoding": "^0.7.3", "just-extend": "^6.2.0", - "path-to-regexp": "^6.2.1" + "path-to-regexp": "^8.1.0" } }, "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", - "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", + "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8529,11 +8515,14 @@ } }, "node_modules/nise/node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.1.0.tgz", + "integrity": "sha512-Bqn3vc8CMHty6zuD+tG23s6v2kwxslHEhTj4eYaVKGIEB+YX/2wd0/rgXLFD9G9id9KCtbVy/3ZgmvZjpa0UdQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=16" + } }, "node_modules/node-ical": { "version": "0.18.0", @@ -9041,9 +9030,9 @@ "license": "MIT" }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "license": "MIT" }, "node_modules/path-type": { @@ -9073,9 +9062,9 @@ "optional": true }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "license": "ISC" }, @@ -9197,13 +9186,13 @@ } }, "node_modules/playwright": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", - "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", + "version": "1.47.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.1.tgz", + "integrity": "sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.46.1" + "playwright-core": "1.47.1" }, "bin": { "playwright": "cli.js" @@ -9216,9 +9205,9 @@ } }, "node_modules/playwright-core": { - "version": "1.46.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", - "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", + "version": "1.47.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.1.tgz", + "integrity": "sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -9417,9 +9406,9 @@ } }, "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -9438,8 +9427,8 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -9654,9 +9643,9 @@ "license": "MIT" }, "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "license": "MIT", "optional": true, "dependencies": { @@ -9691,12 +9680,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -10399,9 +10388,9 @@ "optional": true }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -10437,11 +10426,14 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, "node_modules/serialize-error": { "version": "7.0.1", @@ -10473,15 +10465,15 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -10577,18 +10569,18 @@ "license": "ISC" }, "node_modules/sinon": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.0.tgz", - "integrity": "sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", + "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^11.2.2", - "@sinonjs/samsam": "^8.0.0", - "diff": "^5.2.0", - "nise": "^6.0.0", - "supports-color": "^7" + "@sinonjs/fake-timers": "^13.0.2", + "@sinonjs/samsam": "^8.0.1", + "diff": "^7.0.0", + "nise": "^6.1.1", + "supports-color": "^7.2.0" }, "funding": { "type": "opencollective", @@ -10596,9 +10588,9 @@ } }, "node_modules/sinon/node_modules/@sinonjs/fake-timers": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz", - "integrity": "sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", + "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -10606,9 +10598,9 @@ } }, "node_modules/sinon/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -10804,9 +10796,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -10952,9 +10944,9 @@ } }, "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { @@ -11382,9 +11374,9 @@ } }, "node_modules/stylelint/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { @@ -11923,9 +11915,9 @@ } }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -12304,9 +12296,9 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", "engines": { @@ -12422,9 +12414,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 5d19595455..0c8f9dd0be 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^8.57.0", - "express": "^4.19.2", + "express": "^4.21.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^7.1.0", @@ -74,26 +74,26 @@ "systeminformation": "^5.23.5" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.7.2", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.8.1", - "eslint-plugin-jsdoc": "^50.2.2", - "eslint-plugin-package-json": "^0.15.2", + "@stylistic/eslint-plugin": "^2.8.0", + "eslint-plugin-import": "^2.30.0", + "eslint-plugin-jest": "^28.8.3", + "eslint-plugin-jsdoc": "^50.2.3", + "eslint-plugin-package-json": "^0.15.3", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", - "husky": "^9.1.5", + "husky": "^9.1.6", "jest": "^29.7.0", "jsdom": "^25.0.0", - "lint-staged": "^15.2.9", - "playwright": "^1.46.1", + "lint-staged": "^15.2.10", + "playwright": "^1.47.1", "prettier": "^3.3.3", - "sinon": "^18.0.0", + "sinon": "^19.0.2", "stylelint": "^16.9.0", "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.2" }, "optionalDependencies": { - "electron": "^31.4.0" + "electron": "^31.6.0" }, "engines": { "node": ">=20" From 0faefd109abc792dc1156a737fedd454850cfd61 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 15 Sep 2024 08:36:11 +0200 Subject: [PATCH 094/418] fixes calendar test by moving it from e2e to electron with fixed date (#3540) and refactor tests/electron/modules/calendar_spec.js fixes #3532 --- CHANGELOG.md | 2 +- tests/e2e/modules/calendar_spec.js | 11 ---- tests/electron/modules/calendar_spec.js | 72 ++++++++----------------- 3 files changed, 24 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b824b7795..b601450f47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Fixed issue with the UK Met Office provider following a change in their API paths and header info. - [core] add check for node_helper loading for multiple instances of same module (#3502) - [weather] Fixed issue for respecting unit config on broadcasted notifications -- [tests] Fixes calendar e2e test (#3532) +- [tests] Fixes calendar test by moving it from e2e to electron with fixed date (#3532) ## [2.28.0] - 2024-07-01 diff --git a/tests/e2e/modules/calendar_spec.js b/tests/e2e/modules/calendar_spec.js index e2f9266c3e..e88c003ad1 100644 --- a/tests/e2e/modules/calendar_spec.js +++ b/tests/e2e/modules/calendar_spec.js @@ -88,17 +88,6 @@ describe("Calendar module", () => { }); }); - describe("Events from multiple calendars", () => { - beforeAll(async () => { - await helpers.startApplication("tests/configs/modules/calendar/show-duplicates-in-calendar.js"); - await helpers.getDocument(); - }); - - it("should show multiple events with the same title and start time from different calendars", async () => { - await expect(testElementLength(".calendar .event", 20)).resolves.toBe(true); - }); - }); - //Will contain everyday an fullDayEvent that starts today and ends tomorrow, and one starting tomorrow and ending the day after tomorrow describe("FullDayEvent over several days should show how many days are left from the from the starting date on", () => { beforeAll(async () => { diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index bf10ecd752..5624b51b23 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -13,6 +13,15 @@ describe("Calendar module", () => { return true; }; + const doTestCount = async () => { + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + return await loc.count(); + }; + afterEach(async () => { await helpers.stopApplication(); }); @@ -44,6 +53,13 @@ describe("Calendar module", () => { }); }); + describe("Events from multiple calendars", () => { + it("should show multiple events with the same title and start time from different calendars", async () => { + await helpers.startApplication("tests/configs/modules/calendar/show-duplicates-in-calendar.js", "15 Sep 2024 12:30:00 GMT"); + await expect(doTestCount()).resolves.toBe(20); + }); + }); + /* * RRULE TESTS: * Add any tests that check rrule functionality here. @@ -51,13 +67,7 @@ describe("Calendar module", () => { describe("rrule", () => { it("Issue #3393 recurrence dates past rrule until date", async () => { await helpers.startApplication("tests/configs/modules/calendar/rrule_until.js", "07 Mar 2024 10:38:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); - expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); - const elem = loc.first(); - await elem.waitFor(); - expect(elem).not.toBeNull(); - const cnt = await loc.count(); - expect(cnt).toBe(1); + await expect(doTestCount()).resolves.toBe(1); }); }); @@ -74,38 +84,20 @@ describe("Calendar module", () => { describe("Exdate: LA crossover DST before midnight GMT", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_la_before_midnight.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); - expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); - const elem = loc.first(); - await elem.waitFor(); - expect(elem).not.toBeNull(); - const cnt = await loc.count(); - expect(cnt).toBe(2); + await expect(doTestCount()).resolves.toBe(2); }); }); describe("Exdate: LA crossover DST at midnight GMT local STD", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_std.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); - expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); - const elem = loc.first(); - await elem.waitFor(); - expect(elem).not.toBeNull(); - const cnt = await loc.count(); - expect(cnt).toBe(2); + await expect(doTestCount()).resolves.toBe(2); }); }); describe("Exdate: LA crossover DST at midnight GMT local DST", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_dst.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); - expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); - const elem = loc.first(); - await elem.waitFor(); - expect(elem).not.toBeNull(); - const cnt = await loc.count(); - expect(cnt).toBe(2); + await expect(doTestCount()).resolves.toBe(2); }); }); @@ -122,37 +114,19 @@ describe("Calendar module", () => { describe("Exdate: SYD crossover DST before midnight GMT", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_before_midnight.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); - expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); - const elem = loc.first(); - await elem.waitFor(); - expect(elem).not.toBeNull(); - const cnt = await loc.count(); - expect(cnt).toBe(2); + await expect(doTestCount()).resolves.toBe(2); }); }); describe("Exdate: SYD crossover DST at midnight GMT local STD", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_std.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); - expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); - const elem = loc.first(); - await elem.waitFor(); - expect(elem).not.toBeNull(); - const cnt = await loc.count(); - expect(cnt).toBe(2); + await expect(doTestCount()).resolves.toBe(2); }); }); describe("Exdate: SYD crossover DST at midnight GMT local DST", () => { it("SYD crossover DST at midnight GMT local DST should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); - expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); - const elem = loc.first(); - await elem.waitFor(); - expect(elem).not.toBeNull(); - const cnt = await loc.count(); - expect(cnt).toBe(2); + await expect(doTestCount()).resolves.toBe(2); }); }); }); From ea3a323581b1bb3a97a53b6a535549d9abf53e99 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Tue, 17 Sep 2024 01:01:49 -0500 Subject: [PATCH 095/418] add fix for sliceMultiDayEvents (#3543) sliceMultiDayEvents occasionally gets the number of events wrong and produces too many rows Math.ceil() rounds up over 1.04 so we get an abnormal count then the calcs for the midnight loop control used different moment() functions, producing different results fixes #3542 --- CHANGELOG.md | 1 + modules/default/calendar/calendar.js | 5 +- .../modules/calendar/sliceMultiDayEvents.js | 30 ++++++++++ tests/electron/modules/calendar_spec.js | 18 ++++++ tests/mocks/sliceMultiDayEvents.ics | 58 +++++++++++++++++++ 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 tests/configs/modules/calendar/sliceMultiDayEvents.js create mode 100644 tests/mocks/sliceMultiDayEvents.ics diff --git a/CHANGELOG.md b/CHANGELOG.md index b601450f47..9741ac3f1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] add check for node_helper loading for multiple instances of same module (#3502) - [weather] Fixed issue for respecting unit config on broadcasted notifications - [tests] Fixes calendar test by moving it from e2e to electron with fixed date (#3532) +- [calendar] fixed sliceMultiDayEvents getting wrong count and displaying incorrect entries, Europe/Berlin (#3542) ## [2.28.0] - 2024-07-01 diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 31ad4f5ea0..f952bc5956 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -636,7 +636,7 @@ Module.register("calendar", { * if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days, * otherwise, esp. in dateheaders mode it is not clear how long these events are. */ - const maxCount = Math.ceil((event.endDate - 1 - moment(event.startDate, "x").endOf("day").format("x")) / ONE_DAY) + 1; + const maxCount = Math.round((event.endDate - 1 - moment(event.startDate, "x").endOf("day").format("x")) / ONE_DAY) + 1; if (this.config.sliceMultiDayEvents && maxCount > 1) { const splitEvents = []; let midnight @@ -644,6 +644,7 @@ Module.register("calendar", { .clone() .startOf("day") .add(1, "day") + .endOf("day") .format("x"); let count = 1; while (event.endDate > midnight) { @@ -656,7 +657,7 @@ Module.register("calendar", { event.startDate = midnight; count += 1; - midnight = moment(midnight, "x").add(1, "day").format("x"); // next day + midnight = moment(midnight, "x").add(1, "day").endOf("day").format("x"); // next day } // Last day event.title += ` (${count}/${maxCount})`; diff --git a/tests/configs/modules/calendar/sliceMultiDayEvents.js b/tests/configs/modules/calendar/sliceMultiDayEvents.js new file mode 100644 index 0000000000..ebcf2cec4f --- /dev/null +++ b/tests/configs/modules/calendar/sliceMultiDayEvents.js @@ -0,0 +1,30 @@ +let config = { + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + hideDuplicates: false, + maximumEntries: 100, + sliceMultiDayEvents: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/sliceMultiDayEvents.ics" + } + ] + } + } + ] +}; + +Date.now = () => { + return new Date("01 Sept 2024 10:38:00 GMT+2:00").valueOf(); +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 5624b51b23..8731c3cd1a 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -129,4 +129,22 @@ describe("Calendar module", () => { await expect(doTestCount()).resolves.toBe(2); }); }); + + /* + * RRULE TESTS: + * Add any tests that check rrule functionality here. + */ + describe("sliceMultiDayEvents", () => { + it("Issue #3452 split multiday in Europe", async () => { + await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + const cnt = await loc.count(); + expect(cnt).toBe(6); + }); + }); + }); diff --git a/tests/mocks/sliceMultiDayEvents.ics b/tests/mocks/sliceMultiDayEvents.ics new file mode 100644 index 0000000000..d477246f16 --- /dev/null +++ b/tests/mocks/sliceMultiDayEvents.ics @@ -0,0 +1,58 @@ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:Dirk Test +X-WR-TIMEZONE:Europe/Berlin +BEGIN:VEVENT +DTSTART;VALUE=DATE:20240918 +DTEND;VALUE=DATE:20240919 +DTSTAMP:20240916T084410Z +UID:2crbv1ijljc2kt9jclkgu5hqa0@google.com +CREATED:20240916T083831Z +LAST-MODIFIED:20240916T083831Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:1 day single +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20240919 +DTEND;VALUE=DATE:20240920 +RRULE:FREQ=YEARLY +DTSTAMP:20240916T084410Z +UID:6gb19havnq6vp2qput51e5rmml@google.com +CREATED:20240916T083850Z +LAST-MODIFIED:20240916T083850Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:1 day repeat +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20240920 +DTEND;VALUE=DATE:20240922 +DTSTAMP:20240916T084410Z +UID:06e9u1trbqi3jbvstvq4qqutau@google.com +CREATED:20240916T083902Z +LAST-MODIFIED:20240916T083902Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:2 day single +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20240923 +DTEND;VALUE=DATE:20240925 +RRULE:FREQ=YEARLY +DTSTAMP:20240916T084410Z +UID:0ui78rk6hpcv8rmbb6nuonhmgg@google.com +CREATED:20240916T083919Z +LAST-MODIFIED:20240916T083919Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:2 day repeat +TRANSP:TRANSPARENT +END:VEVENT +END:VCALENDAR \ No newline at end of file From d9f9f41e988dbb2ba4fc9342f5be3916ff706a0e Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 18 Sep 2024 07:37:09 +0200 Subject: [PATCH 096/418] Add spell check (#3544) I felt like adding a spell checker, but it's okay if you find it superfluous. At least then we could fix the found spell issues. What is still missing is an automatic integration so that the spell checker does not have to be called manually. Would it perhaps make sense to always do it before a release? --- CHANGELOG.md | 30 +- README.md | 2 +- cspell.config.json | 226 +++ js/check_config.js | 2 +- js/main.js | 14 +- js/server_functions.js | 18 +- js/translator.js | 6 +- js/utils.js | 4 +- package-lock.json | 1264 +++++++++++++++-- package.json | 2 + tests/e2e/animateCSS_spec.js | 2 +- tests/e2e/modules/weather_hourly_spec.js | 4 +- tests/e2e/modules_display_spec.js | 2 +- tests/e2e/serveronly_spec.js | 2 +- tests/electron/modules/compliments_spec.js | 2 +- tests/unit/functions/server_functions_spec.js | 4 +- .../default/weather/weather_utils_spec.js | 2 +- 17 files changed, 1439 insertions(+), 147 deletions(-) create mode 100644 cspell.config.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 9741ac3f1f..fb6ac2d10b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ _This release is scheduled to be released on 2024-10-01._ ### Added +- [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues + ### Removed - [core] removed installer only files (#3492) @@ -59,7 +61,7 @@ Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @W ### Fixed -- [core] Fixed crash possibility if `module: ` is not defined and on `postion: ` mistake (#3445) +- [core] Fixed crash possibility if `module: ` is not defined and on `position: ` mistake (#3445) - [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) - [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) - [weather] Fixed type=daily for provider openmeteo showing nightly icons in forecast when current time is "nightly" (#3458) @@ -98,7 +100,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T ### Fixed -- Correct apibase of weathergov weatherprovider to match documentation (#2926) +- Correct apiBase of weathergov weatherProvider to match documentation (#2926) - Worked around several issues in the RRULE library that were causing deleted calender events to still show, some initial and recurring events to not show, and some event times to be off an hour. (#3291) - Skip changelog requirement when running tests for dependency updates (#3320) @@ -164,8 +166,8 @@ This release also marks the latest release by Michael Teeuw. For more info, plea - Fix issue template (#3167) - Fix #3256 filter out bad results from rrule.between - Fix calendar events sometimes not respecting deleted events (#3250) -- Fix electron loadurl locally on Windows when address "0.0.0.0" (#2550) -- Fix updatanotification (update_helper.js): catch error if response is not an JSON format (check PM2) +- Fix electron loadURL locally on Windows when address "0.0.0.0" (#2550) +- Fix updatenotification (update_helper.js): catch error if response is not an JSON format (check PM2) - Fix missing typeof in calendar module - Fix style issues after prettier update - Fix calendar test (#3291) by moving "Exdate check" from e2e to electron to run on a Thursday @@ -423,7 +425,7 @@ Special thanks to the following contributors: @eouia, @khassel, @kolbyjack, @Kri ### Added -- Added a new config option `httpHeaders` used by helmet (see https://helmetjs.github.io/). You can now set own httpHeaders which will override the defaults in `js/defauls.js` which is useful e.g. if you want to embed MagicMirror into annother website (solves #2847). +- Added a new config option `httpHeaders` used by helmet (see https://helmetjs.github.io/). You can now set own httpHeaders which will override the defaults in `js/defaults.js` which is useful e.g. if you want to embed MagicMirror into another website (solves #2847). - Show endDate for calendar events when dateHeader is enabled and showEnd is set to true (#2192). - Added the notification emitting from the weather module on information updated. - Use recommended file extension for YAML files (#2864). @@ -472,7 +474,7 @@ Special thanks to the following contributors: @10bias, @CFenner, @JHWelch, @k1rd - Fix minor console output issue for loading translations (#2814). - Don't adjust startDate for full day events if endDate is in the past. - Fix windspeed conversion error in openweathermap provider. (#2812) -- Fix conflicting parms turning off showEnd for full day events. (#2629) +- Fix conflicting parameter turning off showEnd for full day events. (#2629) - Fix regression, calendar.maximumEntries not used to filter calendar level entries (#2868) ## [2.18.0] - 2022-01-01 @@ -504,7 +506,7 @@ Special thanks to the following contributors: @AmpioRosso, @eouia, @fewieden, @j ### Fixed - Fixed wrong file `kr.json` to `ko.json`. Use language code 'ko' instead of 'kr' for Korean language. -- Fixed `feels_like` data from openweathermaps current weather being ignored (#2678). +- Fixed `feels_like` data from openweathermap's current weather being ignored (#2678). - Fixed chaotic newsfeed display after network connection loss thanks to @jalibu (#2638). - Fixed incorrect time zone correction of recurring full day events (#2632 and #2634). - Fixed e2e tests by increasing testTimeout. @@ -541,7 +543,7 @@ Special thanks to the following contributors: @apiontek, @eouia, @jupadin, @khas - Updated github templates. - Actually test all js and css files when lint script is run. - Updated jsdocs and print warnings during testing too. -- Updated weathergov provider to try fetching not just current, but also foreacst, when API URLs available. +- Updated weathergov provider to try fetching not just current, but also forecast, when API URLs available. - Refactored clock layout. - Refactored methods from weather-providers into weatherobject (isDaytime, updateSunTime). - Use of `logger.js` in jest tests. @@ -891,7 +893,7 @@ Special thanks to @sdetweil for all his great contributions! ### Updated - Updated lower bound of `lodash` and `helmet` dependencies for security patches. -- Updated compliments.js to handle newline in text, as textfields to not interpolate contents. +- Updated compliments.js to handle newline in text, as text fields to not interpolate contents. - Updated raspberry.sh installer script to handle new platform issues, split node/npm, pm2, and screen saver changes. - Improve handling for armv6l devices, where electron support has gone away, add optional serveronly config option. - Improved run-start.sh to handle for serveronly mode, by choice, or when electron not available. @@ -1112,7 +1114,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Fixed close dates to be absolute, if no configured in the config.js - module Calendar - Fixed the updatenotification module message about new commits in the repository, so they can be correctly localized in singular and plural form. - Fix for weatherforecast rainfall rounding [#1374](https://github.com/MagicMirrorOrg/MagicMirror/issues/1374) -- Fix calendar parsing issue for Midori on RasperryPi Zero w, related to issue #694. +- Fix calendar parsing issue for Midori on Raspberry Pi Zero w, related to issue #694. - Fix weather city ID link in sample config - Fixed issue with clientonly not updating with IP address and port provided on command line. @@ -1167,7 +1169,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Fixed weatherforecast to use dt_txt field instead of dt to handle timezones better - Newsfeed now remembers to show the description when `"ARTICLE_LESS_DETAILS"` is called if the user wants to always show the description. [#1282](https://github.com/MagicMirrorOrg/MagicMirror/issues/1282) - `clientonly/*.js` is now linted, and one linting error is fixed -- Fix issue #1196 by changing underscore to hyphen in locale id, in align with momentjs. +- Fix issue #1196 by changing underscore to hyphen in locale id, in align with moment.js. - Fixed issue where heat index and wind chill were reporting incorrect values in Kelvin. [#1263](https://github.com/MagicMirrorOrg/MagicMirror/issues/1263) ### Updated @@ -1192,7 +1194,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Implement Danger.js to notify contributors when CHANGELOG.md is missing in PR. - Allow scrolling in full page article view of default newsfeed module with gesture events from [MMM-Gestures](https://github.com/thobach/MMM-Gestures) - Changed 'compliments.js' - Updated DOM if remote compliments are loaded instead of waiting one updateInterval to show custom compliments -- Automated unit tests utils, deprecated, translator, cloneObject(lockstrings) +- Automated unit tests utils, deprecated, translator, cloneObject(lockStrings) - Automated integration tests translations - Add advanced filtering to the excludedEvents configuration of the default calendar module - New currentweather module config option: `showFeelsLike`: Shows how it actually feels like. (wind chill or heat index) @@ -1296,7 +1298,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Fixed - Fixed issue with incorrect alignment of analog clock when displayed in the center column of the MM. -- Fixed ipWhitelist behaviour to make empty whitelist ([]) allow any and all hosts access to the MM. +- Fixed ipWhitelist behavior to make empty whitelist ([]) allow any and all hosts access to the MM. - Fixed issue with calendar module where 'excludedEvents' count towards 'maximumEntries'. - Fixed issue with calendar module where global configuration of maximumEntries was not overridden by calendar specific config (see module doc). - Fixed issue where `this.file(filename)` returns a path with two hashes. @@ -1401,7 +1403,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we - Added multiple calendar icon support. - Added tests for Translations, dev argument, version, dev console. - Added test anytime feature compliments module. -- Added test ipwhitelist configuration directive. +- Added test ipWhitelist configuration directive. - Added test for calendar module: default, basic-auth, backward compatibility, fail-basic-auth. - Added meta tags to support fullscreen mode on iOS (for server mode) - Added `ignoreOldItems` and `ignoreOlderThan` options to the News Feed module diff --git a/README.md b/README.md index 9734cccef7..751637ca8b 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ For the full contribution guidelines, check out: [https://docs.magicmirror.build ## Enjoying MagicMirror? Consider a donation! -MagicMirror² is opensource and free. That doesn't mean we don't need any money. +MagicMirror² is Open Source and free. That doesn't mean we don't need any money. Please consider a donation to help us cover the ongoing costs like webservers and email services. If we receive enough donations we might even be able to free up some working hours and spend some extra time improving the MagicMirror² core. diff --git a/cspell.config.json b/cspell.config.json new file mode 100644 index 0000000000..bbb26dfcf1 --- /dev/null +++ b/cspell.config.json @@ -0,0 +1,226 @@ +{ + "version": "0.2", + "language": "en", + "words": [ + "aarch", + "Alvinger", + "Ampio", + "andrezibaia", + "angeldeejay", + "apiontek", + "armv", + "ashishtank", + "autoplay", + "beada", + "Binney", + "bluemanos", + "bnitkin", + "bokmål", + "Brasileiro", + "Brento", + "browserwindow", + "bryanzzhu", + "btoconnor", + "bugsounet", + "buxxi", + "byday", + "calendarfetcherutils", + "calendarutils", + "chamakura", + "cjbrunner", + "clientonly", + "clockfaces", + "cmdline", + "codac", + "Crazylegstoo", + "crazyscot", + "Creepin", + "currentweather", + "customregions", + "Cymraeg", + "dariom", + "darksky", + "dateheader", + "dateheaders", + "davide", + "DAYAFTERTOMORROW", + "DAYBEFOREYESTERDAY", + "defaultmodules", + "dgoth", + "DTEND", + "Duffman", + "earlman", + "easyas", + "eddiehung", + "Edgardos", + "Ekristoffe", + "envcanada", + "envsub", + "envsubst", + "eouia", + "exdate", + "expectedheaders", + "ezeholz", + "Faizan", + "feedme", + "feelslike", + "Fenner", + "fewieden", + "fixuppm", + "flopp", + "fontawesome", + "fontface", + "forecastweather", + "fortawesome", + "frameguard", + "Frysk", + "fulldate", + "fullday", + "fullscreen", + "Gevoelstemperatuur", + "ghsas", + "grenagit", + "Hirschberger", + "hourlyweather", + "Hwind", + "ical", + "illimarkangur", + "Ingan", + "ipfilter", + "ismarslomic", + "jakemulley", + "jakobsarwary", + "jalibu", + "jetson", + "jkriegshauser", + "jsdocs", + "jsonlint", + "jupadin", + "kaennchenstruggle", + "kenzal", + "Keyport", + "khassel", + "Kingdon", + "kioskmode", + "klaernie", + "kleinmantara", + "Kmph", + "Knapoc", + "Koepke", + "kolbyjack", + "krekos", + "Kristjan", + "krukle", + "larryare", + "letsencrypt", + "Lightspeed", + "locationforecast", + "lockstring", + "lstrip", + "Luciella", + "luxon", + "lxsession", + "magicmirror", + "martingron", + "marvai", + "mastermerge", + "Meteo", + "michaelteeuw", + "michmich", + "Midori", + "mirontoli", + "MISSINGLANG", + "MMPM", + "modernizr", + "modulename", + "multiday", + "Mystara", + "Ñandú", + "nathannaveen", + "naveensrinivasan", + "ndom", + "Nerfzooka", + "NEWSFEED", + "newsitems", + "nfogal", + "njwilliams", + "Norsk", + "nunjuck", + "odroid", + "oemel", + "onecall", + "onevent", + "openmeteo", + "openweathermap", + "oraclesean", + "oscarb", + "philnagel", + "Português", + "PRECIP", + "Problema", + "psieg", + "radokristof", + "rajniszp", + "Reis", + "rejas", + "Resig", + "roboto", + "rohitdharavath", + "Rosso", + "rrule", + "sdetweil", + "sendheaders", + "serveronly", + "SMHI", + "Snille", + "socketclient", + "socketio", + "spectron", + "Starinvest", + "sthuber", + "Stieber", + "stylelintrc", + "subclassing", + "sunaction", + "suncalc", + "suntimes", + "systeminformation", + "tada", + "taglist", + "Teeuw", + "thomasrockhu", + "tomzt", + "ukmetoffice", + "ukmetofficedatahub", + "unitless", + "unparseable", + "updatenotification", + "Vaice", + "veeck", + "VEVENT", + "vgtu", + "Voelt", + "vppencilsharpener", + "Wallys", + "Weatherbit", + "WEATHERDATA", + "Weatherflow", + "weatherforecast", + "weathergov", + "weathericons", + "weatherobject", + "weatherutils", + "windspeed", + "Woolridge", + "worktree", + "xlarge", + "xrandr", + "xsmall", + "xwindows", + "xxxe", + "Ybbet", + "yearmatchgroup" + ], + "ignorePaths": ["node_modules/**", "modules/**", "vendor/node_modules/**", "translations/**", "tests/mocks/**", "tests/e2e/modules/clock_es_spec.js", "fonts/roboto.css"], + "dictionaries": ["node"] +} diff --git a/js/check_config.js b/js/check_config.js index 2df47b7df8..c8e4387654 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -70,7 +70,7 @@ function checkConfigFile () { Log.info("Checking modules structure configuration... "); const position_list = Utils.getModulePositions(); - // Make Ajv schema confguration of modules config + // Make Ajv schema configuration of modules config // only scan "module" and "position" const schema = { type: "object", diff --git a/js/main.js b/js/main.js index e50a67f0fc..c3f783e1ef 100644 --- a/js/main.js +++ b/js/main.js @@ -286,9 +286,9 @@ const MM = (function () { Log.debug(`${module.identifier} Force remove animateIn (in hide): ${module.hasAnimateIn}`); module.hasAnimateIn = false; } - // haveAnimateName for verify if we are using AninateCSS library + // haveAnimateName for verify if we are using AnimateCSS library // we check AnimateCSSOut Array for validate it - // and finaly return the animate name or `null` (for default MM² animation) + // and finally return the animate name or `null` (for default MM² animation) let haveAnimateName = null; // check if have valid animateOut in module definition (module.data.animateOut) if (module.data.animateOut && AnimateCSSOut.indexOf(module.data.animateOut) !== -1) haveAnimateName = module.data.animateOut; @@ -357,7 +357,7 @@ const MM = (function () { } } - // Check if there are no more lockstrings set, or the force option is set. + // Check if there are no more lockStrings set, or the force option is set. // Otherwise cancel show action. if (module.lockStrings.length !== 0 && options.force !== true) { Log.log(`Will not show ${module.name}. LockStrings active: ${module.lockStrings.join(",")}`); @@ -380,7 +380,7 @@ const MM = (function () { module.hidden = false; - // If forced show, clean current lockstrings. + // If forced show, clean current lockStrings. if (module.lockStrings.length !== 0 && options.force === true) { Log.log(`Force show of module: ${module.name}`); module.lockStrings = []; @@ -390,9 +390,9 @@ const MM = (function () { if (moduleWrapper !== null) { clearTimeout(module.showHideTimer); - // haveAnimateName for verify if we are using AninateCSS library + // haveAnimateName for verify if we are using AnimateCSS library // we check AnimateCSSIn Array for validate it - // and finaly return the animate name or `null` (for default MM² animation) + // and finally return the animate name or `null` (for default MM² animation) let haveAnimateName = null; // check if have valid animateOut in module definition (module.data.animateIn) if (module.data.animateIn && AnimateCSSIn.indexOf(module.data.animateIn) !== -1) haveAnimateName = module.data.animateIn; @@ -702,7 +702,7 @@ const MM = (function () { showModule(module, speed, callback, options); }, - // return all available module postions. + // Return all available module positions. getAvailableModulePositions: modulePositions }; }()); diff --git a/js/server_functions.js b/js/server_functions.js index 7d4358b2e5..73d11c0464 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -45,12 +45,12 @@ async function cors (req, res) { url = match[1]; const headersToSend = getHeadersToSend(req.url); - const expectedRecievedHeaders = geExpectedRecievedHeaders(req.url); + const expectedReceivedHeaders = geExpectedReceivedHeaders(req.url); Log.log(`cors url: ${url}`); const response = await fetch(url, { headers: headersToSend }); - for (const header of expectedRecievedHeaders) { + for (const header of expectedReceivedHeaders) { const headerValue = response.headers.get(header); if (header) res.set(header, headerValue); } @@ -89,16 +89,16 @@ function getHeadersToSend (url) { * @param {string} url - The url containing the expected headers from the response. * @returns {string[]} headers - The name of the expected headers. */ -function geExpectedRecievedHeaders (url) { - const expectedRecievedHeaders = ["Content-Type"]; - const expectedRecievedHeadersMatch = new RegExp("expectedheaders=(.+?)(&|$)", "g").exec(url); - if (expectedRecievedHeadersMatch) { - const headers = expectedRecievedHeadersMatch[1].split(","); +function geExpectedReceivedHeaders (url) { + const expectedReceivedHeaders = ["Content-Type"]; + const expectedReceivedHeadersMatch = new RegExp("expectedheaders=(.+?)(&|$)", "g").exec(url); + if (expectedReceivedHeadersMatch) { + const headers = expectedReceivedHeadersMatch[1].split(","); for (const header of headers) { - expectedRecievedHeaders.push(header); + expectedReceivedHeaders.push(header); } } - return expectedRecievedHeaders; + return expectedReceivedHeaders; } /** diff --git a/js/translator.js b/js/translator.js index e742eb9c3b..f420fbed1e 100644 --- a/js/translator.js +++ b/js/translator.js @@ -15,14 +15,14 @@ const Translator = (function () { xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { // needs error handler try/catch at least - let fileinfo = null; + let fileInfo = null; try { - fileinfo = JSON.parse(xhr.responseText); + fileInfo = JSON.parse(xhr.responseText); } catch (exception) { // nothing here, but don't die Log.error(` loading json file =${file} failed`); } - resolve(fileinfo); + resolve(fileInfo); } }; xhr.send(null); diff --git a/js/utils.js b/js/utils.js index a8211a3a7b..5163997195 100644 --- a/js/utils.js +++ b/js/utils.js @@ -42,7 +42,7 @@ module.exports = { return modulePositions; }, - // return if postion is on modulePositions Array (true/false) + // return if position is on modulePositions Array (true/false) moduleHasValidPosition (position) { if (this.getAvailableModulePositions().indexOf(position) === -1) return false; return true; @@ -57,7 +57,7 @@ module.exports = { const results = regionRegEx.exec(line); // if the regex returned something if (results && results.length > 0) { - // get the postition parts and replace space with underscore + // get the position parts and replace space with underscore const positionName = results[1].replace(" ", "_"); // add it to the list modulePositions.push(positionName); diff --git a/package-lock.json b/package-lock.json index 2acfed7408..5a430cf916 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ }, "devDependencies": { "@stylistic/eslint-plugin": "^2.8.0", + "cspell": "^8.14.3", "eslint-plugin-import": "^2.30.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.2.3", @@ -713,6 +714,551 @@ "dev": true, "license": "MIT" }, + "node_modules/@cspell/cspell-bundled-dicts": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.14.3.tgz", + "integrity": "sha512-O0QA2OD0IDatIxNinr5woWJ8uC3/fbMaOdu3R+142wMX3f2hB08Wfvk+anFgFVTgo90JQnmKEvlCZD1Q8QlWig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-ada": "^4.0.2", + "@cspell/dict-aws": "^4.0.4", + "@cspell/dict-bash": "^4.1.4", + "@cspell/dict-companies": "^3.1.4", + "@cspell/dict-cpp": "^5.1.16", + "@cspell/dict-cryptocurrencies": "^5.0.0", + "@cspell/dict-csharp": "^4.0.2", + "@cspell/dict-css": "^4.0.13", + "@cspell/dict-dart": "^2.2.1", + "@cspell/dict-django": "^4.1.0", + "@cspell/dict-docker": "^1.1.7", + "@cspell/dict-dotnet": "^5.0.5", + "@cspell/dict-elixir": "^4.0.3", + "@cspell/dict-en_us": "^4.3.23", + "@cspell/dict-en-common-misspellings": "^2.0.4", + "@cspell/dict-en-gb": "1.1.33", + "@cspell/dict-filetypes": "^3.0.4", + "@cspell/dict-flutter": "^1.0.0", + "@cspell/dict-fonts": "^4.0.0", + "@cspell/dict-fsharp": "^1.0.1", + "@cspell/dict-fullstack": "^3.2.0", + "@cspell/dict-gaming-terms": "^1.0.5", + "@cspell/dict-git": "^3.0.0", + "@cspell/dict-golang": "^6.0.12", + "@cspell/dict-google": "^1.0.1", + "@cspell/dict-haskell": "^4.0.1", + "@cspell/dict-html": "^4.0.5", + "@cspell/dict-html-symbol-entities": "^4.0.0", + "@cspell/dict-java": "^5.0.7", + "@cspell/dict-julia": "^1.0.1", + "@cspell/dict-k8s": "^1.0.6", + "@cspell/dict-latex": "^4.0.0", + "@cspell/dict-lorem-ipsum": "^4.0.0", + "@cspell/dict-lua": "^4.0.3", + "@cspell/dict-makefile": "^1.0.0", + "@cspell/dict-monkeyc": "^1.0.6", + "@cspell/dict-node": "^5.0.1", + "@cspell/dict-npm": "^5.1.4", + "@cspell/dict-php": "^4.0.10", + "@cspell/dict-powershell": "^5.0.8", + "@cspell/dict-public-licenses": "^2.0.8", + "@cspell/dict-python": "^4.2.6", + "@cspell/dict-r": "^2.0.1", + "@cspell/dict-ruby": "^5.0.3", + "@cspell/dict-rust": "^4.0.5", + "@cspell/dict-scala": "^5.0.3", + "@cspell/dict-software-terms": "^4.1.3", + "@cspell/dict-sql": "^2.1.5", + "@cspell/dict-svelte": "^1.0.2", + "@cspell/dict-swift": "^2.0.1", + "@cspell/dict-terraform": "^1.0.1", + "@cspell/dict-typescript": "^3.1.6", + "@cspell/dict-vue": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-json-reporter": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.14.3.tgz", + "integrity": "sha512-xJbIhSVL1LrwtIpFYvfbXMXv0GUqp2mFkTdG652zb4ZCjQUitmAN1eOhpUt2WHqyCdsMNjMcoJ05PNAN1LrLBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-types": "8.14.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-pipe": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.14.3.tgz", + "integrity": "sha512-vc4gcsQ/qLHcHHz1EmTLe0x1aZYUzkQAyIOTLRWFlsWrdztXQ3zSEaPB2JzgLNCaqJrYJPs5Wh/Uo+6w9ZaIeA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-resolver": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.14.3.tgz", + "integrity": "sha512-SOG4LQS4rt93FnCyCsDfCxOuq+uTzco6zpncwMU1GgH8bSEEeiDphGsgmdgK7XxKNlr59o8JFeD+45AkJWHm5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-directory": "^4.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-service-bus": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.14.3.tgz", + "integrity": "sha512-bqb+6KlFMVEprBlga1olLmZFWmsT267hmLZHhQoNKTlZJlzyQjmAd4XYUJyH9oEYOOt4t5PgqtZJSxudmq2SIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-types": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.14.3.tgz", + "integrity": "sha512-t8cvWSLVmgoAnmwMKXf0W1k3aWPPksTIqcNFMVF2f3m4dZh9HBh+M+xK9mXXScALmQev+psbvbiTjRlKD52ZnQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/dict-ada": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.2.tgz", + "integrity": "sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-aws": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.4.tgz", + "integrity": "sha512-6AWI/Kkf+RcX/J81VX8+GKLeTgHWEr/OMhGk3dHQzWK66RaqDJCGDqi7494ghZKcBB7dGa3U5jcKw2FZHL/u3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-bash": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.4.tgz", + "integrity": "sha512-W/AHoQcJYn3Vn/tUiXX2+6D/bhfzdDshwcbQWv9TdiNlXP9P6UJjDKWbxyA5ogJCsR2D0X9Kx11oV8E58siGKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-companies": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.4.tgz", + "integrity": "sha512-y9e0amzEK36EiiKx3VAA+SHQJPpf2Qv5cCt5eTUSggpTkiFkCh6gRKQ97rVlrKh5GJrqinDwYIJtTsxuh2vy2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-cpp": { + "version": "5.1.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.16.tgz", + "integrity": "sha512-32fU5RkuOM55IRcxjByiSoKbjr+C4danDfYjHaQNRWdvjzJzci3fLDGA2wTXiclkgDODxGiV8LCTUwCz+3TNWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-cryptocurrencies": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.0.tgz", + "integrity": "sha512-Z4ARIw5+bvmShL+4ZrhDzGhnc9znaAGHOEMaB/GURdS/jdoreEDY34wdN0NtdLHDO5KO7GduZnZyqGdRoiSmYA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-csharp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz", + "integrity": "sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-css": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.13.tgz", + "integrity": "sha512-WfOQkqlAJTo8eIQeztaH0N0P+iF5hsJVKFuhy4jmARPISy8Efcv8QXk2/IVbmjJH0/ZV7dKRdnY5JFVXuVz37g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-dart": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.2.1.tgz", + "integrity": "sha512-yriKm7QkoPx3JPSSOcw6iX9gOb2N50bOo/wqWviqPYbhpMRh9Xiv6dkUy3+ot+21GuShZazO8X6U5+Vw67XEwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-data-science": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.1.tgz", + "integrity": "sha512-xeutkzK0eBe+LFXOFU2kJeAYO6IuFUc1g7iRLr7HeCmlC4rsdGclwGHh61KmttL3+YHQytYStxaRBdGAXWC8Lw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-django": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.0.tgz", + "integrity": "sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-docker": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.7.tgz", + "integrity": "sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-dotnet": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.5.tgz", + "integrity": "sha512-gjg0L97ee146wX47dnA698cHm85e7EOpf9mVrJD8DmEaqoo/k1oPy2g7c7LgKxK9XnqwoXxhLNnngPrwXOoEtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-elixir": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.3.tgz", + "integrity": "sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-en_us": { + "version": "4.3.23", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.23.tgz", + "integrity": "sha512-l0SoEQBsi3zDSl3OuL4/apBkxjuj4hLIg/oy6+gZ7LWh03rKdF6VNtSZNXWAmMY+pmb1cGA3ouleTiJIglbsIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-en-common-misspellings": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.4.tgz", + "integrity": "sha512-lvOiRjV/FG4pAGZL3PN2GCVHSTCE92cwhfLGGkOsQtxSmef6WCHfHwp9auafkBlX0yFQSKDfq6/TlpQbjbJBtQ==", + "dev": true, + "license": "CC BY-SA 4.0" + }, + "node_modules/@cspell/dict-en-gb": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz", + "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-filetypes": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.4.tgz", + "integrity": "sha512-IBi8eIVdykoGgIv5wQhOURi5lmCNJq0we6DvqKoPQJHthXbgsuO1qrHSiUVydMiQl/XvcnUWTMeAlVUlUClnVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-flutter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.0.0.tgz", + "integrity": "sha512-W7k1VIc4KeV8BjEBxpA3cqpzbDWjfb7oXkEb0LecBCBp5Z7kcfnjT1YVotTx/U9PGyAOBhDaEdgZACVGNQhayw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fonts": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.0.tgz", + "integrity": "sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fsharp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.0.1.tgz", + "integrity": "sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fullstack": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.0.tgz", + "integrity": "sha512-sIGQwU6G3rLTo+nx0GKyirR5dQSFeTIzFTOrURw51ISf+jKG9a3OmvsVtc2OANfvEAOLOC9Wfd8WYhmsO8KRDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-gaming-terms": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.5.tgz", + "integrity": "sha512-C3riccZDD3d9caJQQs1+MPfrUrQ+0KHdlj9iUR1QD92FgTOF6UxoBpvHUUZ9YSezslcmpFQK4xQQ5FUGS7uWfw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-git": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.0.tgz", + "integrity": "sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-golang": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.12.tgz", + "integrity": "sha512-LEPeoqd+4O+vceHF73S7D7+LYfrAjOvp4Dqzh4MT30ruzlQ77yHRSuYOJtrFN1GK5ntAt/ILSVOKg9sgsz1Llg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-google": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.1.tgz", + "integrity": "sha512-dQr4M3n95uOhtloNSgB9tYYGXGGEGEykkFyRtfcp5pFuEecYUa0BSgtlGKx9RXVtJtKgR+yFT/a5uQSlt8WjqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-haskell": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.1.tgz", + "integrity": "sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-html": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.5.tgz", + "integrity": "sha512-p0brEnRybzSSWi8sGbuVEf7jSTDmXPx7XhQUb5bgG6b54uj+Z0Qf0V2n8b/LWwIPJNd1GygaO9l8k3HTCy1h4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-html-symbol-entities": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.0.tgz", + "integrity": "sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-java": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.7.tgz", + "integrity": "sha512-ejQ9iJXYIq7R09BScU2y5OUGrSqwcD+J5mHFOKbduuQ5s/Eh/duz45KOzykeMLI6KHPVxhBKpUPBWIsfewECpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-julia": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.0.1.tgz", + "integrity": "sha512-4JsCLCRhhLMLiaHpmR7zHFjj1qOauzDI5ZzCNQS31TUMfsOo26jAKDfo0jljFAKgw5M2fEG7sKr8IlPpQAYrmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-k8s": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.6.tgz", + "integrity": "sha512-srhVDtwrd799uxMpsPOQqeDJY+gEocgZpoK06EFrb4GRYGhv7lXo9Fb+xQMyQytzOW9dw4DNOEck++nacDuymg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-latex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.0.tgz", + "integrity": "sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-lorem-ipsum": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.0.tgz", + "integrity": "sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-lua": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.3.tgz", + "integrity": "sha512-lDHKjsrrbqPaea13+G9s0rtXjMO06gPXPYRjRYawbNmo4E/e3XFfVzeci3OQDQNDmf2cPOwt9Ef5lu2lDmwfJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-makefile": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.0.tgz", + "integrity": "sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-monkeyc": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.6.tgz", + "integrity": "sha512-oO8ZDu/FtZ55aq9Mb67HtaCnsLn59xvhO/t2mLLTHAp667hJFxpp7bCtr2zOrR1NELzFXmKln/2lw/PvxMSvrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-node": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.1.tgz", + "integrity": "sha512-lax/jGz9h3Dv83v8LHa5G0bf6wm8YVRMzbjJPG/9rp7cAGPtdrga+XANFq+B7bY5+jiSA3zvj10LUFCFjnnCCg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-npm": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.4.tgz", + "integrity": "sha512-yzqVTY4P5neom4z9orV2IFOqDZ7fDotmisP7nwQkEmftoELgn5CUtNdnJhWDoDQQn6yrxOxA8jEqmyETIWzN4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-php": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.10.tgz", + "integrity": "sha512-NfTZdp6kcZDF1PvgQ6cY0zE4FUO5rSwNmBH/iwCBuaLfJAFQ97rgjxo+D2bic4CFwNjyHutnHPtjJBRANO5XQw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-powershell": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.8.tgz", + "integrity": "sha512-Eg64BccQp5oEJ+V/O2G27KaLWmuOL2AWMOs2470adUihOleRfW8j9XwAEGCS+JKSnDb2mksWA72Z6kDqH138IQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-public-licenses": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.8.tgz", + "integrity": "sha512-Sup+tFS7cDV0fgpoKtUqEZ6+fA/H+XUgBiqQ/Fbs6vUE3WCjJHOIVsP+udHuyMH7iBfJ4UFYOYeORcY4EaKdMg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-python": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.6.tgz", + "integrity": "sha512-Hkz399qDGEbfXi9GYa2hDl7GahglI86JmS2F1KP8sfjLXofUgtnknyC5NWc86nzHcP38pZiPqPbTigyDYw5y8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-data-science": "^2.0.1" + } + }, + "node_modules/@cspell/dict-r": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.1.tgz", + "integrity": "sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-ruby": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.3.tgz", + "integrity": "sha512-V1xzv9hN6u8r6SM4CkYdsxs4ov8gjXXo0Twfx5kWhLXbEVxTXDMt7ohLTqpy2XlF5mutixZdbHMeFiAww8v+Ug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-rust": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.5.tgz", + "integrity": "sha512-DIvlPRDemjKQy8rCqftAgGNZxY5Bg+Ps7qAIJjxkSjmMETyDgl0KTVuaJPt7EK4jJt6uCZ4ILy96npsHDPwoXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-scala": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.3.tgz", + "integrity": "sha512-4yGb4AInT99rqprxVNT9TYb1YSpq58Owzq7zi3ZS5T0u899Y4VsxsBiOgHnQ/4W+ygi+sp+oqef8w8nABR2lkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-software-terms": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.3.tgz", + "integrity": "sha512-5Wn5JG4IzCboX5pjISdkipsPKGaz1//iuBZdHl4US5x7mO4jOGXLpjzx6ZoPM4PXUlMEFz9NJRCDepAu8fXVtA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-sql": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.5.tgz", + "integrity": "sha512-FmxanytHXss7GAWAXmgaxl3icTCW7YxlimyOSPNfm+njqeUDjw3kEv4mFNDDObBJv8Ec5AWCbUDkWIpkE3IpKg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-svelte": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.2.tgz", + "integrity": "sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-swift": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.1.tgz", + "integrity": "sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-terraform": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.1.tgz", + "integrity": "sha512-29lmUUnZgPh+ieZ5hunick8hzNIpNRtiJh9vAusNskPCrig3RTW6u7F+GG1a8uyslbzSw+Irjf40PTOan1OJJA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-typescript": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.6.tgz", + "integrity": "sha512-1beC6O4P/j23VuxX+i0+F7XqPVc3hhiAzGJHEKqnWf5cWAXQtg0xz3xQJ5MvYx2a7iLaSa+lu7+05vG9UHyu9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-vue": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.0.tgz", + "integrity": "sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dynamic-import": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.14.3.tgz", + "integrity": "sha512-LlWDTfQO2V3CAwax5PlQnS2prLs0icWfaROaNrIoSe8X6OUerfoxJ9p3Bpx0AxSKv4FtvYQraRV/UNPWRhhHag==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-meta-resolve": "^4.1.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@cspell/filetypes": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.14.3.tgz", + "integrity": "sha512-a1BbKi3BcSju9owpa37x6I3sZtwpnzpRslSsV7IUBI8k85nfH+TiFm0toEEj/8jFJKehBWr83kMjZFHQReV13g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/strong-weak-map": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.14.3.tgz", + "integrity": "sha512-ZC5HiGbvD3vCA1pj7FL5gwyOi3OeXa51TDDRSjMW5A9XOpr57ptKxlSCwFVxNfszPTfMKP19a81rz1jo3GyFMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/url": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.14.3.tgz", + "integrity": "sha512-r7fVsgOBu1qpt4UH45mE3TZfW7H+CHzK3INRUjSsrWKaiyE57mD6IIoqYdjCDoP4xaMRrHGC5SBKy+eX3prsBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0" + } + }, "node_modules/@csstools/css-parser-algorithms": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", @@ -2513,6 +3059,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -3141,6 +3694,35 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk-template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz", + "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", @@ -3250,6 +3832,46 @@ "node": ">=0.8.0" } }, + "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/clear-module/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clear-module/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -3456,6 +4078,23 @@ "node": ">= 6" } }, + "node_modules/comment-json": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", + "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/comment-parser": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", @@ -3472,156 +4111,449 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/console-stamp": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-3.1.2.tgz", - "integrity": "sha512-ab66x3NxOTxPuq71dI6gXEiw2X6ql4Le5gZz0bm7FW3FSCB00eztra/oQUuCoCGlsyKOxtULnHwphzMrRtzMBg==", + "node_modules/console-stamp": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-3.1.2.tgz", + "integrity": "sha512-ab66x3NxOTxPuq71dI6gXEiw2X6ql4Le5gZz0bm7FW3FSCB00eztra/oQUuCoCGlsyKOxtULnHwphzMrRtzMBg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "dateformat": "^4.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/croner": { + "version": "4.1.97", + "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cspell": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.14.3.tgz", + "integrity": "sha512-GTok3s0J6hb8lXPgOkFcJ6+i91YS99AD5t60htNrq7Ae89BZByG20XPZc/6zbRN9eEQvtCx4OAIXnnfxP5QENw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-json-reporter": "8.14.3", + "@cspell/cspell-pipe": "8.14.3", + "@cspell/cspell-types": "8.14.3", + "@cspell/dynamic-import": "8.14.3", + "@cspell/url": "8.14.3", + "chalk": "^5.3.0", + "chalk-template": "^1.1.0", + "commander": "^12.1.0", + "cspell-dictionary": "8.14.3", + "cspell-gitignore": "8.14.3", + "cspell-glob": "8.14.3", + "cspell-io": "8.14.3", + "cspell-lib": "8.14.3", + "fast-glob": "^3.3.2", + "fast-json-stable-stringify": "^2.1.0", + "file-entry-cache": "^9.1.0", + "get-stdin": "^9.0.0", + "semver": "^7.6.3", + "strip-ansi": "^7.1.0" + }, + "bin": { + "cspell": "bin.mjs", + "cspell-esm": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" + } + }, + "node_modules/cspell-config-lib": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.14.3.tgz", + "integrity": "sha512-uQFhEvnMJBpZBoi5U5jcMdykze5Cng28RDq4jzM2bYR2aE0HKZfFS8Hsjf5SLDxxS7TAKhnDh5a0r+6T/G6+qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-types": "8.14.3", + "comment-json": "^4.2.5", + "yaml": "^2.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-dictionary": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.14.3.tgz", + "integrity": "sha512-FiTas0KXWXKyTJIRYZF7USp7Cjjq6RmzLKcDKAvJhc0XmbRaoYHW20IRkHVsrfO6bHTmo1fLoJQpvuDCkBiojg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-pipe": "8.14.3", + "@cspell/cspell-types": "8.14.3", + "cspell-trie-lib": "8.14.3", + "fast-equals": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-gitignore": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.14.3.tgz", + "integrity": "sha512-SOPYlaOh2tPSYZ48zGN9TzjaxnO05/AJMpvlvxUf0uASa2BOeogl11KvzcS7ig5MUnB/+s/2YsShcF+YjfptEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/url": "8.14.3", + "cspell-glob": "8.14.3", + "cspell-io": "8.14.3", + "find-up-simple": "^1.0.0" + }, + "bin": { + "cspell-gitignore": "bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-glob": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.14.3.tgz", + "integrity": "sha512-d12Dn/i6BRKQrvq0ikcBPBsjPdyemu2Ggw1WgWvxAlaGGZsoyC6Hn5ElQt6tQt2CruwUfPPXVm2+UMyHlRMt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/url": "8.14.3", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-grammar": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.14.3.tgz", + "integrity": "sha512-clb5HCVJn6wW/v7dC3CGuo1YmmXIVpvpz7BGwt2Rvybk/8o6CD3i4aF8TqnHc0FIWP0iHCwMhqnCyiOJtYI9Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-pipe": "8.14.3", + "@cspell/cspell-types": "8.14.3" + }, + "bin": { + "cspell-grammar": "bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-io": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.14.3.tgz", + "integrity": "sha512-8SWe553kpSsQ039SiFQ+G/87KoJn51W1yc42aGUwkuagglspEiUVj3bTlD3eVswZAT3KbG26Mti49L37Lecj/g==", + "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.2", - "dateformat": "^4.6.3" + "@cspell/cspell-service-bus": "8.14.3", + "@cspell/url": "8.14.3" }, "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" + "node_modules/cspell-lib": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.14.3.tgz", + "integrity": "sha512-hcpxyX+xZ1LbcuvT1H+zCjfmW04on6nsdkKTT0bRdsgxyw6O08hR2OVqQ9+oYiXdp6QccjOl6UPOS6dEZajOmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-bundled-dicts": "8.14.3", + "@cspell/cspell-pipe": "8.14.3", + "@cspell/cspell-resolver": "8.14.3", + "@cspell/cspell-types": "8.14.3", + "@cspell/dynamic-import": "8.14.3", + "@cspell/filetypes": "8.14.3", + "@cspell/strong-weak-map": "8.14.3", + "@cspell/url": "8.14.3", + "clear-module": "^4.1.2", + "comment-json": "^4.2.5", + "cspell-config-lib": "8.14.3", + "cspell-dictionary": "8.14.3", + "cspell-glob": "8.14.3", + "cspell-grammar": "8.14.3", + "cspell-io": "8.14.3", + "cspell-trie-lib": "8.14.3", + "env-paths": "^3.0.0", + "fast-equals": "^5.0.1", + "gensequence": "^7.0.0", + "import-fresh": "^3.3.0", + "resolve-from": "^5.0.0", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-uri": "^3.0.8", + "xdg-basedir": "^5.1.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/cspell-lib/node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/cspell-lib/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "node_modules/cspell-trie-lib": { + "version": "8.14.3", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.14.3.tgz", + "integrity": "sha512-90Rwt8Kzcv2HB2uuwUqMlCQVa7tpsqHtSFiGox3DTDUZWTikMiOwUigRvO17FsxxQL+qW4fIH4PUi4SGwins9Q==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.23.3" + "@cspell/cspell-pipe": "8.14.3", + "@cspell/cspell-types": "8.14.3", + "gensequence": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "node_modules/cspell/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cspell/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=18" } }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "node_modules/cspell/node_modules/file-entry-cache": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", "dev": true, "license": "MIT", "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" + "flat-cache": "^5.0.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=18" } }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "node_modules/cspell/node_modules/flat-cache": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" + "flatted": "^3.3.1", + "keyv": "^4.5.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/croner": { - "version": "4.1.97", - "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", - "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==", - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/cspell/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">= 8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/css-functions-list": { @@ -5185,6 +6117,16 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -5370,6 +6312,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", + "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -5522,6 +6477,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gensequence": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-7.0.0.tgz", + "integrity": "sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -5584,6 +6549,19 @@ "node": ">=8.0.0" } }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -5762,6 +6740,32 @@ "node": ">=10.0" } }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-directory/node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -5950,6 +6954,16 @@ "node": ">=8" } }, + "node_modules/has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -6243,6 +7257,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -9986,6 +11011,16 @@ "jsesc": "bin/jsesc" } }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/replace-last": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/replace-last/-/replace-last-1.2.6.tgz", @@ -12142,6 +13177,20 @@ "lodash": "^4.17.14" } }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true, + "license": "MIT" + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", @@ -12379,6 +13428,19 @@ } } }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", diff --git a/package.json b/package.json index 0c8f9dd0be..c82b472d25 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "test:js": "eslint .", "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json", "test:calendar": "node ./modules/default/calendar/debug.js", + "test:spelling": "cspell . --gitignore", "config:check": "node js/check_config.js", "lint:prettier": "prettier . --write", "lint:js": "eslint . --fix", @@ -75,6 +76,7 @@ }, "devDependencies": { "@stylistic/eslint-plugin": "^2.8.0", + "cspell": "^8.14.3", "eslint-plugin-import": "^2.30.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.2.3", diff --git a/tests/e2e/animateCSS_spec.js b/tests/e2e/animateCSS_spec.js index d7fcb52e44..b82a05712c 100644 --- a/tests/e2e/animateCSS_spec.js +++ b/tests/e2e/animateCSS_spec.js @@ -5,7 +5,7 @@ describe("AnimateCSS integration Test", () => { let testConfigFile = "tests/configs/modules/compliments/compliments_animateCSS.js"; // define config file to fallback to default: wrong animation name (must return no animation) let testConfigFileFallbackToDefault = "tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js"; - // define config file with an inversed name animation : in for out and vice versa (must return no animation) + // define config file with an inverted name animation : in for out and vice versa (must return no animation) let testConfigFileInvertedAnimationName = "tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js"; // define config file with no animation defined let testConfigByDefault = "tests/configs/modules/compliments/compliments_anytime.js"; diff --git a/tests/e2e/modules/weather_hourly_spec.js b/tests/e2e/modules/weather_hourly_spec.js index f61cee0546..861ff50f74 100644 --- a/tests/e2e/modules/weather_hourly_spec.js +++ b/tests/e2e/modules/weather_hourly_spec.js @@ -53,8 +53,8 @@ describe("Weather module: Weather Hourly Forecast", () => { }); describe("Shows precipitation probability", () => { - const propabilities = [undefined, undefined, "12 %", "36 %", "44 %"]; - for (const [index, pop] of propabilities.entries()) { + const probabilities = [undefined, undefined, "12 %", "36 %", "44 %"]; + for (const [index, pop] of probabilities.entries()) { if (pop) { it(`should render probability ${pop}`, async () => { await expect(weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td.precipitation-prob`, pop)).resolves.toBe(true); diff --git a/tests/e2e/modules_display_spec.js b/tests/e2e/modules_display_spec.js index c8dba6e9f8..88b9ff50be 100644 --- a/tests/e2e/modules_display_spec.js +++ b/tests/e2e/modules_display_spec.js @@ -12,7 +12,7 @@ describe("Display of modules", () => { it("should show the test header", async () => { const elem = await helpers.waitForElement("#module_0_helloworld .module-header"); expect(elem).not.toBeNull(); - // textContent gibt hier lowercase zurück, das uppercase wird durch css realisiert, was daher nicht in textContent landet + // textContent returns lowercase here, the uppercase is realized by CSS, which therefore does not end up in textContent expect(elem.textContent).toBe("test_header"); }); diff --git a/tests/e2e/serveronly_spec.js b/tests/e2e/serveronly_spec.js index c33a78d292..70db4aaa10 100644 --- a/tests/e2e/serveronly_spec.js +++ b/tests/e2e/serveronly_spec.js @@ -7,7 +7,7 @@ describe("App environment", () => { beforeAll(async () => { process.env.MM_CONFIG_FILE = "tests/configs/default.js"; serverProcess = await require("node:child_process").spawn("npm", ["run", "server"], { env: process.env, detached: true }); - // we have to wait until the server is startet + // we have to wait until the server is started await delay(2000); }); afterAll(async () => { diff --git a/tests/electron/modules/compliments_spec.js b/tests/electron/modules/compliments_spec.js index ac162fd9ce..15c3c37c08 100644 --- a/tests/electron/modules/compliments_spec.js +++ b/tests/electron/modules/compliments_spec.js @@ -51,7 +51,7 @@ describe("Compliments module", () => { }); }); - describe("Test all date events shown without neww property", () => { + describe("Test all date events shown without new property", () => { it("shows 'any message' on May 6", async () => { await helpers.startApplication("tests/configs/modules/compliments/compliments_specialDayUnique_false.js", "06 May 2022 10:00:00 GMT"); await expect(doTest(["Special day message", "Typical message 1", "Typical message 2", "Typical message 3"])).resolves.toBe(true); diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index f5fb98f2f0..eb4e138d01 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -45,7 +45,7 @@ describe("server_functions tests", () => { expect(fetchMock.mock.calls[0][0]).toBe(urlToCall); }); - it("Forewards Content-Type if json", async () => { + it("Forwards Content-Type if json", async () => { fetchResponseHeadersGet.mockImplementation(() => "json"); await cors(request, corsResponse); @@ -58,7 +58,7 @@ describe("server_functions tests", () => { expect(corsResponse.set.mock.calls[0][1]).toBe("json"); }); - it("Forewards Content-Type if xml", async () => { + it("Forwards Content-Type if xml", async () => { fetchResponseHeadersGet.mockImplementation(() => "xml"); await cors(request, corsResponse); diff --git a/tests/unit/modules/default/weather/weather_utils_spec.js b/tests/unit/modules/default/weather/weather_utils_spec.js index a0c41edb05..979fba2fa8 100644 --- a/tests/unit/modules/default/weather/weather_utils_spec.js +++ b/tests/unit/modules/default/weather/weather_utils_spec.js @@ -47,7 +47,7 @@ describe("Weather utils tests", () => { expect(WeatherUtils.calculateFeelsLike(0, 20, 40)).toBe(-9.444444444444445); }); - it("should return a calculated feelsLike info (positiv value)", () => { + it("should return a calculated feelsLike info (positive value)", () => { expect(WeatherUtils.calculateFeelsLike(30, 0, 60)).toBe(32.8320322777777); }); }); From 659e0c74cb00a5bff98ffea1d19181ed6faf58ef Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 18 Sep 2024 19:10:46 +0200 Subject: [PATCH 097/418] =?UTF-8?q?add=20new=20env=20vars=20MM=5FMODULES?= =?UTF-8?q?=5FDIR=20and=20MM=5FCUSTOMCSS=5FFILE=20=E2=80=A6=20(#3530)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … for setting these things from outside (and overriding corresponding config.js properties `config.foreignModulesDir` and `customCss`) - remove elements from index.html when loading script or stylesheet files fails - removed `config.paths.vendor` (could never work because `vendor` is hardcoded in `index.html`) and renamed `config.paths.modules` to `config.foreignModulesDir`. The `config.paths. ...` properties were implemented in the initial commit in `js/defaults.js` but were never functional. - fixes `app.js` which didn't respect `config.paths.modules` before - as `modules/defaults` is directly set in many places in the source code restrict `config.paths.modules` to foreign modules (it has never worked for default modules), now renamed to `config.foreignModulesDir` - adds new `/env` section in `server.js` for getting the new env vars in the browser - fixes TODO in `server.js` so test directories are now only published when running tests These changes allow changing some main paths from outside mm with the new env vars. You now **can** put all user stuff into one directory, e.g. the `config` dir: - `config.js` as before - `custom.css` - foreign modules This would simplify other setups e.g. the docker setup. At the moment we have to deal with 3 directories where 2 of them (`modules` and `css`) contains mixed stuff, which means mm owned files and user files. This can now simplified and leads to cleaner setups (if wanted). --- CHANGELOG.md | 2 ++ js/app.js | 4 +++- js/defaults.js | 8 ++------ js/loader.js | 26 ++++++++++++++++++++------ js/server.js | 12 ++++++++---- js/server_functions.js | 28 +++++++++++++++++++++++++++- 6 files changed, 62 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb6ac2d10b..62ad64e240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ _This release is scheduled to be released on 2024-10-01._ ### Added - [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues +- [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir` +- [core] elements are now removed from index.html when loading script or stylesheet files fails ### Removed diff --git a/js/app.js b/js/app.js index f6d510a64a..3bdf47ceca 100644 --- a/js/app.js +++ b/js/app.js @@ -9,6 +9,7 @@ const Log = require("logger"); const Server = require(`${__dirname}/server`); const Utils = require(`${__dirname}/utils`); const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`); +const { getEnvVarsAsObj } = require(`${__dirname}/server_functions`); // Get version number. global.version = require(`${__dirname}/../package.json`).version; @@ -159,7 +160,8 @@ function App () { function loadModule (module) { const elements = module.split("/"); const moduleName = elements[elements.length - 1]; - let moduleFolder = `${__dirname}/../modules/${module}`; + const env = getEnvVarsAsObj(); + let moduleFolder = `${__dirname}/../${env.modulesDir}/${module}`; if (defaultModules.includes(moduleName)) { moduleFolder = `${__dirname}/../modules/default/${module}`; diff --git a/js/defaults.js b/js/defaults.js index c4efa77e95..f3a894d6a9 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -19,6 +19,7 @@ const defaults = { units: "metric", zoom: 1, customCss: "css/custom.css", + foreignModulesDir: "modules", // httpHeaders used by helmet, see https://helmetjs.github.io/. You can add other/more object values by overriding this in config.js, // e.g. you need to add `frameguard: false` for embedding MagicMirror in another website, see https://github.com/MagicMirrorOrg/MagicMirror/issues/2847 httpHeaders: { contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false }, @@ -72,12 +73,7 @@ const defaults = { text: "www.michaelteeuw.nl" } } - ], - - paths: { - modules: "modules", - vendor: "vendor" - } + ] }; /*************** DO NOT EDIT THE LINE BELOW ***************/ diff --git a/js/loader.js b/js/loader.js index e8dff1907c..acc77d2801 100644 --- a/js/loader.js +++ b/js/loader.js @@ -10,6 +10,15 @@ const Loader = (function () { /* Private Methods */ + /** + * Retrieve object of env variables. + * @returns {object} with key: values as assembled in js/server_functions.js + */ + const getEnvVars = async function () { + const res = await fetch(`${location.protocol}//${location.host}/env`); + return JSON.parse(await res.text()); + }; + /** * Loops through all modules and requests start for every module. */ @@ -58,19 +67,20 @@ const Loader = (function () { * Generate array with module information including module paths. * @returns {object[]} Module information. */ - const getModuleData = function () { + const getModuleData = async function () { const modules = getAllModules(); const moduleFiles = []; + const envVars = await getEnvVars(); modules.forEach(function (moduleData, index) { const module = moduleData.module; const elements = module.split("/"); const moduleName = elements[elements.length - 1]; - let moduleFolder = `${config.paths.modules}/${module}`; + let moduleFolder = `${envVars.modulesDir}/${module}`; if (defaultModules.indexOf(moduleName) !== -1) { - moduleFolder = `${config.paths.modules}/default/${module}`; + moduleFolder = `modules/default/${module}`; } if (moduleData.disabled === true) { @@ -166,6 +176,7 @@ const Loader = (function () { }; script.onerror = function () { Log.error("Error on loading script:", fileName); + script.remove(); resolve(); }; document.getElementsByTagName("body")[0].appendChild(script); @@ -183,6 +194,7 @@ const Loader = (function () { }; stylesheet.onerror = function () { Log.error("Error on loading stylesheet:", fileName); + stylesheet.remove(); resolve(); }; document.getElementsByTagName("head")[0].appendChild(stylesheet); @@ -197,7 +209,9 @@ const Loader = (function () { * Load all modules as defined in the config. */ async loadModules () { - let moduleData = getModuleData(); + let moduleData = await getModuleData(); + const envVars = await getEnvVars(); + const customCss = envVars.customCss; /** * @returns {Promise} when all modules are loaded @@ -212,7 +226,7 @@ const Loader = (function () { // All modules loaded. Load custom.css // This is done after all the modules so we can // overwrite all the defined styles. - await loadFile(config.customCss); + await loadFile(customCss); // custom.css loaded. Start all modules. await startModules(); } @@ -244,7 +258,7 @@ const Loader = (function () { // This file is available in the vendor folder. // Load it from this vendor folder. loadedFiles.push(fileName.toLowerCase()); - return loadFile(`${config.paths.vendor}/${vendor[fileName]}`); + return loadFile(`vendor/${vendor[fileName]}`); } // File not loaded yet. diff --git a/js/server.js b/js/server.js index bfa0f911d7..42b3ff6692 100644 --- a/js/server.js +++ b/js/server.js @@ -8,8 +8,7 @@ const helmet = require("helmet"); const socketio = require("socket.io"); const Log = require("logger"); -const Utils = require("./utils"); -const { cors, getConfig, getHtml, getVersion, getStartup } = require("./server_functions"); +const { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars } = require("./server_functions"); /** * Server @@ -73,8 +72,11 @@ function Server (config) { app.use(helmet(config.httpHeaders)); app.use("/js", express.static(__dirname)); - // TODO add tests directory only when running tests? - const directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations", "/tests/configs", "/tests/mocks"]; + let directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations"]; + if (process.env.JEST_WORKER_ID !== undefined) { + // add tests directories only when running tests + directories.push("/tests/configs", "/tests/mocks"); + } for (const directory of directories) { app.use(directory, express.static(path.resolve(global.root_path + directory))); } @@ -87,6 +89,8 @@ function Server (config) { app.get("/startup", (req, res) => getStartup(req, res)); + app.get("/env", (req, res) => getEnvVars(req, res)); + app.get("/", (req, res) => getHtml(req, res)); server.on("listening", () => { diff --git a/js/server_functions.js b/js/server_functions.js index 73d11c0464..65928d732e 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -128,4 +128,30 @@ function getVersion (req, res) { res.send(global.version); } -module.exports = { cors, getConfig, getHtml, getVersion, getStartup }; +/** + * Gets environment variables needed in the browser. + * @returns {object} environment variables key: values + */ +function getEnvVarsAsObj () { + const obj = { modulesDir: `${config.foreignModulesDir}`, customCss: `${config.customCss}` }; + if (process.env.MM_MODULES_DIR) { + obj.modulesDir = process.env.MM_MODULES_DIR.replace(`${global.root_path}/`, ""); + } + if (process.env.MM_CUSTOMCSS_FILE) { + obj.customCss = process.env.MM_CUSTOMCSS_FILE.replace(`${global.root_path}/`, ""); + } + + return obj; +} + +/** + * Gets environment variables needed in the browser. + * @param {Request} req - the request + * @param {Response} res - the result + */ +function getEnvVars (req, res) { + const obj = getEnvVarsAsObj(); + res.send(obj); +} + +module.exports = { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj }; From 866419eb955eeb07db42d76e7badc25972455c93 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:37:25 +0200 Subject: [PATCH 098/418] Check config before starting MM (#3450) I think it might be a good idea to check the config at every start. --- CHANGELOG.md | 1 + js/app.js | 2 ++ js/check_config.js | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62ad64e240..ec74476f76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ _This release is scheduled to be released on 2024-10-01._ ### Added +- [core] Check config at every start of MagicMirror² (#3450) - [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues - [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir` - [core] elements are now removed from index.html when loading script or stylesheet files fails diff --git a/js/app.js b/js/app.js index 3bdf47ceca..0bf60a9b0e 100644 --- a/js/app.js +++ b/js/app.js @@ -117,6 +117,8 @@ function App () { } } + require(`${global.root_path}/js/check_config.js`); + try { fs.accessSync(configFilename, fs.F_OK); const c = require(configFilename); diff --git a/js/check_config.js b/js/check_config.js index c8e4387654..825aa3f325 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -64,12 +64,13 @@ function checkConfigFile () { for (const error of errors) { Log.error(`Line ${error.line} column ${error.column}: ${error.message}`); } - return; + process.exit(1); } Log.info("Checking modules structure configuration... "); const position_list = Utils.getModulePositions(); + // Make Ajv schema configuration of modules config // only scan "module" and "position" const schema = { From c6e05c9fecf75ec6e8656a4690656b4dfa719b1b Mon Sep 17 00:00:00 2001 From: Ryan Williams <65094007+ryan-d-williams@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:40:46 -0400 Subject: [PATCH 099/418] Added `DOM_OBJECTS_UPDATED` notification when the DOM is re-rendered via `updateDom` (#3535) - [x] Base your pull requests against the `develop` branch. - [x] Include these infos in the description: > - Does the pull request solve a **related** issue? Yes - solves #3534 > - If so, can you reference the issue like this `Fixes #`? Fixes #3534 (also mentioned in commit message) > - What does the pull request accomplish? Use a list if needed. > > - Adds a new notification (`DOM_OBJECTS_UPDATED`) when the DOM is updated via `updateDom` - [x] Please run `npm run lint:prettier` before submitting - [x] Don't forget to add an entry about your changes to the CHANGELOG.md file. More info can be found in #3534, but as a summary: The `updateDom` function is not synchronous - there is an undetermined amount of time between when it completes and when the DOM has actually been re-rendered and is ready for interaction. The existing notification (`MODULE_DOM_CREATED`) only fires once on the initial DOM render. This PR solves the issue of subsequent re-renders by adding a new notification that fires whenever the DOM is ready after an update. This notification falls within expected lifecycle notifications (very similar to other libraries that provide DOM lifecycle notifications). --- CHANGELOG.md | 1 + js/main.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec74476f76..1f2bd7b46f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @W - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar - [compliments] Added `specialDayUnique` config option, defaults to `false` (#3465) - [weather] Provider weathergov: Use `precipitationLast3Hours` if `precipitationLastHour` is `null` (#3124) +- [core] Added `DOM_OBJECTS_UPDATED` notification each time the DOM is re-rendered via `updateDom` (#3534) ### Removed diff --git a/js/main.js b/js/main.js index c3f783e1ef..fd70c56413 100644 --- a/js/main.js +++ b/js/main.js @@ -666,7 +666,10 @@ const MM = (function () { } // Further implementation is done in the private method. - updateDom(module, updateOptions); + updateDom(module, updateOptions).then(function () { + // Once the update is complete and rendered, send a notification to the module that the DOM has been updated + sendNotification("DOM_OBJECTS_UPDATED", null, null, module); + }); }, /** From 06f6fbf49ba46c5fbe764d86e16656497f3d6375 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:39:02 +0200 Subject: [PATCH 100/418] Review config_check.js (#3545) Only details changes. No functional changes. - remove superfluous colors in Log.error - invert negative if - update ESLint env - use camel case variable name - optimize Log strings --- CHANGELOG.md | 7 ++++--- cspell.config.json | 1 + js/check_config.js | 46 ++++++++++++++++++++++------------------------ 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f2bd7b46f..7c03ef63ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,9 +12,9 @@ _This release is scheduled to be released on 2024-10-01._ ### Added - [core] Check config at every start of MagicMirror² (#3450) -- [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues -- [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir` -- [core] elements are now removed from index.html when loading script or stylesheet files fails +- [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues (#3544) +- [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir` (#3530) +- [core] elements are now removed from `index.html` when loading script or stylesheet files fails ### Removed @@ -27,6 +27,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Updated dependencies including stylistic-eslint - [core] Updated SocketIO catch all to new API - [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded (PR #3518 fixes issue #3504) +- [core] Detail optimizations in `config_check.js` ### Fixed diff --git a/cspell.config.json b/cspell.config.json index bbb26dfcf1..16addf44a9 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -36,6 +36,7 @@ "crazyscot", "Creepin", "currentweather", + "CUSTOMCSS", "customregions", "Cymraeg", "dariom", diff --git a/js/check_config.js b/js/check_config.js index 825aa3f325..59c4221251 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -1,18 +1,16 @@ const path = require("node:path"); const fs = require("node:fs"); +const Ajv = require("ajv"); const colors = require("ansis"); const { Linter } = require("eslint"); -const linter = new Linter(); - -const Ajv = require("ajv"); - -const ajv = new Ajv(); - const rootPath = path.resolve(`${__dirname}/../`); const Log = require(`${rootPath}/js/logger.js`); const Utils = require(`${rootPath}/js/utils.js`); +const linter = new Linter(); +const ajv = new Ajv(); + /** * Returns a string with path of configuration file. * Check if set by environment variable MM_CONFIG_FILE @@ -38,28 +36,28 @@ function checkConfigFile () { // Check permission try { fs.accessSync(configFileName, fs.F_OK); - } catch (e) { - Log.error(e); + } catch (error) { + Log.error(error); throw new Error("No permission to access config file!"); } // Validate syntax of the configuration file. - Log.info("Checking file... ", configFileName); + Log.info(`Checking config file ${configFileName} ...`); // I'm not sure if all ever is utf-8 const configFile = fs.readFileSync(configFileName, "utf-8"); - // Explicitly tell linter that he might encounter es6 syntax ("let config = {...}") + // Explicitly tell linter that he might encounter es2024 syntax ("let config = {...}") const errors = linter.verify(configFile, { env: { - es6: true + es2024: true } }); if (errors.length === 0) { Log.info(colors.green("Your configuration file doesn't contain syntax errors :)")); } else { - Log.error(colors.red("Your configuration file contains syntax errors :(")); + Log.error("Your configuration file contains syntax errors :("); for (const error of errors) { Log.error(`Line ${error.line} column ${error.column}: ${error.message}`); @@ -67,9 +65,9 @@ function checkConfigFile () { process.exit(1); } - Log.info("Checking modules structure configuration... "); + Log.info("Checking modules structure configuration ..."); - const position_list = Utils.getModulePositions(); + const positionList = Utils.getModulePositions(); // Make Ajv schema configuration of modules config // only scan "module" and "position" @@ -86,7 +84,7 @@ function checkConfigFile () { }, position: { type: "string", - enum: position_list + enum: positionList } }, required: ["module"] @@ -95,25 +93,25 @@ function checkConfigFile () { } }; - // scan all modules + // Scan all modules const validate = ajv.compile(schema); const data = require(configFileName); const valid = validate(data); - if (!valid) { - let module = validate.errors[0].instancePath.split("/")[2]; - let position = validate.errors[0].instancePath.split("/")[3]; + if (valid) { + Log.info(colors.green("Your modules structure configuration doesn't contain errors :)")); + } else { + const module = validate.errors[0].instancePath.split("/")[2]; + const position = validate.errors[0].instancePath.split("/")[3]; - Log.error(colors.red("This module configuration contains errors:")); + Log.error("This module configuration contains errors:"); Log.error(`\n${JSON.stringify(data.modules[module], null, 2)}`); if (position) { - Log.error(colors.red(`${position}: ${validate.errors[0].message}`)); + Log.error(`${position}: ${validate.errors[0].message}`); Log.error(`\n${JSON.stringify(validate.errors[0].params.allowedValues, null, 2).slice(1, -1)}`); } else { - Log.error(colors.red(validate.errors[0].message)); + Log.error(validate.errors[0].message); } - } else { - Log.info(colors.green("Your modules structure configuration doesn't contain errors :)")); } } From 65d7e2d0678c75a30e419e48397bae71ca3b4c0b Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 18 Sep 2024 21:53:18 +0200 Subject: [PATCH 101/418] fix CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c03ef63ec..1249adca22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues (#3544) - [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir` (#3530) - [core] elements are now removed from `index.html` when loading script or stylesheet files fails +- [core] Added `DOM_OBJECTS_UPDATED` notification each time the DOM is re-rendered via `updateDom` (#3534) ### Removed @@ -50,7 +51,6 @@ Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @W - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar - [compliments] Added `specialDayUnique` config option, defaults to `false` (#3465) - [weather] Provider weathergov: Use `precipitationLast3Hours` if `precipitationLastHour` is `null` (#3124) -- [core] Added `DOM_OBJECTS_UPDATED` notification each time the DOM is re-rendered via `updateDom` (#3534) ### Removed From 8f5aa50d79b75ba2ef432659cf948212fb0a1af4 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Thu, 19 Sep 2024 07:29:04 +0200 Subject: [PATCH 102/418] added test for `MM_MODULES_DIR` (#3546) uses newsfeed test after copying this module to config dir addition for #3530 --- CHANGELOG.md | 2 +- tests/e2e/modules/newsfeed_spec.js | 31 +++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1249adca22..de8be1d58f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Check config at every start of MagicMirror² (#3450) - [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues (#3544) -- [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir` (#3530) +- [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir`, added test for `MM_MODULES_DIR` (#3530) - [core] elements are now removed from `index.html` when loading script or stylesheet files fails - [core] Added `DOM_OBJECTS_UPDATED` notification each time the DOM is re-rendered via `updateDom` (#3534) diff --git a/tests/e2e/modules/newsfeed_spec.js b/tests/e2e/modules/newsfeed_spec.js index 141b880661..e3a9c79099 100644 --- a/tests/e2e/modules/newsfeed_spec.js +++ b/tests/e2e/modules/newsfeed_spec.js @@ -1,10 +1,7 @@ +const fs = require("node:fs"); const helpers = require("../helpers/global-setup"); -describe("Newsfeed module", () => { - afterAll(async () => { - await helpers.stopApplication(); - }); - +const runTests = async () => { describe("Default configuration", () => { beforeAll(async () => { await helpers.startApplication("tests/configs/modules/newsfeed/default.js"); @@ -74,4 +71,28 @@ describe("Newsfeed module", () => { expect(elem.textContent).toContain("No news at the moment."); }); }); +}; + +describe("Newsfeed module", () => { + afterAll(async () => { + await helpers.stopApplication(); + }); + + runTests(); +}); + +describe("Newsfeed module located in config directory", () => { + beforeAll(async () => { + const baseDir = `${__dirname}/../../..`; + if (!fs.existsSync(`${baseDir}/config/newsfeed`)) { + await fs.cp(`${baseDir}/modules/default/newsfeed`, `${baseDir}/config/newsfeed`, { recursive: true }, (err) => err && console.error(err)); + } + process.env.MM_MODULES_DIR = "config"; + }); + + afterAll(async () => { + await helpers.stopApplication(); + }); + + runTests(); }); From 1823f5a13041f28723284181883fb61d915b8daa Mon Sep 17 00:00:00 2001 From: Ryan Williams <65094007+ryan-d-williams@users.noreply.github.com> Date: Thu, 19 Sep 2024 01:29:43 -0400 Subject: [PATCH 103/418] Updated to new notification name `DOM_OBJECTS_UPDATED` -> `MODULE_DOM_UPDATED` (#3548) This is an update to #3535. See #3534 for discussion and context. Fixes #3534 (again). --- CHANGELOG.md | 2 +- js/main.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de8be1d58f..f2fad4db2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues (#3544) - [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir`, added test for `MM_MODULES_DIR` (#3530) - [core] elements are now removed from `index.html` when loading script or stylesheet files fails -- [core] Added `DOM_OBJECTS_UPDATED` notification each time the DOM is re-rendered via `updateDom` (#3534) +- [core] Added `MODULE_DOM_UPDATED` notification each time the DOM is re-rendered via `updateDom` (#3534) ### Removed diff --git a/js/main.js b/js/main.js index fd70c56413..16aaa1b1b4 100644 --- a/js/main.js +++ b/js/main.js @@ -668,7 +668,7 @@ const MM = (function () { // Further implementation is done in the private method. updateDom(module, updateOptions).then(function () { // Once the update is complete and rendered, send a notification to the module that the DOM has been updated - sendNotification("DOM_OBJECTS_UPDATED", null, null, module); + sendNotification("MODULE_DOM_UPDATED", null, null, module); }); }, From 06a8b517aab6088c289dbd79bdbdb19ed5bf9437 Mon Sep 17 00:00:00 2001 From: Veeck Date: Thu, 19 Sep 2024 12:25:41 +0200 Subject: [PATCH 104/418] Cleanup github actions (#3549) - should now correct itself when one changes from (accidentaly selected) master to develop - also fixes wrong CHANGELOG entry from https://github.com/MagicMirrorOrg/MagicMirror/pull/3481 - update deps a little --- .../{depsreview.yaml => dep-review.yaml} | 0 ...tronRebuild.yaml => electron-rebuild.yaml} | 0 .../workflows/enforce-pullrequest-rules.yaml | 4 +- CHANGELOG.md | 2 +- package-lock.json | 202 +++++++++--------- package.json | 4 +- 6 files changed, 106 insertions(+), 106 deletions(-) rename .github/workflows/{depsreview.yaml => dep-review.yaml} (100%) rename .github/workflows/{electronRebuild.yaml => electron-rebuild.yaml} (100%) diff --git a/.github/workflows/depsreview.yaml b/.github/workflows/dep-review.yaml similarity index 100% rename from .github/workflows/depsreview.yaml rename to .github/workflows/dep-review.yaml diff --git a/.github/workflows/electronRebuild.yaml b/.github/workflows/electron-rebuild.yaml similarity index 100% rename from .github/workflows/electronRebuild.yaml rename to .github/workflows/electron-rebuild.yaml diff --git a/.github/workflows/enforce-pullrequest-rules.yaml b/.github/workflows/enforce-pullrequest-rules.yaml index 30c0d0ca08..77d3befb39 100644 --- a/.github/workflows/enforce-pullrequest-rules.yaml +++ b/.github/workflows/enforce-pullrequest-rules.yaml @@ -5,7 +5,7 @@ name: "Enforce Pull-Request Rules" on: - pull_request: + pull_request_target: types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled] jobs: @@ -25,4 +25,4 @@ jobs: echo "Please don't do this. Switch the branch to 'develop'." exit 1 env: - BASE_BRANCH: ${{ github.base_ref }} + BASE_BRANCH: ${{ github.event.pull_request.base.ref }} diff --git a/CHANGELOG.md b/CHANGELOG.md index f2fad4db2a..f29a4fd9d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ _This release is scheduled to be released on 2024-10-01._ ### Added +- [compliments] Added support for cron type date/time format entries mm hh DD MM dow (minutes/hours/days/months and day of week) see https://crontab.cronhub.io for construction (#3481) - [core] Check config at every start of MagicMirror² (#3450) - [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues (#3544) - [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir`, added test for `MM_MODULES_DIR` (#3530) @@ -47,7 +48,6 @@ Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @W ### Added -- [compliments] Added support for cron type date/time format entries.. mm hh DD MM dow (minutes/hours/days/months and day of week) see https://crontab.cronhub.io for construction - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar - [compliments] Added `specialDayUnique` config option, defaults to `false` (#3465) - [weather] Provider weathergov: Use `precipitationLast3Hours` if `precipitationLastHour` is `null` (#3124) diff --git a/package-lock.json b/package-lock.json index 5a430cf916..40847e435e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,10 +31,10 @@ }, "devDependencies": { "@stylistic/eslint-plugin": "^2.8.0", - "cspell": "^8.14.3", + "cspell": "^8.14.4", "eslint-plugin-import": "^2.30.0", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.2.3", + "eslint-plugin-jsdoc": "^50.2.4", "eslint-plugin-package-json": "^0.15.3", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", @@ -715,9 +715,9 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.14.3.tgz", - "integrity": "sha512-O0QA2OD0IDatIxNinr5woWJ8uC3/fbMaOdu3R+142wMX3f2hB08Wfvk+anFgFVTgo90JQnmKEvlCZD1Q8QlWig==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.14.4.tgz", + "integrity": "sha512-JHZOpCJzN6fPBapBOvoeMxZbr0ZA11ZAkwcqM4w0lKoacbi6TwK8GIYf66hHvwLmMeav75TNXWE6aPTvBLMMqA==", "dev": true, "license": "MIT", "dependencies": { @@ -780,22 +780,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.14.3.tgz", - "integrity": "sha512-xJbIhSVL1LrwtIpFYvfbXMXv0GUqp2mFkTdG652zb4ZCjQUitmAN1eOhpUt2WHqyCdsMNjMcoJ05PNAN1LrLBQ==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.14.4.tgz", + "integrity": "sha512-gJ6tQbGCNLyHS2iIimMg77as5MMAFv3sxU7W6tjLlZp8htiNZS7fS976g24WbT/hscsTT9Dd0sNHkpo8K3nvVw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.14.3" + "@cspell/cspell-types": "8.14.4" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.14.3.tgz", - "integrity": "sha512-vc4gcsQ/qLHcHHz1EmTLe0x1aZYUzkQAyIOTLRWFlsWrdztXQ3zSEaPB2JzgLNCaqJrYJPs5Wh/Uo+6w9ZaIeA==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.14.4.tgz", + "integrity": "sha512-CLLdouqfrQ4rqdQdPu0Oo+HHCU/oLYoEsK1nNPb28cZTFxnn0cuSPKB6AMPBJmMwdfJ6fMD0BCKNbEe1UNLHcw==", "dev": true, "license": "MIT", "engines": { @@ -803,9 +803,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.14.3.tgz", - "integrity": "sha512-SOG4LQS4rt93FnCyCsDfCxOuq+uTzco6zpncwMU1GgH8bSEEeiDphGsgmdgK7XxKNlr59o8JFeD+45AkJWHm5w==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.14.4.tgz", + "integrity": "sha512-s3uZyymJ04yn8+zlTp7Pt1WRSlAel6XVo+iZRxls3LSvIP819KK64DoyjCD2Uon0Vg9P/K7aAPt8GcxDcnJtgA==", "dev": true, "license": "MIT", "dependencies": { @@ -816,9 +816,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.14.3.tgz", - "integrity": "sha512-bqb+6KlFMVEprBlga1olLmZFWmsT267hmLZHhQoNKTlZJlzyQjmAd4XYUJyH9oEYOOt4t5PgqtZJSxudmq2SIw==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.14.4.tgz", + "integrity": "sha512-i3UG+ep63akNsDXZrtGgICNF3MLBHtvKe/VOIH6+L+NYaAaVHqqQvOY9MdUwt1HXh8ElzfwfoRp36wc5aAvt6g==", "dev": true, "license": "MIT", "engines": { @@ -826,9 +826,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.14.3.tgz", - "integrity": "sha512-t8cvWSLVmgoAnmwMKXf0W1k3aWPPksTIqcNFMVF2f3m4dZh9HBh+M+xK9mXXScALmQev+psbvbiTjRlKD52ZnQ==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.14.4.tgz", + "integrity": "sha512-VXwikqdHgjOVperVVCn2DOe8W3rPIswwZtMHfRYnagpzZo/TOntIjkXPJSfTtl/cFyx5DnCBsDH8ytKGlMeHkw==", "dev": true, "license": "MIT", "engines": { @@ -1217,9 +1217,9 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.14.3.tgz", - "integrity": "sha512-LlWDTfQO2V3CAwax5PlQnS2prLs0icWfaROaNrIoSe8X6OUerfoxJ9p3Bpx0AxSKv4FtvYQraRV/UNPWRhhHag==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.14.4.tgz", + "integrity": "sha512-GjKsBJvPXp4dYRqsMn7n1zpnKbnpfJnlKLOVeoFBh8fi4n06G50xYr+G25CWX1WT3WFaALAavvVICEUPrVsuqg==", "dev": true, "license": "MIT", "dependencies": { @@ -1230,9 +1230,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.14.3.tgz", - "integrity": "sha512-a1BbKi3BcSju9owpa37x6I3sZtwpnzpRslSsV7IUBI8k85nfH+TiFm0toEEj/8jFJKehBWr83kMjZFHQReV13g==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.14.4.tgz", + "integrity": "sha512-qd68dD7xTA4Mnf/wjIKYz2SkiTBshIM+yszOUtLa06YJm0aocoNQ25FHXyYEQYm9NQXCYnRWWA02sFMGs8Sv/w==", "dev": true, "license": "MIT", "engines": { @@ -1240,9 +1240,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.14.3.tgz", - "integrity": "sha512-ZC5HiGbvD3vCA1pj7FL5gwyOi3OeXa51TDDRSjMW5A9XOpr57ptKxlSCwFVxNfszPTfMKP19a81rz1jo3GyFMg==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.14.4.tgz", + "integrity": "sha512-Uyfck64TfVU24wAP3BLGQ5EsAfzIZiLfN90NhttpEM7GlOBmbGrEJd4hNOwfpYsE/TT80eGWQVPRTLr5SDbXFA==", "dev": true, "license": "MIT", "engines": { @@ -1250,9 +1250,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.14.3.tgz", - "integrity": "sha512-r7fVsgOBu1qpt4UH45mE3TZfW7H+CHzK3INRUjSsrWKaiyE57mD6IIoqYdjCDoP4xaMRrHGC5SBKy+eX3prsBQ==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.14.4.tgz", + "integrity": "sha512-htHhNF8WrM/NfaLSWuTYw0NqVgFRVHYSyHlRT3i/Yv5xvErld8Gw7C6ldm+0TLjoGlUe6X1VV72JSir7+yLp/Q==", "dev": true, "license": "MIT", "engines": { @@ -4271,25 +4271,25 @@ } }, "node_modules/cspell": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.14.3.tgz", - "integrity": "sha512-GTok3s0J6hb8lXPgOkFcJ6+i91YS99AD5t60htNrq7Ae89BZByG20XPZc/6zbRN9eEQvtCx4OAIXnnfxP5QENw==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.14.4.tgz", + "integrity": "sha512-R5Awb3i/RKaVVcZzFt8dkN3M6VnifIEDYBcbzbmYjZ/Eq+ASF+QTmI0E9WPhMEcFM1nd7YOyXnETo560yRdoKw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.14.3", - "@cspell/cspell-pipe": "8.14.3", - "@cspell/cspell-types": "8.14.3", - "@cspell/dynamic-import": "8.14.3", - "@cspell/url": "8.14.3", + "@cspell/cspell-json-reporter": "8.14.4", + "@cspell/cspell-pipe": "8.14.4", + "@cspell/cspell-types": "8.14.4", + "@cspell/dynamic-import": "8.14.4", + "@cspell/url": "8.14.4", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^12.1.0", - "cspell-dictionary": "8.14.3", - "cspell-gitignore": "8.14.3", - "cspell-glob": "8.14.3", - "cspell-io": "8.14.3", - "cspell-lib": "8.14.3", + "cspell-dictionary": "8.14.4", + "cspell-gitignore": "8.14.4", + "cspell-glob": "8.14.4", + "cspell-io": "8.14.4", + "cspell-lib": "8.14.4", "fast-glob": "^3.3.2", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", @@ -4309,13 +4309,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.14.3.tgz", - "integrity": "sha512-uQFhEvnMJBpZBoi5U5jcMdykze5Cng28RDq4jzM2bYR2aE0HKZfFS8Hsjf5SLDxxS7TAKhnDh5a0r+6T/G6+qw==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.14.4.tgz", + "integrity": "sha512-cnUeJfniTiebqCaQmIUnbSrPrTH7xzKRQjJDHAEV0WYnOG2MhRXI13OzytdFdhkVBdStmgTzTCJKE7x+kmU2NA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.14.3", + "@cspell/cspell-types": "8.14.4", "comment-json": "^4.2.5", "yaml": "^2.5.1" }, @@ -4324,15 +4324,15 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.14.3.tgz", - "integrity": "sha512-FiTas0KXWXKyTJIRYZF7USp7Cjjq6RmzLKcDKAvJhc0XmbRaoYHW20IRkHVsrfO6bHTmo1fLoJQpvuDCkBiojg==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.14.4.tgz", + "integrity": "sha512-pZvQHxpAW5fZAnt3ZKKy3s7M+3CX2t8tCS3uJrpEHIynlCawpG0fPF78rVE5o+g0dON36Lguc/BUuSN4IWKLmQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.14.3", - "@cspell/cspell-types": "8.14.3", - "cspell-trie-lib": "8.14.3", + "@cspell/cspell-pipe": "8.14.4", + "@cspell/cspell-types": "8.14.4", + "cspell-trie-lib": "8.14.4", "fast-equals": "^5.0.1" }, "engines": { @@ -4340,15 +4340,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.14.3.tgz", - "integrity": "sha512-SOPYlaOh2tPSYZ48zGN9TzjaxnO05/AJMpvlvxUf0uASa2BOeogl11KvzcS7ig5MUnB/+s/2YsShcF+YjfptEw==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.14.4.tgz", + "integrity": "sha512-RwfQEW5hD7CpYwS7m3b0ONG0nTLKP6bL2tvMdl7qtaYkL7ztGdsBTtLD1pmwqUsCbiN5RuaOxhYOYeRcpFRIkQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.14.3", - "cspell-glob": "8.14.3", - "cspell-io": "8.14.3", + "@cspell/url": "8.14.4", + "cspell-glob": "8.14.4", + "cspell-io": "8.14.4", "find-up-simple": "^1.0.0" }, "bin": { @@ -4359,13 +4359,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.14.3.tgz", - "integrity": "sha512-d12Dn/i6BRKQrvq0ikcBPBsjPdyemu2Ggw1WgWvxAlaGGZsoyC6Hn5ElQt6tQt2CruwUfPPXVm2+UMyHlRMt4g==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.14.4.tgz", + "integrity": "sha512-C/xTS5nujMRMuguibq92qMVP767mtxrur7DcVolCvpzcivm1RB5NtIN0OctQxTyMbnmKeQv1t4epRKQ9A8vWRg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.14.3", + "@cspell/url": "8.14.4", "micromatch": "^4.0.8" }, "engines": { @@ -4373,14 +4373,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.14.3.tgz", - "integrity": "sha512-clb5HCVJn6wW/v7dC3CGuo1YmmXIVpvpz7BGwt2Rvybk/8o6CD3i4aF8TqnHc0FIWP0iHCwMhqnCyiOJtYI9Mg==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.14.4.tgz", + "integrity": "sha512-yaSKAAJDiamsw3FChbw4HXb2RvTQrDsLelh1+T4MavarOIcAxXrqAJ8ysqm++g+S/ooJz2YO8YWIyzJKxcMf8g==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.14.3", - "@cspell/cspell-types": "8.14.3" + "@cspell/cspell-pipe": "8.14.4", + "@cspell/cspell-types": "8.14.4" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4390,42 +4390,42 @@ } }, "node_modules/cspell-io": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.14.3.tgz", - "integrity": "sha512-8SWe553kpSsQ039SiFQ+G/87KoJn51W1yc42aGUwkuagglspEiUVj3bTlD3eVswZAT3KbG26Mti49L37Lecj/g==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.14.4.tgz", + "integrity": "sha512-o6OTWRyx/Az+PFhr1B0wMAwqG070hFC9g73Fkxd8+rHX0rfRS69QZH7LgSmZytqbZIMxCTDGdsLl33MFGWCbZQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.14.3", - "@cspell/url": "8.14.3" + "@cspell/cspell-service-bus": "8.14.4", + "@cspell/url": "8.14.4" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.14.3.tgz", - "integrity": "sha512-hcpxyX+xZ1LbcuvT1H+zCjfmW04on6nsdkKTT0bRdsgxyw6O08hR2OVqQ9+oYiXdp6QccjOl6UPOS6dEZajOmw==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.14.4.tgz", + "integrity": "sha512-qdkUkKtm+nmgpA4jQbmQTuepDfjHBDWvs3zDuEwVIVFq/h8gnXrRr75gJ3RYdTy+vOOqHPoLLqgxyqkUUrUGXA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.14.3", - "@cspell/cspell-pipe": "8.14.3", - "@cspell/cspell-resolver": "8.14.3", - "@cspell/cspell-types": "8.14.3", - "@cspell/dynamic-import": "8.14.3", - "@cspell/filetypes": "8.14.3", - "@cspell/strong-weak-map": "8.14.3", - "@cspell/url": "8.14.3", + "@cspell/cspell-bundled-dicts": "8.14.4", + "@cspell/cspell-pipe": "8.14.4", + "@cspell/cspell-resolver": "8.14.4", + "@cspell/cspell-types": "8.14.4", + "@cspell/dynamic-import": "8.14.4", + "@cspell/filetypes": "8.14.4", + "@cspell/strong-weak-map": "8.14.4", + "@cspell/url": "8.14.4", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.14.3", - "cspell-dictionary": "8.14.3", - "cspell-glob": "8.14.3", - "cspell-grammar": "8.14.3", - "cspell-io": "8.14.3", - "cspell-trie-lib": "8.14.3", + "cspell-config-lib": "8.14.4", + "cspell-dictionary": "8.14.4", + "cspell-glob": "8.14.4", + "cspell-grammar": "8.14.4", + "cspell-io": "8.14.4", + "cspell-trie-lib": "8.14.4", "env-paths": "^3.0.0", "fast-equals": "^5.0.1", "gensequence": "^7.0.0", @@ -4463,14 +4463,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.14.3", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.14.3.tgz", - "integrity": "sha512-90Rwt8Kzcv2HB2uuwUqMlCQVa7tpsqHtSFiGox3DTDUZWTikMiOwUigRvO17FsxxQL+qW4fIH4PUi4SGwins9Q==", + "version": "8.14.4", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.14.4.tgz", + "integrity": "sha512-zu8EJ33CH+FA5lwTRGqS//Q6phO0qtgEmODMR1KPlD7WlrfTFMb3bWFsLo/tiv5hjpsn7CM6dYDAAgBOSkoyhQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.14.3", - "@cspell/cspell-types": "8.14.3", + "@cspell/cspell-pipe": "8.14.4", + "@cspell/cspell-types": "8.14.4", "gensequence": "^7.0.0" }, "engines": { @@ -5636,9 +5636,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.2.3.tgz", - "integrity": "sha512-aNh/dz3wSkyo53y2KWDCrA8fDuXDMtMVflcbesd8AFPgcF8ugOv9mJxC7qKB95R96nzCB91iEwU7MMznh/7okQ==", + "version": "50.2.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.2.4.tgz", + "integrity": "sha512-020jA+dXaXdb+TML3ZJBvpPmzwbNROjnYuTYi/g6A5QEmEjhptz4oPJDKkOGMIByNxsPpdTLzSU1HYVqebOX1w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { diff --git a/package.json b/package.json index c82b472d25..19141c8d5f 100644 --- a/package.json +++ b/package.json @@ -76,10 +76,10 @@ }, "devDependencies": { "@stylistic/eslint-plugin": "^2.8.0", - "cspell": "^8.14.3", + "cspell": "^8.14.4", "eslint-plugin-import": "^2.30.0", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.2.3", + "eslint-plugin-jsdoc": "^50.2.4", "eslint-plugin-package-json": "^0.15.3", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", From fa6a7521b4ad4127fc3dba0403824f660e81de6b Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 24 Sep 2024 22:09:28 +0200 Subject: [PATCH 105/418] add tests for minimal node version (currently v20.9.0) (#3556) Beside testing against node version `v20.x` and `v22.x` we should also test against the minimal node version, currently `v20.9.0`. This is for seeing changes in dependencies which needs higher node version as with the July-24-release, where we wrote `node >=20` but shipped an `eslint` version which required `node>=20.9.0`. --- .github/workflows/automated-tests.yaml | 2 +- .github/workflows/electron-rebuild.yaml | 2 +- CHANGELOG.md | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 9ac92f216a..e48acd9bcc 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -18,7 +18,7 @@ jobs: timeout-minutes: 30 strategy: matrix: - node-version: [20.x, 22.x] + node-version: [20.9.0, 20.x, 22.x] steps: - name: "Checkout code" uses: actions/checkout@v4 diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index f9cc50957f..2d22fcedb0 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.x, 22.x] + node-version: [20.9.0, 20.x, 22.x] steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index f29a4fd9d4..fc3360bd42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir`, added test for `MM_MODULES_DIR` (#3530) - [core] elements are now removed from `index.html` when loading script or stylesheet files fails - [core] Added `MODULE_DOM_UPDATED` notification each time the DOM is re-rendered via `updateDom` (#3534) +- [tests] added minimal needed node version to tests (currently v20.9.0) to avoid releases with wrong node version info ### Removed @@ -44,7 +45,7 @@ _This release is scheduled to be released on 2024-10-01._ Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @WallysWellies. -> ⚠️ This release needs nodejs version >= v20 +> ⚠️ This release needs nodejs version >= v20.9.0 ### Added From 08116b8e646db4b2faa442c17229744a21abc3b6 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 24 Sep 2024 22:38:00 +0200 Subject: [PATCH 106/418] fixes for running tests for MM_MODULES_DIR (#3550) and ignore `js/positions.js` when linting (because this file is generated at runtime). --- .eslintignore | 3 ++- CHANGELOG.md | 1 + js/app.js | 10 +++++++++- js/loader.js | 10 +++++++++- tests/e2e/modules/newsfeed_spec.js | 4 ++-- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.eslintignore b/.eslintignore index 24f4f1f599..c772c23bc2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ modules/* -!modules/default/ \ No newline at end of file +!modules/default/ +js/positions.js diff --git a/CHANGELOG.md b/CHANGELOG.md index fc3360bd42..64b69ed09a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Fixed issue for respecting unit config on broadcasted notifications - [tests] Fixes calendar test by moving it from e2e to electron with fixed date (#3532) - [calendar] fixed sliceMultiDayEvents getting wrong count and displaying incorrect entries, Europe/Berlin (#3542) +- [tests] ignore `js/positions.js` when linting (this file is created at runtime) ## [2.28.0] - 2024-07-01 diff --git a/js/app.js b/js/app.js index 0bf60a9b0e..8ae002e9f0 100644 --- a/js/app.js +++ b/js/app.js @@ -166,7 +166,15 @@ function App () { let moduleFolder = `${__dirname}/../${env.modulesDir}/${module}`; if (defaultModules.includes(moduleName)) { - moduleFolder = `${__dirname}/../modules/default/${module}`; + const defaultModuleFolder = `${__dirname}/../modules/default/${module}`; + if (process.env.JEST_WORKER_ID === undefined) { + moduleFolder = defaultModuleFolder; + } else { + // running in Jest, allow defaultModules placed under moduleDir for testing + if (env.modulesDir === "modules") { + moduleFolder = defaultModuleFolder; + } + } } const moduleFile = `${moduleFolder}/${module}.js`; diff --git a/js/loader.js b/js/loader.js index acc77d2801..9b42dd8493 100644 --- a/js/loader.js +++ b/js/loader.js @@ -80,7 +80,15 @@ const Loader = (function () { let moduleFolder = `${envVars.modulesDir}/${module}`; if (defaultModules.indexOf(moduleName) !== -1) { - moduleFolder = `modules/default/${module}`; + const defaultModuleFolder = `modules/default/${module}`; + if (window.name !== "jsdom") { + moduleFolder = defaultModuleFolder; + } else { + // running in Jest, allow defaultModules placed under moduleDir for testing + if (envVars.modulesDir === "modules") { + moduleFolder = defaultModuleFolder; + } + } } if (moduleData.disabled === true) { diff --git a/tests/e2e/modules/newsfeed_spec.js b/tests/e2e/modules/newsfeed_spec.js index e3a9c79099..1c3c4d288d 100644 --- a/tests/e2e/modules/newsfeed_spec.js +++ b/tests/e2e/modules/newsfeed_spec.js @@ -82,10 +82,10 @@ describe("Newsfeed module", () => { }); describe("Newsfeed module located in config directory", () => { - beforeAll(async () => { + beforeAll(() => { const baseDir = `${__dirname}/../../..`; if (!fs.existsSync(`${baseDir}/config/newsfeed`)) { - await fs.cp(`${baseDir}/modules/default/newsfeed`, `${baseDir}/config/newsfeed`, { recursive: true }, (err) => err && console.error(err)); + fs.cpSync(`${baseDir}/modules/default/newsfeed`, `${baseDir}/config/newsfeed`, { recursive: true }); } process.env.MM_MODULES_DIR = "config"; }); From 5ffdf9af09b902d6fccb1bc6c535e44343c9ca86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Wed, 25 Sep 2024 09:03:09 +0200 Subject: [PATCH 107/418] Updated minimal needed node version in `package.json` (currently v20.9.0) (#3559) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update of package*.json for minimal node verion requirement (v20.9.0) * it's an addition to #3556 * According to changelog v2.28.0: `⚠️ This release needs nodejs version >= v20.9.0` --- CHANGELOG.md | 1 + package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64b69ed09a..9eb6f3f344 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Updated SocketIO catch all to new API - [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded (PR #3518 fixes issue #3504) - [core] Detail optimizations in `config_check.js` +- [core] Updated minimal needed node version in `package.json` (currently v20.9.0) ### Fixed diff --git a/package-lock.json b/package-lock.json index 40847e435e..995187b959 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,7 +50,7 @@ "stylelint-prettier": "^5.0.2" }, "engines": { - "node": ">=20" + "node": ">=20.9.0" }, "optionalDependencies": { "electron": "^31.6.0" diff --git a/package.json b/package.json index 19141c8d5f..685feffacb 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "electron": "^31.6.0" }, "engines": { - "node": ">=20" + "node": ">=20.9.0" }, "_moduleAliases": { "node_helper": "js/node_helper.js", From d3187689f05a790f1c469812634f5f04e75b2043 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 25 Sep 2024 21:05:11 +0200 Subject: [PATCH 108/418] Switch to ESLint v9 and flat config (#3558) Since PR #3551 was not yet complete, I made my own attempt. 1. Update to ESLint v9. 2. Replace deprecated `.eslintrc.json` and `.eslintignore` by flat config `eslint.config.mjs`. 3. Adapt `check_config.js` to use flat config. 4. Since `eslint-plugin-import` still doesn't support ESLint v9 I removed it. We can add it back when it does support v9. 5. Run tests `npm run check:js` and `npm run config:check`. 6. In order not to overload this PR, I have not yet activated more additional rules - there are some useful ones in the new plugin `@eslint/js`. @bugsounet, please don't take it as an offence that I have created a competing PR. The migration to ESLint v9 has been burning under my nails for some time. --- .eslintignore | 3 - .eslintrc.json | 94 -- .github/CONTRIBUTING.md | 2 +- .prettierignore | 2 +- CHANGELOG.md | 2 + eslint.config.mjs | 121 ++ js/check_config.js | 57 +- package-lock.json | 1228 +++-------------- package.json | 5 +- tests/unit/functions/server_functions_spec.js | 2 +- 10 files changed, 367 insertions(+), 1149 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.json create mode 100644 eslint.config.mjs diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index c772c23bc2..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -modules/* -!modules/default/ -js/positions.js diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 629c008246..0000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "extends": ["eslint:recommended", "plugin:@stylistic/all-extends", "plugin:import/recommended", "plugin:jest/recommended", "plugin:jsdoc/recommended"], - "plugins": ["unicorn"], - "env": { - "browser": true, - "es2024": true, - "jest/globals": true, - "node": true - }, - "globals": { - "config": true, - "Log": true, - "MM": true, - "Module": true, - "moment": true - }, - "parserOptions": { - "sourceType": "module", - "ecmaVersion": "latest", - "ecmaFeatures": { - "globalReturn": true - } - }, - "rules": { - "eqeqeq": "error", - "import/order": "error", - "import/extensions": "error", - "import/newline-after-import": "error", - "jest/consistent-test-it": "warn", - "jest/expect-expect": "warn", - "jest/no-done-callback": "warn", - "jest/prefer-expect-resolves": "warn", - "jest/prefer-mock-promise-shorthand": "warn", - "jest/prefer-to-be": "warn", - "jest/prefer-to-have-length": "warn", - "no-param-reassign": "error", - "no-prototype-builtins": "off", - "no-throw-literal": "error", - "no-unused-vars": "off", - "no-useless-return": "error", - "object-shorthand": ["error", "methods"], - "prefer-template": "error", - "@stylistic/array-element-newline": ["error", "consistent"], - "@stylistic/arrow-parens": ["error", "always"], - "@stylistic/brace-style": "off", - "@stylistic/comma-dangle": ["error", "never"], - "@stylistic/dot-location": ["error", "property"], - "@stylistic/function-call-argument-newline": ["error", "consistent"], - "@stylistic/function-paren-newline": ["error", "consistent"], - "@stylistic/implicit-arrow-linebreak": ["error", "beside"], - "@stylistic/max-statements-per-line": ["error", { "max": 2 }], - "@stylistic/multiline-comment-style": "off", - "@stylistic/multiline-ternary": ["error", "always-multiline"], - "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 4 }], - "@stylistic/no-extra-parens": "off", - "@stylistic/no-tabs": "off", - "@stylistic/object-curly-spacing": ["error", "always"], - "@stylistic/object-property-newline": ["error", { "allowAllPropertiesOnSameLine": true }], - "@stylistic/operator-linebreak": ["error", "before"], - "@stylistic/padded-blocks": "off", - "@stylistic/quote-props": ["error", "as-needed"], - "@stylistic/quotes": ["error", "double"], - "@stylistic/indent": ["error", "tab"], - "@stylistic/semi": ["error", "always"], - "@stylistic/space-before-function-paren": ["error", "always"], - "@stylistic/spaced-comment": "off", - "unicorn/prefer-node-protocol": "error" - }, - "overrides": [ - { - "files": ["config/config.js*"], - "rules": { - "@stylistic/comma-dangle": "off", - "@stylistic/indent": "off", - "@stylistic/no-multi-spaces": "off" - } - }, - { - "files": ["tests/configs/modules/weather/*.js"], - "rules": { - "@stylistic/quotes": "off" - } - }, - { - "extends": ["plugin:package-json/recommended"], - "files": ["package.json"], - "parser": "jsonc-eslint-parser", - "plugins": ["package-json"], - "rules": { - "package-json/sort-collections": ["error", ["devDependencies", "dependencies", "peerDependencies", "config"]] - } - } - ] -} diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 9fd4d4a921..360ea62189 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -12,7 +12,7 @@ We use prettier for automatic linting of all our files: `npm run lint:prettier`. We use [ESLint](https://eslint.org) on our JavaScript files. -Our ESLint configuration is in our `.eslintrc.json` and `.eslintignore` files. +The ESLint configuration is in our `eslint.config.mjs` file. To run ESLint, use `npm run lint:js`. diff --git a/.prettierignore b/.prettierignore index daa42fbebb..0315d69371 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,5 @@ *.js -.eslintignore +*.mjs .husky/pre-commit .prettierignore /config diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eb6f3f344..c16a7613a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] removed installer only files (#3492) - [core] removed raspberry object from systeminformation (#3505) +- [linter] removed `eslint-plugin-import`, because it doesn't support ESLint v9. We will reenter it later when it does. ### Updated @@ -32,6 +33,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded (PR #3518 fixes issue #3504) - [core] Detail optimizations in `config_check.js` - [core] Updated minimal needed node version in `package.json` (currently v20.9.0) +- [linter] Switch to ESLint v9 and flat config and replace `eslint-plugin-unicorn` by `@eslint/js` ### Fixed diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..3338c1d786 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,121 @@ +import eslintPluginJest from "eslint-plugin-jest"; +import eslintPluginJs from "@eslint/js"; +import eslintPluginStylistic from "@stylistic/eslint-plugin"; +import globals from "globals"; + +const config = [ + eslintPluginJs.configs.recommended, + { + files: ["**/*.js"], + languageOptions: { + ecmaVersion: "latest", + globals: { + ...globals.browser, + ...globals.node, + ...globals.jest, + Log: "readonly", + MM: "readonly", + Module: "readonly", + config: "readonly", + moment: "readonly" + } + }, + plugins: { + ...eslintPluginStylistic.configs["all-flat"].plugins, + ...eslintPluginJest.configs["flat/recommended"].plugins + }, + rules: { + ...eslintPluginStylistic.configs["all-flat"].rules, + ...eslintPluginJest.configs["flat/recommended"].rules, + "@stylistic/array-element-newline": ["error", "consistent"], + "@stylistic/arrow-parens": ["error", "always"], + "@stylistic/brace-style": "off", + "@stylistic/comma-dangle": ["error", "never"], + "@stylistic/dot-location": ["error", "property"], + "@stylistic/function-call-argument-newline": ["error", "consistent"], + "@stylistic/function-paren-newline": ["error", "consistent"], + "@stylistic/implicit-arrow-linebreak": ["error", "beside"], + "@stylistic/indent": ["error", "tab"], + "@stylistic/max-statements-per-line": ["error", {max: 2}], + "@stylistic/multiline-comment-style": "off", + "@stylistic/multiline-ternary": ["error", "always-multiline"], + "@stylistic/newline-per-chained-call": ["error", {ignoreChainWithDepth: 4}], + "@stylistic/no-extra-parens": "off", + "@stylistic/no-tabs": "off", + "@stylistic/object-curly-spacing": ["error", "always"], + "@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}], + "@stylistic/operator-linebreak": ["error", "before"], + "@stylistic/padded-blocks": "off", + "@stylistic/quote-props": ["error", "as-needed"], + "@stylistic/quotes": ["error", "double"], + "@stylistic/semi": ["error", "always"], + "@stylistic/space-before-function-paren": ["error", "always"], + "@stylistic/spaced-comment": "off", + eqeqeq: "error", + "id-length": "off", + "init-declarations": "off", + "jest/consistent-test-it": "warn", + "jest/no-done-callback": "warn", + "jest/prefer-expect-resolves": "warn", + "jest/prefer-mock-promise-shorthand": "warn", + "jest/prefer-to-be": "warn", + "jest/prefer-to-have-length": "warn", + "max-lines-per-function": ["warn", 350], + "max-statements": "off", + "no-global-assign": "off", + "no-inline-comments": "off", + "no-magic-numbers": "off", + "no-param-reassign": "error", + "no-plusplus": "off", + "no-prototype-builtins": "off", + "no-ternary": "off", + "no-throw-literal": "error", + "no-undefined": "off", + "no-unused-vars": "off", + "no-useless-return": "error", + "no-warning-comments": "off", + "object-shorthand": ["error", "methods"], + "one-var": "off", + "prefer-destructuring": "off", + "prefer-template": "error", + "sort-keys": "off" + } + }, + { + files: ["**/*.mjs"], + languageOptions: { + ecmaVersion: "latest", + globals: { + ...globals.node + }, + sourceType: "module" + }, + plugins: { + ...eslintPluginStylistic.configs["all-flat"].plugins + }, + rules: { + ...eslintPluginStylistic.configs["all-flat"].rules, + "@stylistic/array-element-newline": "off", + "@stylistic/indent": ["error", "tab"], + "@stylistic/padded-blocks": ["error", "never"], + "@stylistic/quote-props": ["error", "as-needed"], + "func-style": "off", + "import/namespace": "off", + "max-lines-per-function": ["error", 100], + "no-magic-numbers": "off", + "one-var": "off", + "prefer-destructuring": "off" + } + }, + { + files: ["tests/configs/modules/weather/*.js"], + rules: { + "@stylistic/quotes": "off" + } + }, + { + ignores: ["config/**", "modules/**", "!modules/default/**", "js/positions.js"] + } +]; + +export default config; diff --git a/js/check_config.js b/js/check_config.js index 59c4221251..d159d9f45a 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -2,13 +2,14 @@ const path = require("node:path"); const fs = require("node:fs"); const Ajv = require("ajv"); const colors = require("ansis"); +const globals = require("globals"); const { Linter } = require("eslint"); const rootPath = path.resolve(`${__dirname}/../`); const Log = require(`${rootPath}/js/logger.js`); const Utils = require(`${rootPath}/js/utils.js`); -const linter = new Linter(); +const linter = new Linter({ configType: "flat" }); const ajv = new Ajv(); /** @@ -29,16 +30,14 @@ function checkConfigFile () { // Check if file is present if (fs.existsSync(configFileName) === false) { - Log.error(`File not found: ${configFileName}`); - throw new Error("No config file present!"); + throw new Error(`File not found: ${configFileName}\nNo config file present!`); } // Check permission try { fs.accessSync(configFileName, fs.F_OK); } catch (error) { - Log.error(error); - throw new Error("No permission to access config file!"); + throw new Error(`${error}\nNo permission to access config file!`); } // Validate syntax of the configuration file. @@ -47,30 +46,39 @@ function checkConfigFile () { // I'm not sure if all ever is utf-8 const configFile = fs.readFileSync(configFileName, "utf-8"); - // Explicitly tell linter that he might encounter es2024 syntax ("let config = {...}") - const errors = linter.verify(configFile, { - env: { - es2024: true - } - }); + const errors = linter.verify( + configFile, + { + languageOptions: { + ecmaVersion: "latest", + globals: { + ...globals.node + } + } + }, + configFileName + ); if (errors.length === 0) { Log.info(colors.green("Your configuration file doesn't contain syntax errors :)")); + validateModulePositions(configFileName); } else { - Log.error("Your configuration file contains syntax errors :("); + let errorMessage = "Your configuration file contains syntax errors :("; for (const error of errors) { - Log.error(`Line ${error.line} column ${error.column}: ${error.message}`); + errorMessage += `\nLine ${error.line} column ${error.column}: ${error.message}`; } - process.exit(1); + throw new Error(errorMessage); } +} +function validateModulePositions (configFileName) { Log.info("Checking modules structure configuration ..."); const positionList = Utils.getModulePositions(); // Make Ajv schema configuration of modules config - // only scan "module" and "position" + // Only scan "module" and "position" const schema = { type: "object", properties: { @@ -103,16 +111,21 @@ function checkConfigFile () { } else { const module = validate.errors[0].instancePath.split("/")[2]; const position = validate.errors[0].instancePath.split("/")[3]; - - Log.error("This module configuration contains errors:"); - Log.error(`\n${JSON.stringify(data.modules[module], null, 2)}`); + let errorMessage = "This module configuration contains errors:"; + errorMessage += `\n${JSON.stringify(data.modules[module], null, 2)}`; if (position) { - Log.error(`${position}: ${validate.errors[0].message}`); - Log.error(`\n${JSON.stringify(validate.errors[0].params.allowedValues, null, 2).slice(1, -1)}`); + errorMessage += `\n${position}: ${validate.errors[0].message}`; + errorMessage += `\n${JSON.stringify(validate.errors[0].params.allowedValues, null, 2).slice(1, -1)}`; } else { - Log.error(validate.errors[0].message); + errorMessage += validate.errors[0].message; } + Log.error(errorMessage); } } -checkConfigFile(); +try { + checkConfigFile(); +} catch (error) { + Log.error(error.message); + process.exit(1); +} diff --git a/package-lock.json b/package-lock.json index 995187b959..ded69986e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^8.57.0", + "eslint": "^9.11.1", "express": "^4.21.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -23,26 +23,25 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "^0.18.0", + "node-ical": "^0.19.0", "pm2": "^5.4.2", - "socket.io": "^4.7.5", + "socket.io": "^4.8.0", "suncalc": "^1.9.0", "systeminformation": "^5.23.5" }, "devDependencies": { + "@eslint/js": "^9.11.1", "@stylistic/eslint-plugin": "^2.8.0", "cspell": "^8.14.4", - "eslint-plugin-import": "^2.30.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.2.4", "eslint-plugin-package-json": "^0.15.3", - "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", - "jsdom": "^25.0.0", + "jsdom": "^25.0.1", "lint-staged": "^15.2.10", - "playwright": "^1.47.1", + "playwright": "^1.47.2", "prettier": "^3.3.3", "sinon": "^19.0.2", "stylelint": "^16.9.0", @@ -53,7 +52,7 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "electron": "^31.6.0" + "electron": "^32.1.2" } }, "node_modules/@altano/repository-tools": { @@ -1443,16 +1442,61 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -1460,7 +1504,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1492,35 +1536,6 @@ "concat-map": "0.0.1" } }, - "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1540,49 +1555,33 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", + "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^1.1.7" + "levn": "^0.4.1" }, "engines": { - "node": "*" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -1598,12 +1597,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "license": "BSD-3-Clause" + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -2360,13 +2365,6 @@ "debug": "^4.3.1" } }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", @@ -2567,6 +2565,12 @@ "@types/node": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "license": "MIT" + }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -2622,11 +2626,10 @@ "@types/istanbul-lib-report": "*" } }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, "node_modules/@types/keyv": { @@ -2655,13 +2658,6 @@ "undici-types": "~6.19.2" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/responselike": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", @@ -2821,12 +2817,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "license": "ISC" - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -3038,27 +3028,6 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-timsort": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", @@ -3076,65 +3045,6 @@ "node": ">=8" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", @@ -3213,12 +3123,12 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3568,19 +3478,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -3775,22 +3672,6 @@ "node": ">= 6" } }, - "node_modules/ci-info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", - "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cjs-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", @@ -3809,29 +3690,6 @@ "node": ">=0.3.6" } }, - "node_modules/clean-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", - "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/clean-regexp/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/clear-module": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz", @@ -4167,20 +4025,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, - "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "browserslist": "^4.23.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -4929,18 +4773,6 @@ "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -5003,9 +4835,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "31.6.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.6.0.tgz", - "integrity": "sha512-J64VtIF8DI/zsGgoYd3p5LbxAWjt59tk2cBSHJNzVhzgiVgDyPFkBwsqmN4gUvyv+6l6+WoYpYmYdapr2o4bPw==", + "version": "32.1.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-32.1.2.tgz", + "integrity": "sha512-CXe6doFzhmh1U7daOvUzmF6Cj8hssdYWMeEPRnRO6rB9/bbwMlWctcQ7P8NJXhLQ88/vYUJQrJvlJPh8qM0BRQ==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5068,9 +4900,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.1.tgz", + "integrity": "sha512-NEpDCw9hrvBW+hVEOK4T7v0jFJ++KgtPl4jKFwsZVfG1XhS0dCrSb3VMb9gPAd7VAdW52VT1EnaNiU2vM8C0og==", "license": "MIT", "dependencies": { "@types/cookie": "^0.4.1", @@ -5331,16 +5163,6 @@ "node": ">= 0.4" } }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - } - }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -5415,43 +5237,42 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", + "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.11.1", + "@eslint/plugin-kit": "^0.2.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", @@ -5463,152 +5284,20 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", - "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" + "url": "https://eslint.org/donate" }, - "engines": { - "node": ">=4" + "peerDependencies": { + "jiti": "*" }, "peerDependenciesMeta": { - "eslint": { + "jiti": { "optional": true } } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", - "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.9.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-jest": { "version": "28.8.3", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", @@ -5685,64 +5374,17 @@ "jsonc-eslint-parser": "^2.0.0" } }, - "node_modules/eslint-plugin-unicorn": { - "version": "55.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", - "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", - "@eslint-community/eslint-utils": "^4.4.0", - "ci-info": "^4.0.0", - "clean-regexp": "^1.0.0", - "core-js-compat": "^3.37.0", - "esquery": "^1.5.0", - "globals": "^15.7.0", - "indent-string": "^4.0.0", - "is-builtin-module": "^3.2.1", - "jsesc": "^3.0.2", - "pluralize": "^8.0.0", - "read-pkg-up": "^7.0.1", - "regexp-tree": "^0.1.27", - "regjsparser": "^0.10.0", - "semver": "^7.6.1", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=18.18" - }, - "funding": { - "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" - }, - "peerDependencies": { - "eslint": ">=8.56.0" - } - }, - "node_modules/eslint-plugin-unicorn/node_modules/globals": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -5752,7 +5394,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5787,35 +5428,6 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5838,7 +5450,6 @@ "version": "10.1.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.12.0", @@ -6240,15 +5851,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -6326,17 +5937,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -6425,6 +6035,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -6672,6 +6283,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -6704,6 +6316,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -6714,6 +6327,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -6808,15 +6422,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6909,12 +6520,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "license": "MIT" - }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -7036,13 +6641,6 @@ "node": ">=16.0.0" } }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -7277,21 +6875,12 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -7430,22 +7019,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -8479,13 +8052,13 @@ } }, "node_modules/jsdom": { - "version": "25.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.0.tgz", - "integrity": "sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dev": true, "license": "MIT", "dependencies": { - "cssstyle": "^4.0.1", + "cssstyle": "^4.1.0", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", @@ -8498,7 +8071,7 @@ "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.4", + "tough-cookie": "^5.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", @@ -8519,19 +8092,6 @@ } } }, - "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -9336,16 +8896,6 @@ "node": ">=4" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -9550,15 +9100,15 @@ } }, "node_modules/node-ical": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.18.0.tgz", - "integrity": "sha512-FrOUPztjw9OUgSB9o/ffhl86BiVClQTut97C2NqCwKIgOAcKPEw5UQMuSuNJO/Y4hqTyJdKZh2TCqNHQnE9YFg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.19.0.tgz", + "integrity": "sha512-WukOgHg7q44trEfA3wAYGHBvVP0LX6mR/STkI2da3Ke34F2Em0aUPIg+74SUf5qGymNraLSqUv6IpQYt2adOug==", "license": "Apache-2.0", "dependencies": { - "axios": "1.6.7", - "moment-timezone": "^0.5.44", + "axios": "1.7.7", + "moment-timezone": "^0.5.45", "rrule": "2.8.1", - "uuid": "^9.0.0" + "uuid": "^10.0.0" } }, "node_modules/node-int64": { @@ -9575,29 +9125,6 @@ "dev": true, "license": "MIT" }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -9707,58 +9234,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -9775,6 +9250,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "devOptional": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -10034,6 +9510,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10211,13 +9688,13 @@ } }, "node_modules/playwright": { - "version": "1.47.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.1.tgz", - "integrity": "sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", + "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.1" + "playwright-core": "1.47.2" }, "bin": { "playwright": "cli.js" @@ -10230,9 +9707,9 @@ } }, "node_modules/playwright-core": { - "version": "1.47.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.1.tgz", - "integrity": "sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", + "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10257,16 +9734,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/pm2": { "version": "5.4.2", "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.2.tgz", @@ -10660,13 +10127,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true, - "license": "MIT" - }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -10719,13 +10179,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true, - "license": "MIT" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -10827,116 +10280,6 @@ "node": ">=0.8" } }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -10961,16 +10304,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/regexp-tree": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", - "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", - "dev": true, - "license": "MIT", - "bin": { - "regexp-tree": "bin/regexp-tree" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -10989,28 +10322,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regjsparser": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", - "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -11063,13 +10374,6 @@ "node": ">=6" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true, - "license": "MIT" - }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -11212,22 +10516,6 @@ "dev": true, "license": "MIT" }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -11707,16 +10995,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", + "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -11851,28 +11139,6 @@ "source-map": "^0.6.0" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-correct/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, "node_modules/spdx-exceptions": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", @@ -12114,19 +11380,6 @@ "node": ">=6" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -12669,6 +11922,26 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "license": "MIT" }, + "node_modules/tldts": { + "version": "6.1.47", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.47.tgz", + "integrity": "sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.47" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.47", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.47.tgz", + "integrity": "sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==", + "dev": true, + "license": "MIT" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -12708,29 +11981,16 @@ } }, "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" + "node": ">=16" } }, "node_modules/tr46": { @@ -12759,42 +12019,6 @@ "typescript": ">=4.2.0" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -12851,18 +12075,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -13057,17 +12269,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -13085,9 +12286,9 @@ } }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -13112,28 +12313,6 @@ "node": ">=10.12.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, "node_modules/validate-npm-package-name": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", @@ -13390,6 +12569,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "devOptional": true, "license": "ISC" }, "node_modules/write-file-atomic": { diff --git a/package.json b/package.json index 685feffacb..a0cb41a110 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^8.57.0", + "eslint": "^9.11.1", "express": "^4.21.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -75,13 +75,12 @@ "systeminformation": "^5.23.5" }, "devDependencies": { + "@eslint/js": "^9.11.1", "@stylistic/eslint-plugin": "^2.8.0", "cspell": "^8.14.4", - "eslint-plugin-import": "^2.30.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.2.4", "eslint-plugin-package-json": "^0.15.3", - "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index eb4e138d01..d394d055c3 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -19,7 +19,7 @@ describe("server_functions tests", () => { }, text: fetchResponseHeadersText }; - // eslint-disable-next-line + fetch = jest.fn(); fetch.mockImplementation(() => fetchResponse); From 2e6e86887b786d08de5580c66e218ffa4dc4c079 Mon Sep 17 00:00:00 2001 From: Marc Landis Date: Wed, 25 Sep 2024 21:16:43 +0200 Subject: [PATCH 109/418] fix calendar showing previous day when using sliceMultiDayEvents (#3555) This bug is caused by #3543. The calculation for midnight adds a day but for endDate we want the day to be subtracted again. --- CHANGELOG.md | 1 + modules/default/calendar/calendar.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c16a7613a2..7d53acf2d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ _This release is scheduled to be released on 2024-10-01._ - [tests] Fixes calendar test by moving it from e2e to electron with fixed date (#3532) - [calendar] fixed sliceMultiDayEvents getting wrong count and displaying incorrect entries, Europe/Berlin (#3542) - [tests] ignore `js/positions.js` when linting (this file is created at runtime) +- [calendar] fixed sliceMultiDayEvents showing previous day without config enabled ## [2.28.0] - 2024-07-01 diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index f952bc5956..31b863eb28 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -651,7 +651,7 @@ Module.register("calendar", { const thisEvent = JSON.parse(JSON.stringify(event)); // clone object thisEvent.today = thisEvent.startDate >= today && thisEvent.startDate < today + ONE_DAY; thisEvent.tomorrow = !thisEvent.today && thisEvent.startDate >= today + ONE_DAY && thisEvent.startDate < today + 2 * ONE_DAY; - thisEvent.endDate = midnight; + thisEvent.endDate = moment(midnight, "x").clone().subtract(1, "day").format("x"); thisEvent.title += ` (${count}/${maxCount})`; splitEvents.push(thisEvent); From ebaeed935f338d49a3911eedd97fd115d0c920da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Thu, 26 Sep 2024 19:09:10 +0200 Subject: [PATCH 110/418] Engine except on node v21 (#3561) in addition of #3559 except with node v21: no security updates and EOL --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d53acf2d3..92cab193d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Updated SocketIO catch all to new API - [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded (PR #3518 fixes issue #3504) - [core] Detail optimizations in `config_check.js` -- [core] Updated minimal needed node version in `package.json` (currently v20.9.0) +- [core] Updated minimal needed node version in `package.json` (currently v20.9.0) (#3559) and except for v21 (no security updates) (#3561) - [linter] Switch to ESLint v9 and flat config and replace `eslint-plugin-unicorn` by `@eslint/js` ### Fixed diff --git a/package-lock.json b/package-lock.json index ded69986e8..d4a4e7857b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,7 @@ "stylelint-prettier": "^5.0.2" }, "engines": { - "node": ">=20.9.0" + "node": ">=20.9.0 <21 || 22" }, "optionalDependencies": { "electron": "^32.1.2" diff --git a/package.json b/package.json index a0cb41a110..1ecc90cfba 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "electron": "^31.6.0" }, "engines": { - "node": ">=20.9.0" + "node": ">=20.9.0 <21 || 22" }, "_moduleAliases": { "node_helper": "js/node_helper.js", From 731512c2e503f555f2172600f766c0c75f8de7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Thu, 26 Sep 2024 19:09:39 +0200 Subject: [PATCH 111/418] Electron rebuild tests update (#3563) # Update electron-rebuild.yaml * remove onoff library: Not updated since 3 years, don't work with last rpi Os * add node-libgpiod library in replacement --- .github/workflows/electron-rebuild.yaml | 4 +++- CHANGELOG.md | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index 2d22fcedb0..fa09f43d82 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -21,8 +21,10 @@ jobs: run: npm run install-mm - name: Install @electron/rebuild run: npm install @electron/rebuild + - name: Install node-libgpiod deps + run: sudo apt-get install gpiod libgpiod2 libgpiod-dev - name: Install some test library to be rebuilded - run: npm install onoff node-pty drivelist + run: npm install node-libgpiod node-pty drivelist - name: Run electron-rebuild run: npx electron-rebuild continue-on-error: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 92cab193d1..f5bb539e77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,12 +18,14 @@ _This release is scheduled to be released on 2024-10-01._ - [core] elements are now removed from `index.html` when loading script or stylesheet files fails - [core] Added `MODULE_DOM_UPDATED` notification each time the DOM is re-rendered via `updateDom` (#3534) - [tests] added minimal needed node version to tests (currently v20.9.0) to avoid releases with wrong node version info +- [tests] Added `node-libgpiod` library to electron-rebuild tests (#3563) ### Removed - [core] removed installer only files (#3492) - [core] removed raspberry object from systeminformation (#3505) - [linter] removed `eslint-plugin-import`, because it doesn't support ESLint v9. We will reenter it later when it does. +- [tests] removed `onoff` library from electron-rebuild tests (#3563) ### Updated From d9eefff0661b466ee9883eebc3768a062480edc3 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sat, 28 Sep 2024 08:52:09 -0500 Subject: [PATCH 112/418] fix double load of positions now that check:config at startup is active (#3565) after adding check:config to the MM startup process, #3450, we accidentally discover module positions more than once, and write the file each time.. add a check to see if we have done this work already --- CHANGELOG.md | 1 + js/utils.js | 33 ++++++++++++++++++--------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5bb539e77..fb6b35514a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ _This release is scheduled to be released on 2024-10-01._ - [core] Detail optimizations in `config_check.js` - [core] Updated minimal needed node version in `package.json` (currently v20.9.0) (#3559) and except for v21 (no security updates) (#3561) - [linter] Switch to ESLint v9 and flat config and replace `eslint-plugin-unicorn` by `@eslint/js` +- [core] fix discovering module positions twice after #3450 ### Fixed diff --git a/js/utils.js b/js/utils.js index 5163997195..9536a1b070 100644 --- a/js/utils.js +++ b/js/utils.js @@ -49,21 +49,24 @@ module.exports = { }, getModulePositions () { - // get the lines of the index.html - const lines = fs.readFileSync(indexFileName).toString().split(os.EOL); - // loop thru the lines - lines.forEach((line) => { - // run the regex on each line - const results = regionRegEx.exec(line); - // if the regex returned something - if (results && results.length > 0) { - // get the position parts and replace space with underscore - const positionName = results[1].replace(" ", "_"); - // add it to the list - modulePositions.push(positionName); - } - }); - fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`); + // if not already discovered + if (modulePositions.length === 0) { + // get the lines of the index.html + const lines = fs.readFileSync(indexFileName).toString().split(os.EOL); + // loop thru the lines + lines.forEach((line) => { + // run the regex on each line + const results = regionRegEx.exec(line); + // if the regex returned something + if (results && results.length > 0) { + // get the position parts and replace space with underscore + const positionName = results[1].replace(" ", "_"); + // add it to the list + modulePositions.push(positionName); + } + }); + fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`); + } // return the list to the caller return modulePositions; } From 719eca49fe7c1127f588a17d01ac730fe1ebb776 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 28 Sep 2024 22:33:53 +0200 Subject: [PATCH 113/418] update dependencies, nail down node-ical version to 0.18.0 (#3566) - node-ical use `0.18.0` instead of `^0.18.0` in `package.json` - cleanup `package-lock.json` --- .github/workflows/dep-review.yaml | 2 + CHANGELOG.md | 1 + package-lock.json | 1022 ++++++++++++++--------------- package.json | 10 +- vendor/package-lock.json | 8 +- vendor/package.json | 2 +- 6 files changed, 494 insertions(+), 551 deletions(-) diff --git a/.github/workflows/dep-review.yaml b/.github/workflows/dep-review.yaml index 141e821b9c..838f157ecb 100644 --- a/.github/workflows/dep-review.yaml +++ b/.github/workflows/dep-review.yaml @@ -16,3 +16,5 @@ jobs: uses: actions/checkout@v4 - name: "Dependency Review" uses: actions/dependency-review-action@v4 + with: + allow-ghsas: GHSA-8hc4-vh64-cxmj diff --git a/CHANGELOG.md b/CHANGELOG.md index fb6b35514a..2834fa70fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) - [core] Updated dependencies including stylistic-eslint +- [core] nail down `node-ical` version to `0.18.0` with exception `allow-ghsas: GHSA-8hc4-vh64-cxmj` in `dep-review.yaml` (which should removed after next `node-ical` update) - [core] Updated SocketIO catch all to new API - [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded (PR #3518 fixes issue #3504) - [core] Detail optimizations in `config_check.js` diff --git a/package-lock.json b/package-lock.json index d4a4e7857b..89d93e5204 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "^0.19.0", + "node-ical": "0.18.0", "pm2": "^5.4.2", "socket.io": "^4.8.0", "suncalc": "^1.9.0", @@ -34,7 +34,7 @@ "@stylistic/eslint-plugin": "^2.8.0", "cspell": "^8.14.4", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.2.4", + "eslint-plugin-jsdoc": "^50.3.0", "eslint-plugin-package-json": "^0.15.3", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", @@ -52,7 +52,7 @@ "node": ">=20.9.0 <21 || 22" }, "optionalDependencies": { - "electron": "^32.1.2" + "electron": "^31.6.0" } }, "node_modules/@altano/repository-tools": { @@ -157,19 +157,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/helper-compilation-targets": { "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", @@ -1024,9 +1011,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-html": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.5.tgz", - "integrity": "sha512-p0brEnRybzSSWi8sGbuVEf7jSTDmXPx7XhQUb5bgG6b54uj+Z0Qf0V2n8b/LWwIPJNd1GygaO9l8k3HTCy1h4w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.6.tgz", + "integrity": "sha512-cLWHfuOhE4wqwC12up6Doxo2u1xxVhX1A8zriR4CUD+osFQzUIcBK1ykNXppga+rt1WyypaJdTU2eV6OpzYrgQ==", "dev": true, "license": "MIT" }, @@ -1101,9 +1088,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.4.tgz", - "integrity": "sha512-yzqVTY4P5neom4z9orV2IFOqDZ7fDotmisP7nwQkEmftoELgn5CUtNdnJhWDoDQQn6yrxOxA8jEqmyETIWzN4Q==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.5.tgz", + "integrity": "sha512-oAOGWuJYU3DlO+cAsStKMWN8YEkBue25cRC9EwdiL5Z84nchU20UIoYrLfIQejMlZca+1GyrNeyxRAgn4KiivA==", "dev": true, "license": "MIT" }, @@ -1115,9 +1102,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-powershell": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.8.tgz", - "integrity": "sha512-Eg64BccQp5oEJ+V/O2G27KaLWmuOL2AWMOs2470adUihOleRfW8j9XwAEGCS+JKSnDb2mksWA72Z6kDqH138IQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.9.tgz", + "integrity": "sha512-Vi0h0rlxS39tgTyUtxI6L3BPHH7MLPkLWCYkNfb/buQuNJYNFdHiF4bqoqVdJ/7ZrfIfNg4i6rzocnwGRn2ruw==", "dev": true, "license": "MIT" }, @@ -1167,9 +1154,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.3.tgz", - "integrity": "sha512-5Wn5JG4IzCboX5pjISdkipsPKGaz1//iuBZdHl4US5x7mO4jOGXLpjzx6ZoPM4PXUlMEFz9NJRCDepAu8fXVtA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.4.tgz", + "integrity": "sha512-AHS25sYEzWze/aFglp9ODKSu+phjkuGx+OLwIcmOnvyn8axtSq5GCn9UqS4XG1/Qn0UG2Lgb4i5PJbZ0QNPNXQ==", "dev": true, "license": "MIT" }, @@ -1381,6 +1368,16 @@ "global-agent": "^3.0.0" } }, + "node_modules/@electron/get/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/@electron/get/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1434,9 +1431,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -1707,16 +1704,6 @@ "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -1800,18 +1787,25 @@ } } }, - "node_modules/@jest/core/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/@jest/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/@jest/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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { "node": ">=8" } @@ -1937,6 +1931,29 @@ } } }, + "node_modules/@jest/reporters/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/@jest/reporters/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/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2650,9 +2667,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz", - "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==", + "version": "20.16.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", + "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -2703,14 +2720,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", - "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", + "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0" + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2721,9 +2738,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", - "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", + "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", "dev": true, "license": "MIT", "engines": { @@ -2735,14 +2752,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", - "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", + "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/visitor-keys": "8.7.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2764,16 +2781,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", + "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0" + "@typescript-eslint/scope-manager": "8.7.0", + "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/typescript-estree": "8.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2787,13 +2804,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", - "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", + "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/types": "8.7.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2919,26 +2936,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -3123,12 +3131,12 @@ } }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3420,9 +3428,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "dev": true, "funding": [ { @@ -3440,8 +3448,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, @@ -3555,9 +3563,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001660", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", - "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", + "version": "1.0.30001664", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", + "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", "dev": true, "funding": [ { @@ -3672,6 +3680,22 @@ "node": ">= 6" } }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cjs-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", @@ -3707,29 +3731,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clear-module/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clear-module/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -3802,6 +3803,16 @@ "node": ">=12" } }, + "node_modules/cliui/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/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3834,6 +3845,19 @@ "node": ">=8" } }, + "node_modules/cliui/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/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -3928,12 +3952,13 @@ } }, "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=18" } }, "node_modules/comment-json": { @@ -4072,6 +4097,16 @@ } } }, + "node_modules/cosmiconfig/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -4283,29 +4318,6 @@ "node": ">=18" } }, - "node_modules/cspell-lib/node_modules/env-paths": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", - "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cspell-lib/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cspell-trie-lib": { "version": "8.14.4", "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.14.4.tgz", @@ -4321,19 +4333,6 @@ "node": ">=18" } }, - "node_modules/cspell/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/cspell/node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -4347,104 +4346,51 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/cspell/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "node_modules/css-functions-list": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", + "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=12 || >=16" } }, - "node_modules/cspell/node_modules/file-entry-cache": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", - "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^5.0.0" + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">=18" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/cspell/node_modules/flat-cache": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", - "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "license": "MIT", - "dependencies": { - "flatted": "^3.3.1", - "keyv": "^4.5.4" + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/cspell/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/cssstyle": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/css-functions-list": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", - "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12 || >=16" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssstyle": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", - "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", - "dev": true, - "license": "MIT", - "dependencies": { - "rrweb-cssom": "^0.7.1" + "rrweb-cssom": "^0.7.1" }, "engines": { "node": ">=18" @@ -4835,9 +4781,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "32.1.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-32.1.2.tgz", - "integrity": "sha512-CXe6doFzhmh1U7daOvUzmF6Cj8hssdYWMeEPRnRO6rB9/bbwMlWctcQ7P8NJXhLQ88/vYUJQrJvlJPh8qM0BRQ==", + "version": "31.6.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-31.6.0.tgz", + "integrity": "sha512-J64VtIF8DI/zsGgoYd3p5LbxAWjt59tk2cBSHJNzVhzgiVgDyPFkBwsqmN4gUvyv+6l6+WoYpYmYdapr2o4bPw==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4854,9 +4800,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.23", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.23.tgz", - "integrity": "sha512-mBhODedOXg4v5QWwl21DjM5amzjmI1zw9EPrPK/5Wx7C8jt33bpZNrC7OhHUG3pxRtbLpr3W2dXT+Ph1SsfRZA==", + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", + "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==", "dev": true, "license": "ISC" }, @@ -4984,13 +4930,16 @@ } }, "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "devOptional": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/environment": { @@ -5039,6 +4988,15 @@ "node": ">=8" } }, + "node_modules/envsub/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -5325,9 +5283,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.2.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.2.4.tgz", - "integrity": "sha512-020jA+dXaXdb+TML3ZJBvpPmzwbNROjnYuTYi/g6A5QEmEjhptz4oPJDKkOGMIByNxsPpdTLzSU1HYVqebOX1w==", + "version": "50.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.0.tgz", + "integrity": "sha512-P7qDB/RckdKETpBM4CtjHRQ5qXByPmFhRi86sN3E+J+tySchq+RSOGGhI2hDIefmmKFuTi/1ACjqsnDJDDDfzg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5375,9 +5333,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -5391,9 +5349,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5418,6 +5376,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/eslint/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5428,6 +5395,31 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/eslint/node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -5446,15 +5438,27 @@ "node": "*" } }, + "node_modules/eslint/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5787,9 +5791,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", "license": "MIT" }, "node_modules/fastest-levenshtein": { @@ -5851,15 +5855,16 @@ } }, "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", + "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^4.0.0" + "flat-cache": "^5.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18" } }, "node_modules/fill-range": { @@ -5937,16 +5942,17 @@ } }, "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", + "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", + "flatted": "^3.3.1", "keyv": "^4.5.4" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/flatted": { @@ -6370,16 +6376,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/global-directory/node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -6408,6 +6404,13 @@ "node": ">=6" } }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, "node_modules/global-prefix/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -6835,6 +6838,27 @@ "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -6894,10 +6918,14 @@ "license": "ISC" }, "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "license": "ISC" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/internal-slot": { "version": "1.0.7", @@ -7530,22 +7558,6 @@ } } }, - "node_modules/jest-config/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -7892,22 +7904,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-util/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/jest-util/node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -8092,6 +8088,19 @@ } } }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -8345,16 +8354,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/lint-staged/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/lint-staged/node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -8594,19 +8593,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/log-update/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", @@ -8653,22 +8639,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -9090,9 +9060,9 @@ } }, "node_modules/nise/node_modules/path-to-regexp": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.1.0.tgz", - "integrity": "sha512-Bqn3vc8CMHty6zuD+tG23s6v2kwxslHEhTj4eYaVKGIEB+YX/2wd0/rgXLFD9G9id9KCtbVy/3ZgmvZjpa0UdQ==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", "dev": true, "license": "MIT", "engines": { @@ -9100,15 +9070,15 @@ } }, "node_modules/node-ical": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.19.0.tgz", - "integrity": "sha512-WukOgHg7q44trEfA3wAYGHBvVP0LX6mR/STkI2da3Ke34F2Em0aUPIg+74SUf5qGymNraLSqUv6IpQYt2adOug==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.18.0.tgz", + "integrity": "sha512-FrOUPztjw9OUgSB9o/ffhl86BiVClQTut97C2NqCwKIgOAcKPEw5UQMuSuNJO/Y4hqTyJdKZh2TCqNHQnE9YFg==", "license": "Apache-2.0", "dependencies": { - "axios": "1.7.7", - "moment-timezone": "^0.5.45", + "axios": "1.6.7", + "moment-timezone": "^0.5.44", "rrule": "2.8.1", - "uuid": "^10.0.0" + "uuid": "^9.0.0" } }, "node_modules/node-int64": { @@ -9180,9 +9150,9 @@ "license": "MIT" }, "node_modules/nwsapi": { - "version": "2.2.12", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", - "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", "dev": true, "license": "MIT" }, @@ -9418,23 +9388,24 @@ "license": "MIT" }, "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz", + "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==", + "dev": true, "license": "MIT", "dependencies": { - "callsites": "^3.0.0" + "callsites": "^3.1.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/parse-imports": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.1.1.tgz", - "integrity": "sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", + "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", "dev": true, - "license": "Apache-2.0", + "license": "Apache-2.0 AND MIT", "dependencies": { "es-module-lexer": "^1.5.3", "slashes": "^3.0.12" @@ -10411,7 +10382,7 @@ "node": ">=8" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { + "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", @@ -10421,15 +10392,6 @@ "node": ">=8" } }, - "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==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/resolve.exports": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", @@ -11226,51 +11188,45 @@ "node": ">=10" } }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/string-length/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", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "node_modules/string-length/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", - "engines": { - "node": ">=12" + "dependencies": { + "ansi-regex": "^5.0.1" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string.prototype.matchall": { @@ -11349,15 +11305,19 @@ } }, "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==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-bom": { @@ -11522,6 +11482,16 @@ "stylelint": ">=16.0.0" } }, + "node_modules/stylelint/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/stylelint/node_modules/balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", @@ -11536,33 +11506,6 @@ "dev": true, "license": "MIT" }, - "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", - "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/stylelint/node_modules/flat-cache": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", - "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.3.1", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/stylelint/node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -11594,16 +11537,6 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/stylelint/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -11645,35 +11578,6 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/stylelint/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/stylelint/node_modules/write-file-atomic": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", @@ -11827,6 +11731,16 @@ "node": ">=10.0.0" } }, + "node_modules/table/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/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -11877,6 +11791,19 @@ "node": ">=8" } }, + "node_modules/table/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/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -11923,22 +11850,22 @@ "license": "MIT" }, "node_modules/tldts": { - "version": "6.1.47", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.47.tgz", - "integrity": "sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==", + "version": "6.1.48", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.48.tgz", + "integrity": "sha512-SPbnh1zaSzi/OsmHb1vrPNnYuwJbdWjwo5TbBYYMlTtH3/1DSb41t8bcSxkwDmmbG2q6VLPVvQc7Yf23T+1EEw==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.47" + "tldts-core": "^6.1.48" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.47", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.47.tgz", - "integrity": "sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==", + "version": "6.1.48", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.48.tgz", + "integrity": "sha512-3gD9iKn/n2UuFH1uilBviK9gvTNT6iYwdqrj1Vr5mh8FuelvpRNaYVH4pNYqUgOGU4aAdL9X35eLuuj0gRsx+A==", "dev": true, "license": "MIT" }, @@ -12075,6 +12002,19 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -12230,9 +12170,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -12250,8 +12190,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -12286,9 +12226,9 @@ } }, "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -12356,6 +12296,12 @@ "lodash": "^4.17.14" } }, + "node_modules/vizion/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, "node_modules/vscode-languageserver-textdocument": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", @@ -12523,19 +12469,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", @@ -12549,22 +12482,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -12697,6 +12614,16 @@ "node": ">=12" } }, + "node_modules/yargs/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/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -12729,6 +12656,19 @@ "node": ">=8" } }, + "node_modules/yargs/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/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 1ecc90cfba..7aa3bdae04 100644 --- a/package.json +++ b/package.json @@ -68,9 +68,9 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "^0.18.0", + "node-ical": "0.18.0", "pm2": "^5.4.2", - "socket.io": "^4.7.5", + "socket.io": "^4.8.0", "suncalc": "^1.9.0", "systeminformation": "^5.23.5" }, @@ -79,14 +79,14 @@ "@stylistic/eslint-plugin": "^2.8.0", "cspell": "^8.14.4", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.2.4", + "eslint-plugin-jsdoc": "^50.3.0", "eslint-plugin-package-json": "^0.15.3", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", - "jsdom": "^25.0.0", + "jsdom": "^25.0.1", "lint-staged": "^15.2.10", - "playwright": "^1.47.1", + "playwright": "^1.47.2", "prettier": "^3.3.3", "sinon": "^19.0.2", "stylelint": "^16.9.0", diff --git a/vendor/package-lock.json b/vendor/package-lock.json index b4370bf642..413d00ea06 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.6.0", "animate.css": "^4.1.1", - "croner": "^8.1.1", + "croner": "^8.1.2", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", @@ -56,9 +56,9 @@ } }, "node_modules/croner": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/croner/-/croner-8.1.1.tgz", - "integrity": "sha512-1VdUuRnQP4drdFkS8NKvDR1NBgevm8TOuflcaZEKsxw42CxonjW/2vkj1AKlinJb4ZLwBcuWF9GiPr7FQc6AQA==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/croner/-/croner-8.1.2.tgz", + "integrity": "sha512-ypfPFcAXHuAZRCzo3vJL6ltENzniTjwe/qsLleH1V2/7SRDjgvRQyrLmumFTLmjFax4IuSxfGXEn79fozXcJog==", "license": "MIT", "engines": { "node": ">=18.0" diff --git a/vendor/package.json b/vendor/package.json index d303ee7ae2..8e7365e2e7 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -13,7 +13,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.6.0", "animate.css": "^4.1.1", - "croner": "^8.1.1", + "croner": "^8.1.2", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "nunjucks": "^3.2.4", From d84d612df592dc0ce2c3d96de4efcdedd5d40ea1 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 18 Sep 2024 22:40:44 +0200 Subject: [PATCH 114/418] Release 2.29.0 --- CHANGELOG.md | 6 ++++-- Collaboration.md | 50 +++++++++++++++++++++++++++++++++-------------- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2834fa70fd..30de4cd9ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,11 @@ This project adheres to [Semantic Versioning](https://semver.org/). ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². -## [2.29.0] - Unreleased (`develop` branch) +## [2.29.0] - 2024-10-01 -_This release is scheduled to be released on 2024-10-01._ +Thanks to: @bugsounet, @dkallen78, @jargordon, @khassel, @KristjanESPERANTO, @MarcLandis, @rejas, @ryan-d-williams, @sdetweil, @skpanagiotis. + +> ⚠️ This release needs nodejs version `v20` or `v22`, minimum version is `v20.9.0` ### Added diff --git a/Collaboration.md b/Collaboration.md index 6d2da4d6a3..a0c64bd9bc 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -15,24 +15,44 @@ This document describes how collaborators of this repository should work togethe ## Releases -Are done by @rejas or @khassel. +Are done by + +- [ ] @rejas +- [ ] @sdetweil +- [ ] @khassel + +### Pre-Deployment steps + +- [ ] update dependencies (a few days before) ### Deployment steps -- pull latest `develop` branch -- update `package.json` to reflect correct version number -- run `npm install` to generate new `package-lock.json` -- test `develop` branch -- update `CHANGELOG.md` (don't forget to add all contributor names) -- commit and push all changes -- after successful test run via github actions: create pull request to `master` branch -- after PR tests run without issues, merge PR -- create new release with corresponding version tag -- publish release notes with link to github release on forum in new locked topic +- [ ] pull latest `develop` branch +- [ ] update `package.json` and `package-lock.json` to reflect correct version number `2.xx.0` +- [ ] test `develop` branch +- [ ] update `CHANGELOG.md` + - [ ] add all contributor names: `...` + - [ ] add min. node version: > ⚠️ This release needs nodejs version `v20` or `v22`, minimum version is `v20.9.0` +- [ ] commit and push all changes +- [ ] after successful test run via github actions: create pull request from `develop` to `master` branch + - [ ] add label `mastermerge` + - [ ] title of the PR is `Release 2.xx.0` + - [ ] description of the PR is the section of the `CHANGELOG.md` +- [ ] after PR tests run without issues, merge PR +- [ ] create new release with + - [ ] corresponding version tag `v2.xx.0` + - [ ] a release name: `...` + - [ ] description of the PR is the section of the `CHANGELOG.md` ### Draft new development release -- checkout `develop` branch -- update `package.json` to reflect correct version number `2.xx.0-develop` -- draft new section in `CHANGELOG.md` -- commit and publish `develop` branch +- [ ] checkout `develop` branch +- [ ] update `package.json` and `package-lock.json` to reflect correct version number `2.xx.0-develop` +- [ ] draft new section in `CHANGELOG.md` +- [ ] commit and publish `develop` branch + +### After release + +- [ ] publish release notes with link to github release on forum in new locked topic +- [ ] close all issues with label `ready (coming with next release)` +- [ ] release new documentation by merging `develop` on `master` in documentation repository diff --git a/package-lock.json b/package-lock.json index 89d93e5204..e79a681f1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.29.0-develop", + "version": "2.29.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.29.0-develop", + "version": "2.29.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 7aa3bdae04..7b80b4e277 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.29.0-develop", + "version": "2.29.0", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From d1be92a4269a1bb58eba168f9150e65fdad36ccc Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 1 Oct 2024 00:09:29 +0200 Subject: [PATCH 115/418] Prepare v2.30.0-develop --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30de4cd9ba..b1157d0632 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ This project adheres to [Semantic Versioning](https://semver.org/). ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². +## [2.30.0] - Unreleased (`develop` branch) + +_This release is scheduled to be released on 2025-01-01._ + +### Added + +### Removed + +### Updated + +### Fixed + ## [2.29.0] - 2024-10-01 Thanks to: @bugsounet, @dkallen78, @jargordon, @khassel, @KristjanESPERANTO, @MarcLandis, @rejas, @ryan-d-williams, @sdetweil, @skpanagiotis. diff --git a/package-lock.json b/package-lock.json index e79a681f1a..219181c19f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.29.0", + "version": "2.30.0-develop", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.29.0", + "version": "2.30.0-develop", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 7b80b4e277..8a7b1a0129 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.29.0", + "version": "2.30.0-develop", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From 4c7c859ae66a965fa9a20db65000cb4d4612250a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Wed, 2 Oct 2024 18:31:57 +0200 Subject: [PATCH 116/418] [Electron rebuild] Removed node-pty and drivelist from rebuilded test (#3575) Related to #3573 I think it's better to keep new library node-libgpiod for testing (library to manage RPI gpio for pir sensor management) and delete others Only one test is better --- .github/workflows/electron-rebuild.yaml | 4 ++-- CHANGELOG.md | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index fa09f43d82..e5bfa13c3e 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -23,8 +23,8 @@ jobs: run: npm install @electron/rebuild - name: Install node-libgpiod deps run: sudo apt-get install gpiod libgpiod2 libgpiod-dev - - name: Install some test library to be rebuilded - run: npm install node-libgpiod node-pty drivelist + - name: Install test library (node-libgpiod) to be rebuilded + run: npm install node-libgpiod - name: Run electron-rebuild run: npx electron-rebuild continue-on-error: false diff --git a/CHANGELOG.md b/CHANGELOG.md index b1157d0632..d02ecc7ee1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ _This release is scheduled to be released on 2025-01-01._ ### Removed +- [tests] Removed node-pty and drivelist from rebuilded test (#3575) + ### Updated ### Fixed From ee98a0c7e59de8b4c1b3bdaae1c32078bdc0c753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Wed, 2 Oct 2024 18:33:46 +0200 Subject: [PATCH 117/418] [UpdateNotification] Fix pm2 using detection when pm2 script is in MagicMirror root folder (#3576) I discover this bug: When pm2 `sh` script is on MagicMirror root folder, updatenotification is not able to detect pm2 using ``` 0|MagicMirror | [2024-10-02 17:23:09.215] [DEBUG] Version Compare: 2.30.0-develop 2.30.0-develop --> true 0|MagicMirror | [2024-10-02 17:23:09.216] [DEBUG] Status: online 0|MagicMirror | [2024-10-02 17:23:09.216] [DEBUG] PM2 MagicMirror starting from Path: /home/bugsounet/MagicMirror-dev 0|MagicMirror | [2024-10-02 17:23:09.216] [DEBUG] MagicMirror Path /home/bugsounet/MagicMirror-dev/ 0|MagicMirror | [2024-10-02 17:23:09.216] [DEBUG] Compare: false 0|MagicMirror | [2024-10-02 17:23:09.216] [INFO] updatenotification: [PM2] You are not using pm2 ``` --- CHANGELOG.md | 2 ++ modules/default/updatenotification/update_helper.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d02ecc7ee1..2abaa52e4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ _This release is scheduled to be released on 2025-01-01._ ### Fixed +- [updatenotification] Fix pm2 using detection when pm2 script is in MagicMirror root folder (#3576) + ## [2.29.0] - 2024-10-01 Thanks to: @bugsounet, @dkallen78, @jargordon, @khassel, @KristjanESPERANTO, @MarcLandis, @rejas, @ryan-d-williams, @sdetweil, @skpanagiotis. diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index 122b6b3567..40d0da8a7b 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -187,7 +187,7 @@ class Updater { return; } list.forEach((pm) => { - if (pm.pm2_env.version === this.version && pm.pm2_env.status === "online" && pm.pm2_env.pm_cwd.includes(`${this.root_path}/`)) { + if (pm.pm2_env.version === this.version && pm.pm2_env.status === "online" && pm.pm2_env.pm_cwd.includes(`${this.root_path}`)) { this.PM2 = pm.name; this.usePM2 = true; Log.info("updatenotification: [PM2] You are using pm2 with", this.PM2); From 0eafa19096d7fc5335819703b2f4ae19ad2099b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 18:41:36 +0200 Subject: [PATCH 118/418] Bump eslint-plugin-jsdoc from 50.3.0 to 50.3.1 (#3571) Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 50.3.0 to 50.3.1.
Release notes

Sourced from eslint-plugin-jsdoc's releases.

v50.3.1

50.3.1 (2024-10-01)

Bug Fixes

  • check-alignment: handle zero indent; fixes #1322 (34866bc)
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=eslint-plugin-jsdoc&package-manager=npm_and_yarn&previous-version=50.3.0&new-version=50.3.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 9 ++++----- package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 219181c19f..db78c71114 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,7 @@ "@stylistic/eslint-plugin": "^2.8.0", "cspell": "^8.14.4", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.3.0", + "eslint-plugin-jsdoc": "^50.3.1", "eslint-plugin-package-json": "^0.15.3", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", @@ -5283,11 +5283,10 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.0.tgz", - "integrity": "sha512-P7qDB/RckdKETpBM4CtjHRQ5qXByPmFhRi86sN3E+J+tySchq+RSOGGhI2hDIefmmKFuTi/1ACjqsnDJDDDfzg==", + "version": "50.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.1.tgz", + "integrity": "sha512-SY9oUuTMr6aWoJggUS40LtMjsRzJPB5ZT7F432xZIHK3EfHF+8i48GbUBpwanrtlL9l1gILNTHK9o8gEhYLcKA==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@es-joy/jsdoccomment": "~0.48.0", "are-docs-informative": "^0.0.2", diff --git a/package.json b/package.json index 8a7b1a0129..843b63437d 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "@stylistic/eslint-plugin": "^2.8.0", "cspell": "^8.14.4", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.3.0", + "eslint-plugin-jsdoc": "^50.3.1", "eslint-plugin-package-json": "^0.15.3", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", From f91340ceca18d556d6ac8cf28656ad510aba47d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 18:42:05 +0200 Subject: [PATCH 119/418] Bump helmet from 7.1.0 to 8.0.0 (#3570) Bumps [helmet](https://github.com/helmetjs/helmet) from 7.1.0 to 8.0.0.
Changelog

Sourced from helmet's changelog.

8.0.0

Changed

  • Breaking: Strict-Transport-Security now has a max-age of 365 days, up from 180
  • Breaking: Content-Security-Policy middleware now throws an error if a directive should have quotes but does not, such as self instead of 'self'. See #454
  • Breaking: Content-Security-Policy's getDefaultDirectives now returns a deep copy. This only affects users who were mutating the result
  • Breaking: Strict-Transport-Security now throws an error when "includeSubDomains" option is misspelled. This was previously a warning

Removed

  • Breaking: Drop support for Node 16 and 17. Node 18+ is now required

7.2.0 - 2024-09-28

Changed

  • Content-Security-Policy middleware now warns if a directive should have quotes but does not, such as self instead of 'self'. This will be an error in future versions. See #454
Commits
  • 9a8e6d5 8.0.0
  • 6562cd7 CSP: speed up getDefaultDirectives
  • a8befb3 getDefaultDirectives should do a deep copy
  • 558ef2c HSTS: throw when misspelling "includeSubDomains" option
  • 73e7595 Content-Security-Policy: throw if directive value lacks necessary quotes
  • 76410e1 Content-Security-Policy can now use Object.hasOwn
  • 293bd18 Strict-Transport-Security: increase max-age to 1 year
  • 898cdc4 Require Node 18+
  • 7e2b069 7.2.0
  • 7bea915 Update changelog for 7.2.0 release
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=helmet&package-manager=npm_and_yarn&previous-version=7.1.0&new-version=8.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 11 +++++------ package.json | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index db78c71114..d004ae6732 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "express": "^4.21.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", - "helmet": "^7.1.0", + "helmet": "^8.0.0", "html-to-text": "^9.0.5", "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", @@ -6635,12 +6635,11 @@ } }, "node_modules/helmet": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", - "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", - "license": "MIT", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.0.0.tgz", + "integrity": "sha512-VyusHLEIIO5mjQPUI1wpOAEu+wl6Q0998jzTxqUYGE45xCIcAxy3MsbEK/yyJUJ3ADeMoB6MornPH6GMWAf+Pw==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/html-encoding-sniffer": { diff --git a/package.json b/package.json index 843b63437d..fb58c4d644 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "express": "^4.21.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", - "helmet": "^7.1.0", + "helmet": "^8.0.0", "html-to-text": "^9.0.5", "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", From f51fbe39c4882e11df178d5ed8de7cd07630ffd3 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 4 Oct 2024 21:47:07 +0200 Subject: [PATCH 120/418] reactivated `stale.yaml` as github action (#3577) The old `stale.yaml` seems not to work anymore, so I set up the same content in a new github workflow. I think we should use it again to get rid of old issues. --- .github/stale.yaml | 19 ------------------- .github/workflows/stale.yaml | 20 ++++++++++++++++++++ CHANGELOG.md | 2 ++ 3 files changed, 22 insertions(+), 19 deletions(-) delete mode 100644 .github/stale.yaml create mode 100644 .github/workflows/stale.yaml diff --git a/.github/stale.yaml b/.github/stale.yaml deleted file mode 100644 index 136532c1a7..0000000000 --- a/.github/stale.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 60 -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 -# Issues with these labels will never be considered stale -exemptLabels: - - pinned - - security - - under investigation - - pr welcome -# Label to use when marking an issue as stale -staleLabel: wontfix -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: false diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 0000000000..e2acfe8258 --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,20 @@ +name: "Close stale issues and PRs" + +on: + schedule: + - cron: "30 1 * * 6" # every Saturday at 1:30 + +permissions: + issues: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + stale-issue-message: "This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions." + days-before-issue-stale: 60 + days-before-issue-close: 7 + stale-issue-label: "wontfix" + exempt-issue-labels: "pinned,security,under investigation,pr welcome" diff --git a/CHANGELOG.md b/CHANGELOG.md index 2abaa52e4e..ce55b0228d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated +- [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) + ### Fixed - [updatenotification] Fix pm2 using detection when pm2 script is in MagicMirror root folder (#3576) From 961bae637c9506e12321112519cfc10b43a34bab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Sat, 5 Oct 2024 15:23:36 +0200 Subject: [PATCH 121/418] [core] add try / catch on mode_helper loading (#3578) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a library is missing on an 3rd party module, MM² stop loading and display a black screen. (I'm sure it's happened to everyone.) So, I have added a try/catch block and it's avoid black screen, display errors and allow continue loading with next module --- CHANGELOG.md | 1 + js/app.js | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce55b0228d..2b9ac1ac53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Fixed - [updatenotification] Fix pm2 using detection when pm2 script is in MagicMirror root folder (#3576) +- [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) ## [2.29.0] - 2024-10-01 diff --git a/js/app.js b/js/app.js index 8ae002e9f0..5ab23356ee 100644 --- a/js/app.js +++ b/js/app.js @@ -197,7 +197,13 @@ function App () { // if the helper was found if (loadHelper) { - const Module = require(helperPath); + let Module; + try { + Module = require(helperPath); + } catch (e) { + Log.error(`Error when loading ${moduleName}:`, e.message); + return; + } let m = new Module(); if (m.requiresVersion) { From c7dcf542cfb8709e4bfe991326b001b2ab93a5ff Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 5 Oct 2024 19:47:34 +0200 Subject: [PATCH 122/418] allow manually running stale workflow (#3580) --- .github/workflows/stale.yaml | 1 + CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index e2acfe8258..742c702157 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -1,6 +1,7 @@ name: "Close stale issues and PRs" on: + workflow_dispatch: # needed for manually running this workflow schedule: - cron: "30 1 * * 6" # every Saturday at 1:30 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b9ac1ac53..6f58bd9a23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated -- [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) +- [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity). ### Fixed From 0130dc45ab99ac981bb379fa06b1aa364f14dca2 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 5 Oct 2024 22:41:41 +0200 Subject: [PATCH 123/418] =?UTF-8?q?stale=20workflow:=20increase=20operatio?= =?UTF-8?q?ns-per-run=20(default=3D30)=20so=20that=20all=20=E2=80=A6=20(#3?= =?UTF-8?q?581)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …issues can be processed --- .github/workflows/stale.yaml | 1 + CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 742c702157..fd73269c86 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -17,5 +17,6 @@ jobs: stale-issue-message: "This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions." days-before-issue-stale: 60 days-before-issue-close: 7 + operations-per-run: 100 stale-issue-label: "wontfix" exempt-issue-labels: "pinned,security,under investigation,pr welcome" diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f58bd9a23..2b9ac1ac53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated -- [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity). +- [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) ### Fixed From 7489e51a676afa91a7d64a15824ddeadcaf110d6 Mon Sep 17 00:00:00 2001 From: HeikoGr <20295490+HeikoGr@users.noreply.github.com> Date: Fri, 11 Oct 2024 08:51:00 +0200 Subject: [PATCH 124/418] Change default for weatherEndpoint according to API 3.0 (#3583) since API 3.0 is default, weatherEndpoint should be set to "/onecall" Fixes #3574 ATTENTION: since lat / lon defaults to 0 / 0, the weather plugins works after this patch, but shows the weather from https://de.wikipedia.org/wiki/Null_Island if lat / lon is not manually set. --------- Co-authored-by: Karsten Hassel Co-authored-by: Pedro Lamas --- CHANGELOG.md | 1 + .../weather/providers/openweathermap.js | 31 +++---------------- .../weather/currentweather_compliments.js | 2 ++ .../modules/weather/currentweather_default.js | 2 ++ .../modules/weather/currentweather_options.js | 2 ++ .../modules/weather/currentweather_units.js | 2 ++ .../weather/forecastweather_absolute.js | 3 +- .../weather/forecastweather_default.js | 5 +-- .../weather/forecastweather_options.js | 3 +- .../modules/weather/forecastweather_units.js | 3 +- .../modules/weather/hourlyweather_default.js | 2 ++ .../modules/weather/hourlyweather_options.js | 2 ++ .../hourlyweather_showPrecipitation.js | 2 ++ 13 files changed, 29 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b9ac1ac53..280652d1f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ _This release is scheduled to be released on 2025-01-01._ - [updatenotification] Fix pm2 using detection when pm2 script is in MagicMirror root folder (#3576) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) +- [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) ## [2.29.0] - 2024-10-01 diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index 3f29ed5562..dc902705ce 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -17,10 +17,13 @@ WeatherProvider.register("openweathermap", { defaults: { apiVersion: "3.0", apiBase: "https://api.openweathermap.org/data/", - weatherEndpoint: "", // can be "onecall", "forecast" or "weather" (for current) + // weatherEndpoint is "/onecall" since API 3.0 + // "/onecall", "/forecast" or "/weather" only for pro customers + weatherEndpoint: "/onecall", locationID: false, location: false, - lat: 0, // the onecall endpoint needs lat / lon values, it doesn't support the locationId + // the /onecall endpoint needs lat / lon values, it doesn't support the locationId + lat: 0, lon: 0, apiKey: "" }, @@ -90,30 +93,6 @@ WeatherProvider.register("openweathermap", { .finally(() => this.updateAvailable()); }, - /** - * Overrides method for setting config to check if endpoint is correct for hourly - * @param {object} config The configuration object - */ - setConfig (config) { - this.config = config; - if (!this.config.weatherEndpoint) { - switch (this.config.type) { - case "hourly": - this.config.weatherEndpoint = "/onecall"; - break; - case "daily": - case "forecast": - this.config.weatherEndpoint = "/forecast"; - break; - case "current": - this.config.weatherEndpoint = "/weather"; - break; - default: - Log.error("weatherEndpoint not configured and could not resolve it based on type"); - } - } - }, - /** OpenWeatherMap Specific Methods - These are not part of the default provider methods */ /* * Gets the complete url for the request diff --git a/tests/configs/modules/weather/currentweather_compliments.js b/tests/configs/modules/weather/currentweather_compliments.js index 25303fd3cb..73e5855453 100644 --- a/tests/configs/modules/weather/currentweather_compliments.js +++ b/tests/configs/modules/weather/currentweather_compliments.js @@ -15,6 +15,8 @@ let config = { position: "bottom_bar", config: { location: "Munich", + weatherProvider: "openweathermap", + weatherEndpoint: "/weather", mockData: '"#####WEATHERDATA#####"' } } diff --git a/tests/configs/modules/weather/currentweather_default.js b/tests/configs/modules/weather/currentweather_default.js index b6601aa378..d2ad0a6bf4 100644 --- a/tests/configs/modules/weather/currentweather_default.js +++ b/tests/configs/modules/weather/currentweather_default.js @@ -8,6 +8,8 @@ let config = { config: { location: "Munich", showHumidity: "feelslike", + weatherProvider: "openweathermap", + weatherEndpoint: "/weather", mockData: '"#####WEATHERDATA#####"' } } diff --git a/tests/configs/modules/weather/currentweather_options.js b/tests/configs/modules/weather/currentweather_options.js index f7c2e3f116..903d3df760 100644 --- a/tests/configs/modules/weather/currentweather_options.js +++ b/tests/configs/modules/weather/currentweather_options.js @@ -5,6 +5,8 @@ let config = { position: "bottom_bar", config: { location: "Munich", + weatherProvider: "openweathermap", + weatherEndpoint: "/weather", mockData: '"#####WEATHERDATA#####"', windUnits: "beaufort", showWindDirectionAsArrow: true, diff --git a/tests/configs/modules/weather/currentweather_units.js b/tests/configs/modules/weather/currentweather_units.js index eedbc37de8..856acf2635 100644 --- a/tests/configs/modules/weather/currentweather_units.js +++ b/tests/configs/modules/weather/currentweather_units.js @@ -7,6 +7,8 @@ let config = { position: "bottom_bar", config: { location: "Munich", + weatherProvider: "openweathermap", + weatherEndpoint: "/weather", mockData: '"#####WEATHERDATA#####"', decimalSymbol: ",", showHumidity: "wind" diff --git a/tests/configs/modules/weather/forecastweather_absolute.js b/tests/configs/modules/weather/forecastweather_absolute.js index a2640d3025..4b3884fe3a 100644 --- a/tests/configs/modules/weather/forecastweather_absolute.js +++ b/tests/configs/modules/weather/forecastweather_absolute.js @@ -8,8 +8,9 @@ let config = { config: { type: "forecast", location: "Munich", - mockData: '"#####WEATHERDATA#####"', + weatherProvider: "openweathermap", weatherEndpoint: "/forecast/daily", + mockData: '"#####WEATHERDATA#####"', absoluteDates: true } } diff --git a/tests/configs/modules/weather/forecastweather_default.js b/tests/configs/modules/weather/forecastweather_default.js index 4cddef62fa..3192b4c9dc 100644 --- a/tests/configs/modules/weather/forecastweather_default.js +++ b/tests/configs/modules/weather/forecastweather_default.js @@ -8,8 +8,9 @@ let config = { config: { type: "forecast", location: "Munich", - mockData: '"#####WEATHERDATA#####"', - weatherEndpoint: "/forecast/daily" + weatherProvider: "openweathermap", + weatherEndpoint: "/forecast/daily", + mockData: '"#####WEATHERDATA#####"' } } ] diff --git a/tests/configs/modules/weather/forecastweather_options.js b/tests/configs/modules/weather/forecastweather_options.js index 0eea8292ed..ec55dc6cd1 100644 --- a/tests/configs/modules/weather/forecastweather_options.js +++ b/tests/configs/modules/weather/forecastweather_options.js @@ -8,8 +8,9 @@ let config = { config: { type: "forecast", location: "Munich", - mockData: '"#####WEATHERDATA#####"', + weatherProvider: "openweathermap", weatherEndpoint: "/forecast/daily", + mockData: '"#####WEATHERDATA#####"', showPrecipitationAmount: true, colored: true, tableClass: "myTableClass" diff --git a/tests/configs/modules/weather/forecastweather_units.js b/tests/configs/modules/weather/forecastweather_units.js index 8ac58a43b0..b9ba11e79c 100644 --- a/tests/configs/modules/weather/forecastweather_units.js +++ b/tests/configs/modules/weather/forecastweather_units.js @@ -8,8 +8,9 @@ let config = { config: { type: "forecast", location: "Munich", - mockData: '"#####WEATHERDATA#####"', + weatherProvider: "openweathermap", weatherEndpoint: "/forecast/daily", + mockData: '"#####WEATHERDATA#####"', decimalSymbol: "_", showPrecipitationAmount: true } diff --git a/tests/configs/modules/weather/hourlyweather_default.js b/tests/configs/modules/weather/hourlyweather_default.js index 8e46b44cab..ed6f66db39 100644 --- a/tests/configs/modules/weather/hourlyweather_default.js +++ b/tests/configs/modules/weather/hourlyweather_default.js @@ -8,6 +8,8 @@ let config = { config: { type: "hourly", location: "Berlin", + weatherProvider: "openweathermap", + weatherEndpoint: "/onecall", mockData: '"#####WEATHERDATA#####"' } } diff --git a/tests/configs/modules/weather/hourlyweather_options.js b/tests/configs/modules/weather/hourlyweather_options.js index b37fd7b9f1..5422075e6d 100644 --- a/tests/configs/modules/weather/hourlyweather_options.js +++ b/tests/configs/modules/weather/hourlyweather_options.js @@ -8,6 +8,8 @@ let config = { config: { type: "hourly", location: "Berlin", + weatherProvider: "openweathermap", + weatherEndpoint: "/onecall", mockData: '"#####WEATHERDATA#####"', hourlyForecastIncrements: 2 } diff --git a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js index 0e79858f16..1448172f81 100644 --- a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js +++ b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js @@ -8,6 +8,8 @@ let config = { config: { type: "hourly", location: "Berlin", + weatherProvider: "openweathermap", + weatherEndpoint: "/onecall", mockData: '"#####WEATHERDATA#####"', showPrecipitationAmount: true, showPrecipitationProbability: true From 1b80e8756320a3adad4d703738391f1702d0e063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Fri, 11 Oct 2024 11:57:34 +0200 Subject: [PATCH 125/418] [core] test electron v32 and electron rebuild (#3584) test deps: nan v2.22.0 and electron v32 --- CHANGELOG.md | 1 + package-lock.json | 9 +++++---- package.json | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 280652d1f4..d6d5a3e30a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated - [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) +- [core] Update electron dependency to v32 (test electron rebuild) ### Fixed diff --git a/package-lock.json b/package-lock.json index d004ae6732..d5d71855f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "ajv": "^8.17.1", "ansis": "^3.3.2", "console-stamp": "^3.1.2", + "electron": "^32.2.0", "envsub": "^4.1.0", "eslint": "^9.11.1", "express": "^4.21.0", @@ -52,7 +53,7 @@ "node": ">=20.9.0 <21 || 22" }, "optionalDependencies": { - "electron": "^31.6.0" + "electron": "^32.2.0" } }, "node_modules/@altano/repository-tools": { @@ -4781,9 +4782,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "31.6.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.6.0.tgz", - "integrity": "sha512-J64VtIF8DI/zsGgoYd3p5LbxAWjt59tk2cBSHJNzVhzgiVgDyPFkBwsqmN4gUvyv+6l6+WoYpYmYdapr2o4bPw==", + "version": "32.2.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.0.tgz", + "integrity": "sha512-Xy82QBQrEiQysoxsv6lnhHAcWNNe6vV6QqH3OPFXhEj/T9oAsBHEhZuuYHINSSsUE7zRSj+J9sNwJYOjisT0Vw==", "hasInstallScript": true, "license": "MIT", "optional": true, diff --git a/package.json b/package.json index fb58c4d644..4314be6141 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "stylelint-prettier": "^5.0.2" }, "optionalDependencies": { - "electron": "^31.6.0" + "electron": "^32.2.0" }, "engines": { "node": ">=20.9.0 <21 || 22" From 3d1e8ab849ed4b87174c838a8dfd82c20b5e16f5 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 12 Oct 2024 07:53:58 +0200 Subject: [PATCH 126/418] add address and ipWhitelist to all test configs (#3585) All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) --- CHANGELOG.md | 1 + tests/configs/customregions.js | 2 ++ tests/configs/modules/alert/default.js | 2 ++ tests/configs/modules/calendar/auth-default.js | 2 ++ tests/configs/modules/calendar/bad_rrule.js | 2 ++ tests/configs/modules/calendar/basic-auth.js | 2 ++ tests/configs/modules/calendar/changed-port.js | 2 ++ tests/configs/modules/calendar/custom.js | 2 ++ tests/configs/modules/calendar/default.js | 2 ++ tests/configs/modules/calendar/exdate_la_at_midnight_dst.js | 2 ++ tests/configs/modules/calendar/exdate_la_at_midnight_std.js | 2 ++ tests/configs/modules/calendar/exdate_la_before_midnight.js | 2 ++ tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js | 2 ++ tests/configs/modules/calendar/exdate_syd_at_midnight_std.js | 2 ++ tests/configs/modules/calendar/exdate_syd_before_midnight.js | 2 ++ tests/configs/modules/calendar/fail-basic-auth.js | 2 ++ tests/configs/modules/calendar/long-fullday-event.js | 2 ++ tests/configs/modules/calendar/old-basic-auth.js | 2 ++ tests/configs/modules/calendar/recurring.js | 2 ++ tests/configs/modules/calendar/rrule_until.js | 2 ++ tests/configs/modules/calendar/show-duplicates-in-calendar.js | 2 ++ tests/configs/modules/calendar/single-fullday-event.js | 2 ++ tests/configs/modules/calendar/sliceMultiDayEvents.js | 2 ++ tests/configs/modules/clock/clock_12hr.js | 2 ++ tests/configs/modules/clock/clock_24hr.js | 2 ++ tests/configs/modules/clock/clock_analog.js | 2 ++ tests/configs/modules/clock/clock_displaySeconds_false.js | 2 ++ tests/configs/modules/clock/clock_showDateAnalog.js | 2 ++ tests/configs/modules/clock/clock_showPeriodUpper.js | 2 ++ tests/configs/modules/clock/clock_showSunMoon.js | 2 ++ tests/configs/modules/clock/clock_showTime.js | 2 ++ tests/configs/modules/clock/clock_showWeek.js | 2 ++ tests/configs/modules/clock/es/clock_12hr.js | 2 ++ tests/configs/modules/clock/es/clock_24hr.js | 2 ++ tests/configs/modules/clock/es/clock_showPeriodUpper.js | 2 ++ tests/configs/modules/clock/es/clock_showWeek.js | 2 ++ tests/configs/modules/compliments/compliments_animateCSS.js | 2 ++ .../compliments/compliments_animateCSS_fallbackToDefault.js | 2 ++ .../compliments_animateCSS_invertedAnimationName.js | 2 ++ tests/configs/modules/compliments/compliments_anytime.js | 2 ++ tests/configs/modules/compliments/compliments_cron_entry.js | 2 ++ tests/configs/modules/compliments/compliments_date.js | 2 ++ .../configs/modules/compliments/compliments_e2e_cron_entry.js | 2 ++ tests/configs/modules/compliments/compliments_only_anytime.js | 2 ++ tests/configs/modules/compliments/compliments_parts_day.js | 2 ++ tests/configs/modules/compliments/compliments_remote.js | 2 ++ .../modules/compliments/compliments_specialDayUnique_false.js | 2 ++ .../modules/compliments/compliments_specialDayUnique_true.js | 2 ++ tests/configs/modules/display.js | 2 ++ tests/configs/modules/helloworld/helloworld.js | 2 ++ tests/configs/modules/helloworld/helloworld_default.js | 2 ++ tests/configs/modules/newsfeed/default.js | 2 ++ tests/configs/modules/newsfeed/ignore_items.js | 2 ++ tests/configs/modules/newsfeed/incorrect_url.js | 2 ++ tests/configs/modules/newsfeed/prohibited_words.js | 2 ++ tests/configs/modules/positions.js | 2 ++ tests/configs/modules/weather/currentweather_compliments.js | 2 ++ tests/configs/modules/weather/currentweather_default.js | 2 ++ tests/configs/modules/weather/currentweather_options.js | 2 ++ tests/configs/modules/weather/currentweather_units.js | 2 ++ tests/configs/modules/weather/forecastweather_absolute.js | 2 ++ tests/configs/modules/weather/forecastweather_default.js | 2 ++ tests/configs/modules/weather/forecastweather_options.js | 2 ++ tests/configs/modules/weather/forecastweather_units.js | 2 ++ tests/configs/modules/weather/hourlyweather_default.js | 2 ++ tests/configs/modules/weather/hourlyweather_options.js | 2 ++ .../configs/modules/weather/hourlyweather_showPrecipitation.js | 2 ++ tests/configs/without_modules.js | 3 ++- 68 files changed, 135 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6d5a3e30a..fd3057e76d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ _This release is scheduled to be released on 2025-01-01._ - [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) - [core] Update electron dependency to v32 (test electron rebuild) +- [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) ### Fixed diff --git a/tests/configs/customregions.js b/tests/configs/customregions.js index 5fe4ee28c4..5f1c643fb9 100644 --- a/tests/configs/customregions.js +++ b/tests/configs/customregions.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: // Using exotic content. This is why don't accept go to JSON configuration file (() => { diff --git a/tests/configs/modules/alert/default.js b/tests/configs/modules/alert/default.js index ea77b574be..9e0238fdb4 100644 --- a/tests/configs/modules/alert/default.js +++ b/tests/configs/modules/alert/default.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "alert", diff --git a/tests/configs/modules/calendar/auth-default.js b/tests/configs/modules/calendar/auth-default.js index 99ce3922b0..eb20683ee7 100644 --- a/tests/configs/modules/calendar/auth-default.js +++ b/tests/configs/modules/calendar/auth-default.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/bad_rrule.js b/tests/configs/modules/calendar/bad_rrule.js index 3810794384..f3e95e4f94 100644 --- a/tests/configs/modules/calendar/bad_rrule.js +++ b/tests/configs/modules/calendar/bad_rrule.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, logLevel: ["INFO", "LOG", "WARN", "ERROR", "DEBUG"], modules: [ diff --git a/tests/configs/modules/calendar/basic-auth.js b/tests/configs/modules/calendar/basic-auth.js index f322f573d7..28c25ef363 100644 --- a/tests/configs/modules/calendar/basic-auth.js +++ b/tests/configs/modules/calendar/basic-auth.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/changed-port.js b/tests/configs/modules/calendar/changed-port.js index 15bf920739..5cb5c63f54 100644 --- a/tests/configs/modules/calendar/changed-port.js +++ b/tests/configs/modules/calendar/changed-port.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/custom.js b/tests/configs/modules/calendar/custom.js index 8552bcbe5c..9a2b4c6a95 100644 --- a/tests/configs/modules/calendar/custom.js +++ b/tests/configs/modules/calendar/custom.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/default.js b/tests/configs/modules/calendar/default.js index 67c943d3c9..0032d1c5a3 100644 --- a/tests/configs/modules/calendar/default.js +++ b/tests/configs/modules/calendar/default.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js index fb431ad7e6..c9fbb4da1c 100644 --- a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js @@ -8,6 +8,8 @@ * See tests/electron/modules/calendar_spec.js */ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js index b6ea3011dc..e59c4114f5 100644 --- a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js @@ -8,6 +8,8 @@ * See tests/electron/modules/calendar_spec.js */ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/exdate_la_before_midnight.js b/tests/configs/modules/calendar/exdate_la_before_midnight.js index e5518df797..c91188d3cc 100644 --- a/tests/configs/modules/calendar/exdate_la_before_midnight.js +++ b/tests/configs/modules/calendar/exdate_la_before_midnight.js @@ -8,6 +8,8 @@ * See tests/electron/modules/calendar_spec.js */ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js index e6287e2b02..edd09798a4 100644 --- a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js @@ -8,6 +8,8 @@ * See tests/electron/modules/calendar_spec.js */ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js index 9000387998..a6b5fdfbb6 100644 --- a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js @@ -8,6 +8,8 @@ * See tests/electron/modules/calendar_spec.js */ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/exdate_syd_before_midnight.js b/tests/configs/modules/calendar/exdate_syd_before_midnight.js index 3b176329ec..b8b3017da2 100644 --- a/tests/configs/modules/calendar/exdate_syd_before_midnight.js +++ b/tests/configs/modules/calendar/exdate_syd_before_midnight.js @@ -8,6 +8,8 @@ * See tests/electron/modules/calendar_spec.js */ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/fail-basic-auth.js b/tests/configs/modules/calendar/fail-basic-auth.js index 2a58d623d6..c6eae35bea 100644 --- a/tests/configs/modules/calendar/fail-basic-auth.js +++ b/tests/configs/modules/calendar/fail-basic-auth.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/long-fullday-event.js b/tests/configs/modules/calendar/long-fullday-event.js index 80137810d8..4606e05c21 100644 --- a/tests/configs/modules/calendar/long-fullday-event.js +++ b/tests/configs/modules/calendar/long-fullday-event.js @@ -5,6 +5,8 @@ * MIT Licensed. */ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/old-basic-auth.js b/tests/configs/modules/calendar/old-basic-auth.js index 08dc407316..18aae723f4 100644 --- a/tests/configs/modules/calendar/old-basic-auth.js +++ b/tests/configs/modules/calendar/old-basic-auth.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/recurring.js b/tests/configs/modules/calendar/recurring.js index fe1d36629e..f393385d3d 100644 --- a/tests/configs/modules/calendar/recurring.js +++ b/tests/configs/modules/calendar/recurring.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/rrule_until.js b/tests/configs/modules/calendar/rrule_until.js index e553ebd194..90daa9a3e4 100644 --- a/tests/configs/modules/calendar/rrule_until.js +++ b/tests/configs/modules/calendar/rrule_until.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/show-duplicates-in-calendar.js b/tests/configs/modules/calendar/show-duplicates-in-calendar.js index c4a1c95811..7ad420944d 100644 --- a/tests/configs/modules/calendar/show-duplicates-in-calendar.js +++ b/tests/configs/modules/calendar/show-duplicates-in-calendar.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/single-fullday-event.js b/tests/configs/modules/calendar/single-fullday-event.js index 7dae36115f..ff0773c200 100644 --- a/tests/configs/modules/calendar/single-fullday-event.js +++ b/tests/configs/modules/calendar/single-fullday-event.js @@ -5,6 +5,8 @@ * MIT Licensed. */ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/calendar/sliceMultiDayEvents.js b/tests/configs/modules/calendar/sliceMultiDayEvents.js index ebcf2cec4f..987ccd8945 100644 --- a/tests/configs/modules/calendar/sliceMultiDayEvents.js +++ b/tests/configs/modules/calendar/sliceMultiDayEvents.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/clock/clock_12hr.js b/tests/configs/modules/clock/clock_12hr.js index 4a7318f58d..46ac92f3ae 100644 --- a/tests/configs/modules/clock/clock_12hr.js +++ b/tests/configs/modules/clock/clock_12hr.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/clock/clock_24hr.js b/tests/configs/modules/clock/clock_24hr.js index f75287eb04..b1aee73d11 100644 --- a/tests/configs/modules/clock/clock_24hr.js +++ b/tests/configs/modules/clock/clock_24hr.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "clock", diff --git a/tests/configs/modules/clock/clock_analog.js b/tests/configs/modules/clock/clock_analog.js index 98331ee389..f3c3ffd353 100644 --- a/tests/configs/modules/clock/clock_analog.js +++ b/tests/configs/modules/clock/clock_analog.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "clock", diff --git a/tests/configs/modules/clock/clock_displaySeconds_false.js b/tests/configs/modules/clock/clock_displaySeconds_false.js index 181e8c6085..db2c5d1af0 100644 --- a/tests/configs/modules/clock/clock_displaySeconds_false.js +++ b/tests/configs/modules/clock/clock_displaySeconds_false.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/clock/clock_showDateAnalog.js b/tests/configs/modules/clock/clock_showDateAnalog.js index 772261c187..0ce9e28941 100644 --- a/tests/configs/modules/clock/clock_showDateAnalog.js +++ b/tests/configs/modules/clock/clock_showDateAnalog.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/clock/clock_showPeriodUpper.js b/tests/configs/modules/clock/clock_showPeriodUpper.js index 78a1f315ef..d6ce8cb3de 100644 --- a/tests/configs/modules/clock/clock_showPeriodUpper.js +++ b/tests/configs/modules/clock/clock_showPeriodUpper.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/clock/clock_showSunMoon.js b/tests/configs/modules/clock/clock_showSunMoon.js index c5766aa255..4472f6d919 100644 --- a/tests/configs/modules/clock/clock_showSunMoon.js +++ b/tests/configs/modules/clock/clock_showSunMoon.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/clock/clock_showTime.js b/tests/configs/modules/clock/clock_showTime.js index 5e68951e2f..bcb112cd09 100644 --- a/tests/configs/modules/clock/clock_showTime.js +++ b/tests/configs/modules/clock/clock_showTime.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/clock/clock_showWeek.js b/tests/configs/modules/clock/clock_showWeek.js index 7af4740655..d47aa89782 100644 --- a/tests/configs/modules/clock/clock_showWeek.js +++ b/tests/configs/modules/clock/clock_showWeek.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/clock/es/clock_12hr.js b/tests/configs/modules/clock/es/clock_12hr.js index 66d380f8bf..8295bfa3ac 100644 --- a/tests/configs/modules/clock/es/clock_12hr.js +++ b/tests/configs/modules/clock/es/clock_12hr.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], language: "es", timeFormat: 12, diff --git a/tests/configs/modules/clock/es/clock_24hr.js b/tests/configs/modules/clock/es/clock_24hr.js index 752c5fd054..f9334c4b2e 100644 --- a/tests/configs/modules/clock/es/clock_24hr.js +++ b/tests/configs/modules/clock/es/clock_24hr.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], language: "es", modules: [ diff --git a/tests/configs/modules/clock/es/clock_showPeriodUpper.js b/tests/configs/modules/clock/es/clock_showPeriodUpper.js index 76f5fd0433..d314e4bb61 100644 --- a/tests/configs/modules/clock/es/clock_showPeriodUpper.js +++ b/tests/configs/modules/clock/es/clock_showPeriodUpper.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], language: "es", timeFormat: 12, diff --git a/tests/configs/modules/clock/es/clock_showWeek.js b/tests/configs/modules/clock/es/clock_showWeek.js index c43eccdaef..0a3d326fc7 100644 --- a/tests/configs/modules/clock/es/clock_showWeek.js +++ b/tests/configs/modules/clock/es/clock_showWeek.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], language: "es", timeFormat: 12, diff --git a/tests/configs/modules/compliments/compliments_animateCSS.js b/tests/configs/modules/compliments/compliments_animateCSS.js index 1e3d3d2f9d..505b7d4d74 100644 --- a/tests/configs/modules/compliments/compliments_animateCSS.js +++ b/tests/configs/modules/compliments/compliments_animateCSS.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js b/tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js index 48f41cbfeb..fa98a5645f 100644 --- a/tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js +++ b/tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js b/tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js index 310210bfc1..863b8c7702 100644 --- a/tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js +++ b/tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/compliments/compliments_anytime.js b/tests/configs/modules/compliments/compliments_anytime.js index 102b59ca8e..5491f6a138 100644 --- a/tests/configs/modules/compliments/compliments_anytime.js +++ b/tests/configs/modules/compliments/compliments_anytime.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/compliments/compliments_cron_entry.js b/tests/configs/modules/compliments/compliments_cron_entry.js index 59a6659293..a2010d5e96 100644 --- a/tests/configs/modules/compliments/compliments_cron_entry.js +++ b/tests/configs/modules/compliments/compliments_cron_entry.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/compliments/compliments_date.js b/tests/configs/modules/compliments/compliments_date.js index f1822f6a1c..80c0730902 100644 --- a/tests/configs/modules/compliments/compliments_date.js +++ b/tests/configs/modules/compliments/compliments_date.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/compliments/compliments_e2e_cron_entry.js b/tests/configs/modules/compliments/compliments_e2e_cron_entry.js index a4d1c5d8f2..eaba541241 100644 --- a/tests/configs/modules/compliments/compliments_e2e_cron_entry.js +++ b/tests/configs/modules/compliments/compliments_e2e_cron_entry.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/compliments/compliments_only_anytime.js b/tests/configs/modules/compliments/compliments_only_anytime.js index 8714bebd7e..09b3cf22f9 100644 --- a/tests/configs/modules/compliments/compliments_only_anytime.js +++ b/tests/configs/modules/compliments/compliments_only_anytime.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/compliments/compliments_parts_day.js b/tests/configs/modules/compliments/compliments_parts_day.js index f5a2bb7f42..a38e0e22af 100644 --- a/tests/configs/modules/compliments/compliments_parts_day.js +++ b/tests/configs/modules/compliments/compliments_parts_day.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/compliments/compliments_remote.js b/tests/configs/modules/compliments/compliments_remote.js index 5d8543e1c8..844f14fdb5 100644 --- a/tests/configs/modules/compliments/compliments_remote.js +++ b/tests/configs/modules/compliments/compliments_remote.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/compliments/compliments_specialDayUnique_false.js b/tests/configs/modules/compliments/compliments_specialDayUnique_false.js index e4cb64c6ab..1effd099ce 100644 --- a/tests/configs/modules/compliments/compliments_specialDayUnique_false.js +++ b/tests/configs/modules/compliments/compliments_specialDayUnique_false.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/compliments/compliments_specialDayUnique_true.js b/tests/configs/modules/compliments/compliments_specialDayUnique_true.js index 3d578611c8..6e10799d71 100644 --- a/tests/configs/modules/compliments/compliments_specialDayUnique_true.js +++ b/tests/configs/modules/compliments/compliments_specialDayUnique_true.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/display.js b/tests/configs/modules/display.js index c66e586a7b..230b7bdd6b 100644 --- a/tests/configs/modules/display.js +++ b/tests/configs/modules/display.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "helloworld", diff --git a/tests/configs/modules/helloworld/helloworld.js b/tests/configs/modules/helloworld/helloworld.js index d9aa0cb442..a6bf31c36f 100644 --- a/tests/configs/modules/helloworld/helloworld.js +++ b/tests/configs/modules/helloworld/helloworld.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "helloworld", diff --git a/tests/configs/modules/helloworld/helloworld_default.js b/tests/configs/modules/helloworld/helloworld_default.js index b0b35c7e48..25f8ffa2e4 100644 --- a/tests/configs/modules/helloworld/helloworld_default.js +++ b/tests/configs/modules/helloworld/helloworld_default.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "helloworld", diff --git a/tests/configs/modules/newsfeed/default.js b/tests/configs/modules/newsfeed/default.js index 0023c4c386..10e70b2efd 100644 --- a/tests/configs/modules/newsfeed/default.js +++ b/tests/configs/modules/newsfeed/default.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/newsfeed/ignore_items.js b/tests/configs/modules/newsfeed/ignore_items.js index 425ef78398..b7e5ffd5ad 100644 --- a/tests/configs/modules/newsfeed/ignore_items.js +++ b/tests/configs/modules/newsfeed/ignore_items.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/newsfeed/incorrect_url.js b/tests/configs/modules/newsfeed/incorrect_url.js index 565da18997..0866469862 100644 --- a/tests/configs/modules/newsfeed/incorrect_url.js +++ b/tests/configs/modules/newsfeed/incorrect_url.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/newsfeed/prohibited_words.js b/tests/configs/modules/newsfeed/prohibited_words.js index 143fcf903c..d4b0d74359 100644 --- a/tests/configs/modules/newsfeed/prohibited_words.js +++ b/tests/configs/modules/newsfeed/prohibited_words.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/positions.js b/tests/configs/modules/positions.js index e9e0d07a76..3013be2f9f 100644 --- a/tests/configs/modules/positions.js +++ b/tests/configs/modules/positions.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: // Using exotic content. This is why don't accept go to JSON configuration file (() => { diff --git a/tests/configs/modules/weather/currentweather_compliments.js b/tests/configs/modules/weather/currentweather_compliments.js index 73e5855453..603fafa173 100644 --- a/tests/configs/modules/weather/currentweather_compliments.js +++ b/tests/configs/modules/weather/currentweather_compliments.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "compliments", diff --git a/tests/configs/modules/weather/currentweather_default.js b/tests/configs/modules/weather/currentweather_default.js index d2ad0a6bf4..e5a9fdce4e 100644 --- a/tests/configs/modules/weather/currentweather_default.js +++ b/tests/configs/modules/weather/currentweather_default.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/weather/currentweather_options.js b/tests/configs/modules/weather/currentweather_options.js index 903d3df760..0ddb8b7cf2 100644 --- a/tests/configs/modules/weather/currentweather_options.js +++ b/tests/configs/modules/weather/currentweather_options.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], modules: [ { module: "weather", diff --git a/tests/configs/modules/weather/currentweather_units.js b/tests/configs/modules/weather/currentweather_units.js index 856acf2635..462b67f682 100644 --- a/tests/configs/modules/weather/currentweather_units.js +++ b/tests/configs/modules/weather/currentweather_units.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], units: "imperial", modules: [ diff --git a/tests/configs/modules/weather/forecastweather_absolute.js b/tests/configs/modules/weather/forecastweather_absolute.js index 4b3884fe3a..ff18bdf973 100644 --- a/tests/configs/modules/weather/forecastweather_absolute.js +++ b/tests/configs/modules/weather/forecastweather_absolute.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/weather/forecastweather_default.js b/tests/configs/modules/weather/forecastweather_default.js index 3192b4c9dc..a53ba1273b 100644 --- a/tests/configs/modules/weather/forecastweather_default.js +++ b/tests/configs/modules/weather/forecastweather_default.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/weather/forecastweather_options.js b/tests/configs/modules/weather/forecastweather_options.js index ec55dc6cd1..0e80198814 100644 --- a/tests/configs/modules/weather/forecastweather_options.js +++ b/tests/configs/modules/weather/forecastweather_options.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/weather/forecastweather_units.js b/tests/configs/modules/weather/forecastweather_units.js index b9ba11e79c..73bcde9727 100644 --- a/tests/configs/modules/weather/forecastweather_units.js +++ b/tests/configs/modules/weather/forecastweather_units.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], units: "imperial", modules: [ diff --git a/tests/configs/modules/weather/hourlyweather_default.js b/tests/configs/modules/weather/hourlyweather_default.js index ed6f66db39..191ceab1d2 100644 --- a/tests/configs/modules/weather/hourlyweather_default.js +++ b/tests/configs/modules/weather/hourlyweather_default.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/weather/hourlyweather_options.js b/tests/configs/modules/weather/hourlyweather_options.js index 5422075e6d..c11d23dbd3 100644 --- a/tests/configs/modules/weather/hourlyweather_options.js +++ b/tests/configs/modules/weather/hourlyweather_options.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js index 1448172f81..3dbbc41837 100644 --- a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js +++ b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js @@ -1,4 +1,6 @@ let config = { + address: "0.0.0.0", + ipWhitelist: [], timeFormat: 12, modules: [ diff --git a/tests/configs/without_modules.js b/tests/configs/without_modules.js index abe8fbc42e..988c338cbb 100644 --- a/tests/configs/without_modules.js +++ b/tests/configs/without_modules.js @@ -1,5 +1,6 @@ let config = { - ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.10.1"] + address: "0.0.0.0", + ipWhitelist: [] }; /*************** DO NOT EDIT THE LINE BELOW ***************/ From fff31068abcc12392e4fc4cb3f869cfe869d7c9b Mon Sep 17 00:00:00 2001 From: Veeck Date: Sun, 13 Oct 2024 15:22:02 +0200 Subject: [PATCH 127/418] Re-add eslint-plugin-import (#3586) eslint-plugin-import was missing since the switch to [v9](https://github.com/MagicMirrorOrg/MagicMirror/pull/3558). They finally [support](https://github.com/import-js/eslint-plugin-import/pull/2996) it so we can re-add it. --- CHANGELOG.md | 2 + eslint.config.mjs | 5 + package-lock.json | 1168 ++++++++++++++++++++++++++++++--------------- package.json | 17 +- 4 files changed, 789 insertions(+), 403 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd3057e76d..c31665ac36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ _This release is scheduled to be released on 2025-01-01._ ### Added +- [linter] re-added `eslint-plugin-import`now that it supports ESLint v9 + ### Removed - [tests] Removed node-pty and drivelist from rebuilded test (#3575) diff --git a/eslint.config.mjs b/eslint.config.mjs index 3338c1d786..9fac7b7fec 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,3 +1,4 @@ +import eslintPluginImport from "eslint-plugin-import"; import eslintPluginJest from "eslint-plugin-jest"; import eslintPluginJs from "@eslint/js"; import eslintPluginStylistic from "@stylistic/eslint-plugin"; @@ -5,6 +6,7 @@ import globals from "globals"; const config = [ eslintPluginJs.configs.recommended, + eslintPluginImport.flatConfigs.recommended, { files: ["**/*.js"], languageOptions: { @@ -53,6 +55,9 @@ const config = [ "@stylistic/spaced-comment": "off", eqeqeq: "error", "id-length": "off", + "import/order": "error", + "import/extensions": "error", + "import/newline-after-import": "error", "init-declarations": "off", "jest/consistent-test-it": "warn", "jest/no-done-callback": "warn", diff --git a/package-lock.json b/package-lock.json index d5d71855f3..985f396fbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,10 +13,9 @@ "ajv": "^8.17.1", "ansis": "^3.3.2", "console-stamp": "^3.1.2", - "electron": "^32.2.0", "envsub": "^4.1.0", - "eslint": "^9.11.1", - "express": "^4.21.0", + "eslint": "^9.12.0", + "express": "^4.21.1", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^8.0.0", @@ -31,21 +30,22 @@ "systeminformation": "^5.23.5" }, "devDependencies": { - "@eslint/js": "^9.11.1", - "@stylistic/eslint-plugin": "^2.8.0", - "cspell": "^8.14.4", + "@eslint/js": "^9.12.0", + "@stylistic/eslint-plugin": "^2.9.0", + "cspell": "^8.15.1", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.3.1", + "eslint-plugin-jsdoc": "^50.3.2", "eslint-plugin-package-json": "^0.15.3", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", - "playwright": "^1.47.2", + "playwright": "^1.48.0", "prettier": "^3.3.3", "sinon": "^19.0.2", - "stylelint": "^16.9.0", + "stylelint": "^16.10.0", "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.2" }, @@ -702,17 +702,17 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.14.4.tgz", - "integrity": "sha512-JHZOpCJzN6fPBapBOvoeMxZbr0ZA11ZAkwcqM4w0lKoacbi6TwK8GIYf66hHvwLmMeav75TNXWE6aPTvBLMMqA==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.15.1.tgz", + "integrity": "sha512-BimBlwdY4gD1cnx8nAaCPLY+yHpAgTuB25rQmpCLMSslQJBFkynRtOmtYQR+Mh4hX9nLaA3oPO4uVKOHVhQ00Q==", "dev": true, "license": "MIT", "dependencies": { "@cspell/dict-ada": "^4.0.2", "@cspell/dict-aws": "^4.0.4", - "@cspell/dict-bash": "^4.1.4", + "@cspell/dict-bash": "^4.1.5", "@cspell/dict-companies": "^3.1.4", - "@cspell/dict-cpp": "^5.1.16", + "@cspell/dict-cpp": "^5.1.19", "@cspell/dict-cryptocurrencies": "^5.0.0", "@cspell/dict-csharp": "^4.0.2", "@cspell/dict-css": "^4.0.13", @@ -731,10 +731,10 @@ "@cspell/dict-fullstack": "^3.2.0", "@cspell/dict-gaming-terms": "^1.0.5", "@cspell/dict-git": "^3.0.0", - "@cspell/dict-golang": "^6.0.12", + "@cspell/dict-golang": "^6.0.13", "@cspell/dict-google": "^1.0.1", "@cspell/dict-haskell": "^4.0.1", - "@cspell/dict-html": "^4.0.5", + "@cspell/dict-html": "^4.0.6", "@cspell/dict-html-symbol-entities": "^4.0.0", "@cspell/dict-java": "^5.0.7", "@cspell/dict-julia": "^1.0.1", @@ -745,20 +745,20 @@ "@cspell/dict-makefile": "^1.0.0", "@cspell/dict-monkeyc": "^1.0.6", "@cspell/dict-node": "^5.0.1", - "@cspell/dict-npm": "^5.1.4", + "@cspell/dict-npm": "^5.1.5", "@cspell/dict-php": "^4.0.10", - "@cspell/dict-powershell": "^5.0.8", + "@cspell/dict-powershell": "^5.0.10", "@cspell/dict-public-licenses": "^2.0.8", - "@cspell/dict-python": "^4.2.6", + "@cspell/dict-python": "^4.2.8", "@cspell/dict-r": "^2.0.1", - "@cspell/dict-ruby": "^5.0.3", - "@cspell/dict-rust": "^4.0.5", + "@cspell/dict-ruby": "^5.0.4", + "@cspell/dict-rust": "^4.0.6", "@cspell/dict-scala": "^5.0.3", - "@cspell/dict-software-terms": "^4.1.3", + "@cspell/dict-software-terms": "^4.1.7", "@cspell/dict-sql": "^2.1.5", "@cspell/dict-svelte": "^1.0.2", "@cspell/dict-swift": "^2.0.1", - "@cspell/dict-terraform": "^1.0.1", + "@cspell/dict-terraform": "^1.0.2", "@cspell/dict-typescript": "^3.1.6", "@cspell/dict-vue": "^3.0.0" }, @@ -767,22 +767,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.14.4.tgz", - "integrity": "sha512-gJ6tQbGCNLyHS2iIimMg77as5MMAFv3sxU7W6tjLlZp8htiNZS7fS976g24WbT/hscsTT9Dd0sNHkpo8K3nvVw==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.15.1.tgz", + "integrity": "sha512-mU4eWHYjGGdhmLd4oGz4kEry2udUl3thzz3clLiutijPrmNU/5sS5C6tiKBZCytWhhCkTwA5eDM3rr7cIt4DYQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.14.4" + "@cspell/cspell-types": "8.15.1" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.14.4.tgz", - "integrity": "sha512-CLLdouqfrQ4rqdQdPu0Oo+HHCU/oLYoEsK1nNPb28cZTFxnn0cuSPKB6AMPBJmMwdfJ6fMD0BCKNbEe1UNLHcw==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.15.1.tgz", + "integrity": "sha512-euErNW69K6+rCirGtORbgapcNtvlObTlO7SHftRRjGbvMh1F5J1rEc+KwW3qhM5H73NSwFrQwR5KzWrUrGimog==", "dev": true, "license": "MIT", "engines": { @@ -790,9 +790,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.14.4.tgz", - "integrity": "sha512-s3uZyymJ04yn8+zlTp7Pt1WRSlAel6XVo+iZRxls3LSvIP819KK64DoyjCD2Uon0Vg9P/K7aAPt8GcxDcnJtgA==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.15.1.tgz", + "integrity": "sha512-9GVRSZKLc7P4S1aOzBiyXbtVMu3yeDHpp/sAeKd7Z869T2ddvMrmQoOTRBmKW90PNP2j4aQkPebPJe85GnOf+A==", "dev": true, "license": "MIT", "dependencies": { @@ -803,9 +803,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.14.4.tgz", - "integrity": "sha512-i3UG+ep63akNsDXZrtGgICNF3MLBHtvKe/VOIH6+L+NYaAaVHqqQvOY9MdUwt1HXh8ElzfwfoRp36wc5aAvt6g==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.15.1.tgz", + "integrity": "sha512-SFnJNw0BOagdx29soC8tiDNObENLU2FFhfT7JHbILHbJ5IdtsRLAxYIf99rDb1zLB3pdA/optqPwPUdAgMIQLg==", "dev": true, "license": "MIT", "engines": { @@ -813,9 +813,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.14.4.tgz", - "integrity": "sha512-VXwikqdHgjOVperVVCn2DOe8W3rPIswwZtMHfRYnagpzZo/TOntIjkXPJSfTtl/cFyx5DnCBsDH8ytKGlMeHkw==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.15.1.tgz", + "integrity": "sha512-6QY0147RmiXIpTMkwI7a6dx+/CtPserPxxsK2p0DFf4bTHOGExx3dlPg7eGL8UFO0/C/nrXPAMy5kZEstPclXA==", "dev": true, "license": "MIT", "engines": { @@ -823,114 +823,114 @@ } }, "node_modules/@cspell/dict-ada": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.2.tgz", - "integrity": "sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.5.tgz", + "integrity": "sha512-6/RtZ/a+lhFVmrx/B7bfP7rzC4yjEYe8o74EybXcvu4Oue6J4Ey2WSYj96iuodloj1LWrkNCQyX5h4Pmcj0Iag==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-aws": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.4.tgz", - "integrity": "sha512-6AWI/Kkf+RcX/J81VX8+GKLeTgHWEr/OMhGk3dHQzWK66RaqDJCGDqi7494ghZKcBB7dGa3U5jcKw2FZHL/u3w==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.7.tgz", + "integrity": "sha512-PoaPpa2NXtSkhGIMIKhsJUXB6UbtTt6Ao3x9JdU9kn7fRZkwD4RjHDGqulucIOz7KeEX/dNRafap6oK9xHe4RA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-bash": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.4.tgz", - "integrity": "sha512-W/AHoQcJYn3Vn/tUiXX2+6D/bhfzdDshwcbQWv9TdiNlXP9P6UJjDKWbxyA5ogJCsR2D0X9Kx11oV8E58siGKQ==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.8.tgz", + "integrity": "sha512-I2CM2pTNthQwW069lKcrVxchJGMVQBzru2ygsHCwgidXRnJL/NTjAPOFTxN58Jc1bf7THWghfEDyKX/oyfc0yg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-companies": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.4.tgz", - "integrity": "sha512-y9e0amzEK36EiiKx3VAA+SHQJPpf2Qv5cCt5eTUSggpTkiFkCh6gRKQ97rVlrKh5GJrqinDwYIJtTsxuh2vy2Q==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.7.tgz", + "integrity": "sha512-ncVs/efuAkP1/tLDhWbXukBjgZ5xOUfe03neHMWsE8zvXXc5+Lw6TX5jaJXZLOoES/f4j4AhRE20jsPCF5pm+A==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "5.1.16", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.16.tgz", - "integrity": "sha512-32fU5RkuOM55IRcxjByiSoKbjr+C4danDfYjHaQNRWdvjzJzci3fLDGA2wTXiclkgDODxGiV8LCTUwCz+3TNWA==", + "version": "5.1.22", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.22.tgz", + "integrity": "sha512-g1/8P5/Q+xnIc8Js4UtBg3XOhcFrFlFbG3UWVtyEx49YTf0r9eyDtDt1qMMDBZT91pyCwLcAEbwS+4i5PIfNZw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cryptocurrencies": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.0.tgz", - "integrity": "sha512-Z4ARIw5+bvmShL+4ZrhDzGhnc9znaAGHOEMaB/GURdS/jdoreEDY34wdN0NtdLHDO5KO7GduZnZyqGdRoiSmYA==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.3.tgz", + "integrity": "sha512-bl5q+Mk+T3xOZ12+FG37dB30GDxStza49Rmoax95n37MTLksk9wBo1ICOlPJ6PnDUSyeuv4SIVKgRKMKkJJglA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-csharp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz", - "integrity": "sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.5.tgz", + "integrity": "sha512-c/sFnNgtRwRJxtC3JHKkyOm+U3/sUrltFeNwml9VsxKBHVmvlg4tk4ar58PdpW9/zTlGUkWi2i85//DN1EsUCA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-css": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.13.tgz", - "integrity": "sha512-WfOQkqlAJTo8eIQeztaH0N0P+iF5hsJVKFuhy4jmARPISy8Efcv8QXk2/IVbmjJH0/ZV7dKRdnY5JFVXuVz37g==", + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.16.tgz", + "integrity": "sha512-70qu7L9z/JR6QLyJPk38fNTKitlIHnfunx0wjpWQUQ8/jGADIhMCrz6hInBjqPNdtGpYm8d1dNFyF8taEkOgrQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-dart": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.2.1.tgz", - "integrity": "sha512-yriKm7QkoPx3JPSSOcw6iX9gOb2N50bOo/wqWviqPYbhpMRh9Xiv6dkUy3+ot+21GuShZazO8X6U5+Vw67XEwg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.2.4.tgz", + "integrity": "sha512-of/cVuUIZZK/+iqefGln8G3bVpfyN6ZtH+LyLkHMoR5tEj+2vtilGNk9ngwyR8L4lEqbKuzSkOxgfVjsXf5PsQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-data-science": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.1.tgz", - "integrity": "sha512-xeutkzK0eBe+LFXOFU2kJeAYO6IuFUc1g7iRLr7HeCmlC4rsdGclwGHh61KmttL3+YHQytYStxaRBdGAXWC8Lw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.5.tgz", + "integrity": "sha512-nNSILXmhSJox9/QoXICPQgm8q5PbiSQP4afpbkBqPi/u/b3K9MbNH5HvOOa6230gxcGdbZ9Argl2hY/U8siBlg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-django": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.0.tgz", - "integrity": "sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.3.tgz", + "integrity": "sha512-yBspeL3roJlO0a1vKKNaWABURuHdHZ9b1L8d3AukX0AsBy9snSggc8xCavPmSzNfeMDXbH+1lgQiYBd3IW03fg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-docker": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.7.tgz", - "integrity": "sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.10.tgz", + "integrity": "sha512-vWybMfsG/8jhN6kmPoilMon36GB3+Ef+m/mgYUfY8tJN23K/x4KD1rU1OOiNWzDqePhu3MMWVKO5W5x6VI6Gbw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-dotnet": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.5.tgz", - "integrity": "sha512-gjg0L97ee146wX47dnA698cHm85e7EOpf9mVrJD8DmEaqoo/k1oPy2g7c7LgKxK9XnqwoXxhLNnngPrwXOoEtQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.8.tgz", + "integrity": "sha512-MD8CmMgMEdJAIPl2Py3iqrx3B708MbCIXAuOeZ0Mzzb8YmLmiisY7QEYSZPg08D7xuwARycP0Ki+bb0GAkFSqg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-elixir": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.3.tgz", - "integrity": "sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.6.tgz", + "integrity": "sha512-TfqSTxMHZ2jhiqnXlVKM0bUADtCvwKQv2XZL/DI0rx3doG8mEMS8SGPOmiyyGkHpR/pGOq18AFH3BEm4lViHIw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.23", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.23.tgz", - "integrity": "sha512-l0SoEQBsi3zDSl3OuL4/apBkxjuj4hLIg/oy6+gZ7LWh03rKdF6VNtSZNXWAmMY+pmb1cGA3ouleTiJIglbsIg==", + "version": "4.3.26", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.26.tgz", + "integrity": "sha512-hDbHYJsi3UgU1J++B0WLiYhWQdsmve3CH53FIaMRAdhrWOHcuw7h1dYkQXHFEP5lOjaq53KUHp/oh5su6VkIZg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.4.tgz", - "integrity": "sha512-lvOiRjV/FG4pAGZL3PN2GCVHSTCE92cwhfLGGkOsQtxSmef6WCHfHwp9auafkBlX0yFQSKDfq6/TlpQbjbJBtQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.7.tgz", + "integrity": "sha512-qNFo3G4wyabcwnM+hDrMYKN9vNVg/k9QkhqSlSst6pULjdvPyPs1mqz1689xO/v9t8e6sR4IKc3CgUXDMTYOpA==", "dev": true, "license": "CC BY-SA 4.0" }, @@ -942,271 +942,271 @@ "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.4.tgz", - "integrity": "sha512-IBi8eIVdykoGgIv5wQhOURi5lmCNJq0we6DvqKoPQJHthXbgsuO1qrHSiUVydMiQl/XvcnUWTMeAlVUlUClnVg==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.7.tgz", + "integrity": "sha512-/DN0Ujp9/EXvpTcgih9JmBaE8n+G0wtsspyNdvHT5luRfpfol1xm/CIQb6xloCXCiLkWX+EMPeLSiVIZq+24dA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-flutter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.0.0.tgz", - "integrity": "sha512-W7k1VIc4KeV8BjEBxpA3cqpzbDWjfb7oXkEb0LecBCBp5Z7kcfnjT1YVotTx/U9PGyAOBhDaEdgZACVGNQhayw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.0.3.tgz", + "integrity": "sha512-52C9aUEU22ptpgYh6gQyIdA4MP6NPwzbEqndfgPh3Sra191/kgs7CVqXiO1qbtZa9gnYHUoVApkoxRE7mrXHfg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-fonts": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.0.tgz", - "integrity": "sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.3.tgz", + "integrity": "sha512-sPd17kV5qgYXLteuHFPn5mbp/oCHKgitNfsZLFC3W2fWEgZlhg4hK+UGig3KzrYhhvQ8wBnmZrAQm0TFKCKzsA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-fsharp": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.0.1.tgz", - "integrity": "sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.0.4.tgz", + "integrity": "sha512-G5wk0o1qyHUNi9nVgdE1h5wl5ylq7pcBjX8vhjHcO4XBq20D5eMoXjwqMo/+szKAqzJ+WV3BgAL50akLKrT9Rw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-fullstack": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.0.tgz", - "integrity": "sha512-sIGQwU6G3rLTo+nx0GKyirR5dQSFeTIzFTOrURw51ISf+jKG9a3OmvsVtc2OANfvEAOLOC9Wfd8WYhmsO8KRDQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.3.tgz", + "integrity": "sha512-62PbndIyQPH11mAv0PyiyT0vbwD0AXEocPpHlCHzfb5v9SspzCCbzQ/LIBiFmyRa+q5LMW35CnSVu6OXdT+LKg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-gaming-terms": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.5.tgz", - "integrity": "sha512-C3riccZDD3d9caJQQs1+MPfrUrQ+0KHdlj9iUR1QD92FgTOF6UxoBpvHUUZ9YSezslcmpFQK4xQQ5FUGS7uWfw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.8.tgz", + "integrity": "sha512-7OL0zTl93WFWhhtpXFrtm9uZXItC3ncAs8d0iQDMMFVNU1rBr6raBNxJskxE5wx2Ant12fgI66ZGVagXfN+yfA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-git": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.0.tgz", - "integrity": "sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.3.tgz", + "integrity": "sha512-LSxB+psZ0qoj83GkyjeEH/ZViyVsGEF/A6BAo8Nqc0w0HjD2qX/QR4sfA6JHUgQ3Yi/ccxdK7xNIo67L2ScW5A==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-golang": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.12.tgz", - "integrity": "sha512-LEPeoqd+4O+vceHF73S7D7+LYfrAjOvp4Dqzh4MT30ruzlQ77yHRSuYOJtrFN1GK5ntAt/ILSVOKg9sgsz1Llg==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.16.tgz", + "integrity": "sha512-hZOBlgcguv2Hdc93n2zjdAQm1j3grsN9T9WhPnQ1wh2vUDoCLEujg+6gWhjcLb8ECOcwZTWgNyQLWeOxEsAj/w==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-google": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.1.tgz", - "integrity": "sha512-dQr4M3n95uOhtloNSgB9tYYGXGGEGEykkFyRtfcp5pFuEecYUa0BSgtlGKx9RXVtJtKgR+yFT/a5uQSlt8WjqQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.4.tgz", + "integrity": "sha512-JThUT9eiguCja1mHHLwYESgxkhk17Gv7P3b1S7ZJzXw86QyVHPrbpVoMpozHk0C9o+Ym764B7gZGKmw9uMGduQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-haskell": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.1.tgz", - "integrity": "sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.4.tgz", + "integrity": "sha512-EwQsedEEnND/vY6tqRfg9y7tsnZdxNqOxLXSXTsFA6JRhUlr8Qs88iUUAfsUzWc4nNmmzQH2UbtT25ooG9x4nA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-html": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.6.tgz", - "integrity": "sha512-cLWHfuOhE4wqwC12up6Doxo2u1xxVhX1A8zriR4CUD+osFQzUIcBK1ykNXppga+rt1WyypaJdTU2eV6OpzYrgQ==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.9.tgz", + "integrity": "sha512-BNp7w3m910K4qIVyOBOZxHuFNbVojUY6ES8Y8r7YjYgJkm2lCuQoVwwhPjurnomJ7BPmZTb+3LLJ58XIkgF7JQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-html-symbol-entities": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.0.tgz", - "integrity": "sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.3.tgz", + "integrity": "sha512-aABXX7dMLNFdSE8aY844X4+hvfK7977sOWgZXo4MTGAmOzR8524fjbJPswIBK7GaD3+SgFZ2yP2o0CFvXDGF+A==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-java": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.7.tgz", - "integrity": "sha512-ejQ9iJXYIq7R09BScU2y5OUGrSqwcD+J5mHFOKbduuQ5s/Eh/duz45KOzykeMLI6KHPVxhBKpUPBWIsfewECpQ==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.10.tgz", + "integrity": "sha512-pVNcOnmoGiNL8GSVq4WbX/Vs2FGS0Nej+1aEeGuUY9CU14X8yAVCG+oih5ZoLt1jaR8YfR8byUF8wdp4qG4XIw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-julia": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.0.1.tgz", - "integrity": "sha512-4JsCLCRhhLMLiaHpmR7zHFjj1qOauzDI5ZzCNQS31TUMfsOo26jAKDfo0jljFAKgw5M2fEG7sKr8IlPpQAYrmQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.0.4.tgz", + "integrity": "sha512-bFVgNX35MD3kZRbXbJVzdnN7OuEqmQXGpdOi9jzB40TSgBTlJWA4nxeAKV4CPCZxNRUGnLH0p05T/AD7Aom9/w==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-k8s": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.6.tgz", - "integrity": "sha512-srhVDtwrd799uxMpsPOQqeDJY+gEocgZpoK06EFrb4GRYGhv7lXo9Fb+xQMyQytzOW9dw4DNOEck++nacDuymg==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.9.tgz", + "integrity": "sha512-Q7GELSQIzo+BERl2ya/nBEnZeQC+zJP19SN1pI6gqDYraM51uYJacbbcWLYYO2Y+5joDjNt/sd/lJtLaQwoSlA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-latex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.0.tgz", - "integrity": "sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.3.tgz", + "integrity": "sha512-2KXBt9fSpymYHxHfvhUpjUFyzrmN4c4P8mwIzweLyvqntBT3k0YGZJSriOdjfUjwSygrfEwiuPI1EMrvgrOMJw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-lorem-ipsum": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.0.tgz", - "integrity": "sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.3.tgz", + "integrity": "sha512-WFpDi/PDYHXft6p0eCXuYnn7mzMEQLVeqpO+wHSUd+kz5ADusZ4cpslAA4wUZJstF1/1kMCQCZM6HLZic9bT8A==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-lua": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.3.tgz", - "integrity": "sha512-lDHKjsrrbqPaea13+G9s0rtXjMO06gPXPYRjRYawbNmo4E/e3XFfVzeci3OQDQNDmf2cPOwt9Ef5lu2lDmwfJg==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.6.tgz", + "integrity": "sha512-Jwvh1jmAd9b+SP9e1GkS2ACbqKKRo9E1f9GdjF/ijmooZuHU0hPyqvnhZzUAxO1egbnNjxS/J2T6iUtjAUK2KQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-makefile": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.0.tgz", - "integrity": "sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.3.tgz", + "integrity": "sha512-R3U0DSpvTs6qdqfyBATnePj9Q/pypkje0Nj26mQJ8TOBQutCRAJbr2ZFAeDjgRx5EAJU/+8txiyVF97fbVRViw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-monkeyc": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.6.tgz", - "integrity": "sha512-oO8ZDu/FtZ55aq9Mb67HtaCnsLn59xvhO/t2mLLTHAp667hJFxpp7bCtr2zOrR1NELzFXmKln/2lw/PvxMSvrA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.9.tgz", + "integrity": "sha512-Jvf6g5xlB4+za3ThvenYKREXTEgzx5gMUSzrAxIiPleVG4hmRb/GBSoSjtkGaibN3XxGx5x809gSTYCA/IHCpA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-node": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.1.tgz", - "integrity": "sha512-lax/jGz9h3Dv83v8LHa5G0bf6wm8YVRMzbjJPG/9rp7cAGPtdrga+XANFq+B7bY5+jiSA3zvj10LUFCFjnnCCg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.4.tgz", + "integrity": "sha512-Hz5hiuOvZTd7Cp1IBqUZ7/ChwJeQpD5BJuwCaDn4mPNq4iMcQ1iWBYMThvNVqCEDgKv63X52nT8RAWacss98qg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.5.tgz", - "integrity": "sha512-oAOGWuJYU3DlO+cAsStKMWN8YEkBue25cRC9EwdiL5Z84nchU20UIoYrLfIQejMlZca+1GyrNeyxRAgn4KiivA==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.8.tgz", + "integrity": "sha512-AJELYXeB4fQdIoNfmuaQxB1Hli3cX6XPsQCjfBxlu0QYXhrjB/IrCLLQAjWIywDqJiWyGUFTz4DqaANm8C/r9Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-php": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.10.tgz", - "integrity": "sha512-NfTZdp6kcZDF1PvgQ6cY0zE4FUO5rSwNmBH/iwCBuaLfJAFQ97rgjxo+D2bic4CFwNjyHutnHPtjJBRANO5XQw==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.13.tgz", + "integrity": "sha512-P6sREMZkhElzz/HhXAjahnICYIqB/HSGp1EhZh+Y6IhvC15AzgtDP8B8VYCIsQof6rPF1SQrFwunxOv8H1e2eg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-powershell": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.9.tgz", - "integrity": "sha512-Vi0h0rlxS39tgTyUtxI6L3BPHH7MLPkLWCYkNfb/buQuNJYNFdHiF4bqoqVdJ/7ZrfIfNg4i6rzocnwGRn2ruw==", + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.13.tgz", + "integrity": "sha512-0qdj0XZIPmb77nRTynKidRJKTU0Fl+10jyLbAhFTuBWKMypVY06EaYFnwhsgsws/7nNX8MTEQuewbl9bWFAbsg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-public-licenses": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.8.tgz", - "integrity": "sha512-Sup+tFS7cDV0fgpoKtUqEZ6+fA/H+XUgBiqQ/Fbs6vUE3WCjJHOIVsP+udHuyMH7iBfJ4UFYOYeORcY4EaKdMg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.11.tgz", + "integrity": "sha512-rR5KjRUSnVKdfs5G+gJ4oIvQvm8+NJ6cHWY2N+GE69/FSGWDOPHxulCzeGnQU/c6WWZMSimG9o49i9r//lUQyA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.6.tgz", - "integrity": "sha512-Hkz399qDGEbfXi9GYa2hDl7GahglI86JmS2F1KP8sfjLXofUgtnknyC5NWc86nzHcP38pZiPqPbTigyDYw5y8A==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.11.tgz", + "integrity": "sha512-bshNZqP5FYRO0CtZ9GgtVjHidrSuRRF537MU/sPew8oaqWPg066F9KQfPllbRi9AzFqqeS2l7/ACYUrFMe21gw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-data-science": "^2.0.1" + "@cspell/dict-data-science": "^2.0.5" } }, "node_modules/@cspell/dict-r": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.1.tgz", - "integrity": "sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.4.tgz", + "integrity": "sha512-cBpRsE/U0d9BRhiNRMLMH1PpWgw+N+1A2jumgt1if9nBGmQw4MUpg2u9I0xlFVhstTIdzXiLXMxP45cABuiUeQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-ruby": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.3.tgz", - "integrity": "sha512-V1xzv9hN6u8r6SM4CkYdsxs4ov8gjXXo0Twfx5kWhLXbEVxTXDMt7ohLTqpy2XlF5mutixZdbHMeFiAww8v+Ug==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.7.tgz", + "integrity": "sha512-4/d0hcoPzi5Alk0FmcyqlzFW9lQnZh9j07MJzPcyVO62nYJJAGKaPZL2o4qHeCS/od/ctJC5AHRdoUm0ktsw6Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-rust": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.5.tgz", - "integrity": "sha512-DIvlPRDemjKQy8rCqftAgGNZxY5Bg+Ps7qAIJjxkSjmMETyDgl0KTVuaJPt7EK4jJt6uCZ4ILy96npsHDPwoXA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.9.tgz", + "integrity": "sha512-Dhr6TIZsMV92xcikKIWei6p/qswS4M+gTkivpWwz4/1oaVk2nRrxJmCdRoVkJlZkkAc17rjxrS12mpnJZI0iWw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-scala": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.3.tgz", - "integrity": "sha512-4yGb4AInT99rqprxVNT9TYb1YSpq58Owzq7zi3ZS5T0u899Y4VsxsBiOgHnQ/4W+ygi+sp+oqef8w8nABR2lkg==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.6.tgz", + "integrity": "sha512-tl0YWAfjUVb4LyyE4JIMVE8DlLzb1ecHRmIWc4eT6nkyDqQgHKzdHsnusxFEFMVLIQomgSg0Zz6hJ5S1E4W4ww==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.4.tgz", - "integrity": "sha512-AHS25sYEzWze/aFglp9ODKSu+phjkuGx+OLwIcmOnvyn8axtSq5GCn9UqS4XG1/Qn0UG2Lgb4i5PJbZ0QNPNXQ==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.10.tgz", + "integrity": "sha512-+9PuQ9MHQhlET6Hv1mGcWDh6Rb+StzjBMrjfksDeBHBIVdT66u9uCkaZapIzfgktflY4m9oK7+dEynr+BAxvtQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-sql": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.5.tgz", - "integrity": "sha512-FmxanytHXss7GAWAXmgaxl3icTCW7YxlimyOSPNfm+njqeUDjw3kEv4mFNDDObBJv8Ec5AWCbUDkWIpkE3IpKg==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.8.tgz", + "integrity": "sha512-dJRE4JV1qmXTbbGm6WIcg1knmR6K5RXnQxF4XHs5HA3LAjc/zf77F95i5LC+guOGppVF6Hdl66S2UyxT+SAF3A==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-svelte": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.2.tgz", - "integrity": "sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.5.tgz", + "integrity": "sha512-sseHlcXOqWE4Ner9sg8KsjxwSJ2yssoJNqFHR9liWVbDV+m7kBiUtn2EB690TihzVsEmDr/0Yxrbb5Bniz70mA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-swift": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.1.tgz", - "integrity": "sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.4.tgz", + "integrity": "sha512-CsFF0IFAbRtYNg0yZcdaYbADF5F3DsM8C4wHnZefQy8YcHP/qjAF/GdGfBFBLx+XSthYuBlo2b2XQVdz3cJZBw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-terraform": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.1.tgz", - "integrity": "sha512-29lmUUnZgPh+ieZ5hunick8hzNIpNRtiJh9vAusNskPCrig3RTW6u7F+GG1a8uyslbzSw+Irjf40PTOan1OJJA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.5.tgz", + "integrity": "sha512-qH3epPB2d6d5w1l4hR2OsnN8qDQ4P0z6oDB7+YiNH+BoECXv4Z38MIV1H8cxIzD2wkzkt2JTcFYaVW72MDZAlg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-typescript": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.6.tgz", - "integrity": "sha512-1beC6O4P/j23VuxX+i0+F7XqPVc3hhiAzGJHEKqnWf5cWAXQtg0xz3xQJ5MvYx2a7iLaSa+lu7+05vG9UHyu9Q==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.9.tgz", + "integrity": "sha512-ZtO1/cVWvvR477ftTl2TFR09+IIzXG1rcin8CGYA0FO5WhyDAbn8v3A85QikS158BhTVUoq09lPYuSF9HBzqvw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-vue": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.0.tgz", - "integrity": "sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.3.tgz", + "integrity": "sha512-akmYbrgAGumqk1xXALtDJcEcOMYBYMnkjpmGzH13Ozhq1mkPF4VgllFQlm1xYde+BUKNnzMgPEzxrL2qZllgYA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.14.4.tgz", - "integrity": "sha512-GjKsBJvPXp4dYRqsMn7n1zpnKbnpfJnlKLOVeoFBh8fi4n06G50xYr+G25CWX1WT3WFaALAavvVICEUPrVsuqg==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.15.1.tgz", + "integrity": "sha512-Zc7tAn1EBFgPcpws0zoZrMyi0likUb3Kpnpq4FGmssmf4PnhSaDF2suqLlcCTPxCML87lF26UT6qUK01G9gIPA==", "dev": true, "license": "MIT", "dependencies": { @@ -1217,9 +1217,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.14.4.tgz", - "integrity": "sha512-qd68dD7xTA4Mnf/wjIKYz2SkiTBshIM+yszOUtLa06YJm0aocoNQ25FHXyYEQYm9NQXCYnRWWA02sFMGs8Sv/w==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.15.1.tgz", + "integrity": "sha512-SgwTDmy5Omc67ThA89t1+kNZcbwGr43ck0Il+tqSoNOBHbs+S5YftUgfinLFIN2pdRm4COPmAnEN2SEAsMh0UA==", "dev": true, "license": "MIT", "engines": { @@ -1227,9 +1227,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.14.4.tgz", - "integrity": "sha512-Uyfck64TfVU24wAP3BLGQ5EsAfzIZiLfN90NhttpEM7GlOBmbGrEJd4hNOwfpYsE/TT80eGWQVPRTLr5SDbXFA==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.15.1.tgz", + "integrity": "sha512-QmtDb0TBdLBlDqOCrOtqhg9e7k4T4t8akx+1LgNI/jGqj/mQVyYtHCHWVHYNxh7S7DumrlmmsJo62NzIZLqtCQ==", "dev": true, "license": "MIT", "engines": { @@ -1237,9 +1237,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.14.4.tgz", - "integrity": "sha512-htHhNF8WrM/NfaLSWuTYw0NqVgFRVHYSyHlRT3i/Yv5xvErld8Gw7C6ldm+0TLjoGlUe6X1VV72JSir7+yLp/Q==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.15.1.tgz", + "integrity": "sha512-LsLoeLRTrdQY1iLsnOxSta/+YvnT3Jm/Ofohhh6XBSegMl2CoJjzdY8wbfsc3YgdB6SHJ1PSZecftXRhMNIEeg==", "dev": true, "license": "MIT", "engines": { @@ -1553,9 +1553,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz", - "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1582,6 +1582,28 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.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", @@ -1596,9 +1618,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -2117,6 +2139,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -2130,6 +2153,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -2139,6 +2163,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -2383,6 +2408,13 @@ "debug": "^4.3.1" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", @@ -2472,15 +2504,15 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.8.0.tgz", - "integrity": "sha512-Ufvk7hP+bf+pD35R/QfunF793XlSRIC7USr3/EdgduK9j13i2JjmsM0LUz3/foS+jDYp2fzyWZA9N44CPur0Ow==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.9.0.tgz", + "integrity": "sha512-OrDyFAYjBT61122MIY1a3SfEgy3YCMgt2vL4eoPmvTwDBwyQhAXurxNQznlRD/jESNfYWfID8Ej+31LljvF7Xg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.4.0", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", + "@typescript-eslint/utils": "^8.8.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -2650,6 +2682,13 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -2721,14 +2760,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", - "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz", + "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0" + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2739,9 +2778,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", - "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz", + "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==", "dev": true, "license": "MIT", "engines": { @@ -2753,14 +2792,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", - "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz", + "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2782,16 +2821,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz", + "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.8.1", + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/typescript-estree": "8.8.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2805,13 +2844,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", - "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz", + "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/types": "8.8.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3037,6 +3076,27 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-timsort": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", @@ -3054,6 +3114,65 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", @@ -4037,9 +4156,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -4151,31 +4270,30 @@ } }, "node_modules/cspell": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.14.4.tgz", - "integrity": "sha512-R5Awb3i/RKaVVcZzFt8dkN3M6VnifIEDYBcbzbmYjZ/Eq+ASF+QTmI0E9WPhMEcFM1nd7YOyXnETo560yRdoKw==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.15.1.tgz", + "integrity": "sha512-bF2RNErisDg3pfm1tOrq/74g9n09wprg2Im+TNwDSmivusE9LxFoyhEPOiGBVg25/iMSu/BPx5nDNL1WDGwZqA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.14.4", - "@cspell/cspell-pipe": "8.14.4", - "@cspell/cspell-types": "8.14.4", - "@cspell/dynamic-import": "8.14.4", - "@cspell/url": "8.14.4", + "@cspell/cspell-json-reporter": "8.15.1", + "@cspell/cspell-pipe": "8.15.1", + "@cspell/cspell-types": "8.15.1", + "@cspell/dynamic-import": "8.15.1", + "@cspell/url": "8.15.1", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^12.1.0", - "cspell-dictionary": "8.14.4", - "cspell-gitignore": "8.14.4", - "cspell-glob": "8.14.4", - "cspell-io": "8.14.4", - "cspell-lib": "8.14.4", - "fast-glob": "^3.3.2", + "cspell-dictionary": "8.15.1", + "cspell-gitignore": "8.15.1", + "cspell-glob": "8.15.1", + "cspell-io": "8.15.1", + "cspell-lib": "8.15.1", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", "semver": "^7.6.3", - "strip-ansi": "^7.1.0" + "tinyglobby": "^0.2.9" }, "bin": { "cspell": "bin.mjs", @@ -4189,13 +4307,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.14.4.tgz", - "integrity": "sha512-cnUeJfniTiebqCaQmIUnbSrPrTH7xzKRQjJDHAEV0WYnOG2MhRXI13OzytdFdhkVBdStmgTzTCJKE7x+kmU2NA==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.15.1.tgz", + "integrity": "sha512-hDkaRRsqJbvAKA5ZoUBobozAA8iTcNzgo3mHK+FCVbGGaA2903q8mG3yFBviFioXUHsBBlN7Em/3JQDnasO3qQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.14.4", + "@cspell/cspell-types": "8.15.1", "comment-json": "^4.2.5", "yaml": "^2.5.1" }, @@ -4204,15 +4322,15 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.14.4.tgz", - "integrity": "sha512-pZvQHxpAW5fZAnt3ZKKy3s7M+3CX2t8tCS3uJrpEHIynlCawpG0fPF78rVE5o+g0dON36Lguc/BUuSN4IWKLmQ==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.15.1.tgz", + "integrity": "sha512-N0Wz/hQlRDVuAH2OqlU9Uad++XccwsZuTmdV82HUHGCjmtHUxCiHD51+d2tsLX8ZXur0/eL988RIMPFePYIOww==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.14.4", - "@cspell/cspell-types": "8.14.4", - "cspell-trie-lib": "8.14.4", + "@cspell/cspell-pipe": "8.15.1", + "@cspell/cspell-types": "8.15.1", + "cspell-trie-lib": "8.15.1", "fast-equals": "^5.0.1" }, "engines": { @@ -4220,15 +4338,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.14.4.tgz", - "integrity": "sha512-RwfQEW5hD7CpYwS7m3b0ONG0nTLKP6bL2tvMdl7qtaYkL7ztGdsBTtLD1pmwqUsCbiN5RuaOxhYOYeRcpFRIkQ==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.15.1.tgz", + "integrity": "sha512-RBJnOIXYKk9ZpYx/y8Hcl/jIhdKposid5Em/GUpj65vXPa0N9arpVXCiIObAtu3645NeHd+Z6RrhNLdKhyZprQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.14.4", - "cspell-glob": "8.14.4", - "cspell-io": "8.14.4", + "@cspell/url": "8.15.1", + "cspell-glob": "8.15.1", + "cspell-io": "8.15.1", "find-up-simple": "^1.0.0" }, "bin": { @@ -4239,13 +4357,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.14.4.tgz", - "integrity": "sha512-C/xTS5nujMRMuguibq92qMVP767mtxrur7DcVolCvpzcivm1RB5NtIN0OctQxTyMbnmKeQv1t4epRKQ9A8vWRg==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.15.1.tgz", + "integrity": "sha512-INKBWUVGg595+F8V8kEEP07OPqQGJs+qp6Q587UwP+yvxMZ4PYA6PudvZEwa5capVxIbSYDNafqtcc2F3MaPbw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.14.4", + "@cspell/url": "8.15.1", "micromatch": "^4.0.8" }, "engines": { @@ -4253,14 +4371,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.14.4.tgz", - "integrity": "sha512-yaSKAAJDiamsw3FChbw4HXb2RvTQrDsLelh1+T4MavarOIcAxXrqAJ8ysqm++g+S/ooJz2YO8YWIyzJKxcMf8g==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.15.1.tgz", + "integrity": "sha512-4sZ3uh3rgrcoBMwXCmq8rDazVYKR2AUAm36t/EU5uiD+Ju1FfoEaxw1DTKtVDGMNNad6JmNmqxOoFdLAqL1sQA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.14.4", - "@cspell/cspell-types": "8.14.4" + "@cspell/cspell-pipe": "8.15.1", + "@cspell/cspell-types": "8.15.1" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4270,42 +4388,42 @@ } }, "node_modules/cspell-io": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.14.4.tgz", - "integrity": "sha512-o6OTWRyx/Az+PFhr1B0wMAwqG070hFC9g73Fkxd8+rHX0rfRS69QZH7LgSmZytqbZIMxCTDGdsLl33MFGWCbZQ==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.15.1.tgz", + "integrity": "sha512-PvzOm4utZuhb97hqlWS1F+ZHbMVbFsUUC0HQcubquLkjV8s/yryuBlgP52gOxNGTZjyEULWk9MYUldRZK3oB8g==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.14.4", - "@cspell/url": "8.14.4" + "@cspell/cspell-service-bus": "8.15.1", + "@cspell/url": "8.15.1" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.14.4.tgz", - "integrity": "sha512-qdkUkKtm+nmgpA4jQbmQTuepDfjHBDWvs3zDuEwVIVFq/h8gnXrRr75gJ3RYdTy+vOOqHPoLLqgxyqkUUrUGXA==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.15.1.tgz", + "integrity": "sha512-qwfeok4DKYhNjlXOLDZ1hagKAKIXByfMSizTlwIMmmZVJ+8SL61P+PJG0ggwLteq9fEK+oLwaf/N2bVRH6M28Q==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.14.4", - "@cspell/cspell-pipe": "8.14.4", - "@cspell/cspell-resolver": "8.14.4", - "@cspell/cspell-types": "8.14.4", - "@cspell/dynamic-import": "8.14.4", - "@cspell/filetypes": "8.14.4", - "@cspell/strong-weak-map": "8.14.4", - "@cspell/url": "8.14.4", + "@cspell/cspell-bundled-dicts": "8.15.1", + "@cspell/cspell-pipe": "8.15.1", + "@cspell/cspell-resolver": "8.15.1", + "@cspell/cspell-types": "8.15.1", + "@cspell/dynamic-import": "8.15.1", + "@cspell/filetypes": "8.15.1", + "@cspell/strong-weak-map": "8.15.1", + "@cspell/url": "8.15.1", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.14.4", - "cspell-dictionary": "8.14.4", - "cspell-glob": "8.14.4", - "cspell-grammar": "8.14.4", - "cspell-io": "8.14.4", - "cspell-trie-lib": "8.14.4", + "cspell-config-lib": "8.15.1", + "cspell-dictionary": "8.15.1", + "cspell-glob": "8.15.1", + "cspell-grammar": "8.15.1", + "cspell-io": "8.15.1", + "cspell-trie-lib": "8.15.1", "env-paths": "^3.0.0", "fast-equals": "^5.0.1", "gensequence": "^7.0.0", @@ -4320,14 +4438,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.14.4", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.14.4.tgz", - "integrity": "sha512-zu8EJ33CH+FA5lwTRGqS//Q6phO0qtgEmODMR1KPlD7WlrfTFMb3bWFsLo/tiv5hjpsn7CM6dYDAAgBOSkoyhQ==", + "version": "8.15.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.15.1.tgz", + "integrity": "sha512-/m7GYH2ICictHt4cpuXQDMtcLDnfj3Picc/uV87n1JQPiB1lHyu4IawhaZB5nRS5cZgYab4wQKKVD8dLbwWXHQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.14.4", - "@cspell/cspell-types": "8.14.4", + "@cspell/cspell-pipe": "8.15.1", + "@cspell/cspell-types": "8.15.1", "gensequence": "^7.0.0" }, "engines": { @@ -4348,9 +4466,9 @@ } }, "node_modules/css-functions-list": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.2.tgz", - "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", + "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", "dev": true, "license": "MIT", "engines": { @@ -4358,13 +4476,13 @@ } }, "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.0.0.tgz", + "integrity": "sha512-o88DVQ6GzsABn1+6+zo2ct801dBO5OASVyxbbvA2W20ue2puSh/VOuqUj90eUeMSX/xqGqBmOKiRQN7tJOuBXw==", "dev": true, "license": "MIT", "dependencies": { - "mdn-data": "2.0.30", + "mdn-data": "2.10.0", "source-map-js": "^1.0.1" }, "engines": { @@ -4720,6 +4838,19 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -5122,6 +5253,16 @@ "node": ">= 0.4" } }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -5196,9 +5337,9 @@ } }, "node_modules/eslint": { - "version": "9.11.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz", - "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -5206,11 +5347,11 @@ "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.6.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.11.1", + "@eslint/js": "9.12.0", "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", + "@humanwhocodes/retry": "^0.3.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -5218,9 +5359,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5230,13 +5371,11 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "bin": { @@ -5257,6 +5396,134 @@ } } }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-plugin-jest": { "version": "28.8.3", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", @@ -5284,10 +5551,11 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.1.tgz", - "integrity": "sha512-SY9oUuTMr6aWoJggUS40LtMjsRzJPB5ZT7F432xZIHK3EfHF+8i48GbUBpwanrtlL9l1gILNTHK9o8gEhYLcKA==", + "version": "50.3.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.2.tgz", + "integrity": "sha512-TjgZocG53N3a84PdCFGqVMWLWwDitOUuKjlJftwTu/iTiD7N/Q2Q3eEy/Q4GfJqpM4rTJCkzUYWQfol6RZNDcA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@es-joy/jsdoccomment": "~0.48.0", "are-docs-informative": "^0.0.2", @@ -5376,15 +5644,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/eslint/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5438,18 +5697,6 @@ "node": "*" } }, - "node_modules/eslint/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", @@ -5608,9 +5855,9 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -5618,7 +5865,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -5810,6 +6057,7 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -5841,6 +6089,21 @@ "pend": "~1.2.0" } }, + "node_modules/fdir": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.0.tgz", + "integrity": "sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/feedme": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/feedme/-/feedme-2.0.2.tgz", @@ -7183,15 +7446,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -8709,9 +8963,9 @@ } }, "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.10.0.tgz", + "integrity": "sha512-qq7C3EtK3yJXMwz1zAab65pjl+UhohqMOctTgcqjLOWABqmwj+me02LSsCuEUxnst9X1lCBpoE0WArGKgdGDzw==", "dev": true, "license": "CC0-1.0" }, @@ -9203,6 +9457,58 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -9658,13 +9964,13 @@ } }, "node_modules/playwright": { - "version": "1.47.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", - "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.0.tgz", + "integrity": "sha512-qPqFaMEHuY/ug8o0uteYJSRfMGFikhUysk8ZvAtfKmUK3kc/6oNl/y3EczF8OFGYIi/Ex2HspMfzYArk6+XQSA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.2" + "playwright-core": "1.48.0" }, "bin": { "playwright": "cli.js" @@ -9677,9 +9983,9 @@ } }, "node_modules/playwright-core": { - "version": "1.47.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", - "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.0.tgz", + "integrity": "sha512-RBvzjM9rdpP7UUFrQzRwR8L/xR4HyC1QXMzGYTbf1vjw25/ya9NRAVnXi/0fvFopjebvyPzsmoK58xxeEOaVvA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -9904,9 +10210,9 @@ "license": "MIT" }, "node_modules/postcss-safe-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", - "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", + "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", "dev": true, "funding": [ { @@ -10153,6 +10459,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -10464,6 +10771,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -10521,6 +10829,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "funding": [ { "type": "github", @@ -11352,9 +11661,9 @@ } }, "node_modules/stylelint": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.9.0.tgz", - "integrity": "sha512-31Nm3WjxGOBGpQqF43o3wO9L5AC36TPIe6030Lnm13H3vDMTcS21DrLh69bMX+DBilKqMMVLian4iG6ybBoNRQ==", + "version": "16.10.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.10.0.tgz", + "integrity": "sha512-z/8X2rZ52dt2c0stVwI9QL2AFJhLhbPkyfpDFcizs200V/g7v+UYY6SNcB9hKOLcDDX/yGLDsY/pX08sLkz9xQ==", "dev": true, "funding": [ { @@ -11376,17 +11685,17 @@ "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.2", - "css-tree": "^2.3.1", - "debug": "^4.3.6", + "css-functions-list": "^3.2.3", + "css-tree": "^3.0.0", + "debug": "^4.3.7", "fast-glob": "^3.3.2", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^9.0.0", + "file-entry-cache": "^9.1.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", - "ignore": "^5.3.2", + "ignore": "^6.0.2", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", "known-css-properties": "^0.34.0", @@ -11395,14 +11704,13 @@ "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.0.1", - "postcss": "^8.4.41", + "postcss": "^8.4.47", "postcss-resolve-nested-selector": "^0.1.6", - "postcss-safe-parser": "^7.0.0", + "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^6.1.2", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", - "strip-ansi": "^7.1.0", "supports-hyperlinks": "^3.1.0", "svg-tags": "^1.0.0", "table": "^6.8.2", @@ -11526,6 +11834,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stylelint/node_modules/globby/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylelint/node_modules/ignore": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", + "integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/stylelint/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", @@ -11848,6 +12176,20 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.9.tgz", + "integrity": "sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.0", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/tldts": { "version": "6.1.48", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.48.tgz", @@ -11945,6 +12287,42 @@ "typescript": ">=4.2.0" } }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", diff --git a/package.json b/package.json index 4314be6141..75fc840d6e 100644 --- a/package.json +++ b/package.json @@ -59,8 +59,8 @@ "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.11.1", - "express": "^4.21.0", + "eslint": "^9.12.0", + "express": "^4.21.1", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^8.0.0", @@ -75,21 +75,22 @@ "systeminformation": "^5.23.5" }, "devDependencies": { - "@eslint/js": "^9.11.1", - "@stylistic/eslint-plugin": "^2.8.0", - "cspell": "^8.14.4", + "@eslint/js": "^9.12.0", + "@stylistic/eslint-plugin": "^2.9.0", + "cspell": "^8.15.1", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.3.1", + "eslint-plugin-jsdoc": "^50.3.2", "eslint-plugin-package-json": "^0.15.3", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", - "playwright": "^1.47.2", + "playwright": "^1.48.0", "prettier": "^3.3.3", "sinon": "^19.0.2", - "stylelint": "^16.9.0", + "stylelint": "^16.10.0", "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.2" }, From 0f024cff4e08430e7bc25c3f7c7571c86b948f94 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 19 Oct 2024 12:11:20 +0200 Subject: [PATCH 128/418] Run and test with node 23 (#3588) --- .github/CONTRIBUTING.md | 2 +- .github/ISSUE_TEMPLATE.md | 2 +- .github/workflows/automated-tests.yaml | 2 +- .github/workflows/electron-rebuild.yaml | 2 +- CHANGELOG.md | 1 + package-lock.json | 2 +- package.json | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 360ea62189..1166747bd5 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -43,7 +43,7 @@ When submitting a new issue, please supply the following information: **Platform**: Place your platform here... give us your web browser/Electron version _and_ your hardware (Raspberry Pi 2/3/4, Windows, Mac, Linux, System V UNIX). -**Node Version**: Make sure it's version 18 or later (recommended is 20). +**Node Version**: Make sure it's version 20 or later (recommended is 22). **MagicMirror² Version**: Please let us know which version of MagicMirror² you are running. It can be found in the `package.json` file. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index f24edfc4b0..2aa4b4d87f 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -35,7 +35,7 @@ When submitting a new issue, please supply the following information: **Platform**: Place your platform here... give us your web browser/Electron version _and_ your hardware (Raspberry Pi 2/3/4, Windows, Mac, Linux, System V UNIX). -**Node Version**: Make sure it's version 18 or later (recommended is 20). +**Node Version**: Make sure it's version 20 or later (recommended is 22). **MagicMirror² Version**: Please let us know which version of MagicMirror² you are running. It can be found in the `package.json` file. diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index e48acd9bcc..1c64d3a727 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -18,7 +18,7 @@ jobs: timeout-minutes: 30 strategy: matrix: - node-version: [20.9.0, 20.x, 22.x] + node-version: [20.9.0, 20.x, 22.x, 23.x] steps: - name: "Checkout code" uses: actions/checkout@v4 diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index e5bfa13c3e..5c5e9b5a3f 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.9.0, 20.x, 22.x] + node-version: [20.9.0, 20.x, 22.x, 23.x] steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index c31665ac36..570b041087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ _This release is scheduled to be released on 2025-01-01._ - [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) - [core] Update electron dependency to v32 (test electron rebuild) - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) +- [core] Run and test with node 23 ### Fixed diff --git a/package-lock.json b/package-lock.json index 985f396fbc..a570db2ff8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,7 +50,7 @@ "stylelint-prettier": "^5.0.2" }, "engines": { - "node": ">=20.9.0 <21 || 22" + "node": ">=20.9.0 <21 || 22 || >=23" }, "optionalDependencies": { "electron": "^32.2.0" diff --git a/package.json b/package.json index 75fc840d6e..35be4b4424 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "electron": "^32.2.0" }, "engines": { - "node": ">=20.9.0 <21 || 22" + "node": ">=20.9.0 <21 || 22 || >=23" }, "_moduleAliases": { "node_helper": "js/node_helper.js", From b54fc08da7f5ee0c86d9b89af7b8dbfd701e25f5 Mon Sep 17 00:00:00 2001 From: Veeck Date: Wed, 23 Oct 2024 20:47:01 +0200 Subject: [PATCH 129/418] Add npm publishing step to release process (#3595) so that the npm version also stays in sync and https://github.com/MagicMirrorOrg/MagicMirror/issues/2876 can be closed for good --- CHANGELOG.md | 3 +- Collaboration.md | 1 + package-lock.json | 482 +++++++++++++++++++-------------------- package.json | 14 +- vendor/package-lock.json | 8 +- vendor/package.json | 2 +- 6 files changed, 249 insertions(+), 261 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 570b041087..a6913948db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Added - [linter] re-added `eslint-plugin-import`now that it supports ESLint v9 +- [docs] Added step for npm publishing in release process ### Removed @@ -68,7 +69,7 @@ Thanks to: @bugsounet, @dkallen78, @jargordon, @khassel, @KristjanESPERANTO, @Ma ### Fixed -- Fixed `checks` badge in README.md +- [docs] Fixed `checks` badge in README.md - [weather] Fixed issue with the UK Met Office provider following a change in their API paths and header info. - [core] add check for node_helper loading for multiple instances of same module (#3502) - [weather] Fixed issue for respecting unit config on broadcasted notifications diff --git a/Collaboration.md b/Collaboration.md index a0c64bd9bc..1bb69e5ba4 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -56,3 +56,4 @@ Are done by - [ ] publish release notes with link to github release on forum in new locked topic - [ ] close all issues with label `ready (coming with next release)` - [ ] release new documentation by merging `develop` on `master` in documentation repository +- [ ] publish new version on [npm](https://www.npmjs.com/package/magicmirror) diff --git a/package-lock.json b/package-lock.json index a570db2ff8..34ef5da3ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.12.0", + "eslint": "^9.13.0", "express": "^4.21.1", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -30,19 +30,19 @@ "systeminformation": "^5.23.5" }, "devDependencies": { - "@eslint/js": "^9.12.0", + "@eslint/js": "^9.13.0", "@stylistic/eslint-plugin": "^2.9.0", - "cspell": "^8.15.1", + "cspell": "^8.15.4", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.3.2", - "eslint-plugin-package-json": "^0.15.3", + "eslint-plugin-jsdoc": "^50.4.3", + "eslint-plugin-package-json": "^0.15.4", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", - "playwright": "^1.48.0", + "playwright": "^1.48.1", "prettier": "^3.3.3", "sinon": "^19.0.2", "stylelint": "^16.10.0", @@ -53,7 +53,7 @@ "node": ">=20.9.0 <21 || 22 || >=23" }, "optionalDependencies": { - "electron": "^32.2.0" + "electron": "^32.2.1" } }, "node_modules/@altano/repository-tools": { @@ -702,87 +702,87 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.15.1.tgz", - "integrity": "sha512-BimBlwdY4gD1cnx8nAaCPLY+yHpAgTuB25rQmpCLMSslQJBFkynRtOmtYQR+Mh4hX9nLaA3oPO4uVKOHVhQ00Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/dict-ada": "^4.0.2", - "@cspell/dict-aws": "^4.0.4", - "@cspell/dict-bash": "^4.1.5", - "@cspell/dict-companies": "^3.1.4", - "@cspell/dict-cpp": "^5.1.19", - "@cspell/dict-cryptocurrencies": "^5.0.0", - "@cspell/dict-csharp": "^4.0.2", - "@cspell/dict-css": "^4.0.13", - "@cspell/dict-dart": "^2.2.1", - "@cspell/dict-django": "^4.1.0", - "@cspell/dict-docker": "^1.1.7", - "@cspell/dict-dotnet": "^5.0.5", - "@cspell/dict-elixir": "^4.0.3", - "@cspell/dict-en_us": "^4.3.23", - "@cspell/dict-en-common-misspellings": "^2.0.4", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.15.4.tgz", + "integrity": "sha512-t5b2JwGeUmzmjl319mCuaeKGxTvmzLLRmrpdHr+ZZGRO4nf7L48Lbe9A6uwNUvsZe0cXohiNXsrrsuzRVXswVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-ada": "^4.0.5", + "@cspell/dict-aws": "^4.0.7", + "@cspell/dict-bash": "^4.1.8", + "@cspell/dict-companies": "^3.1.7", + "@cspell/dict-cpp": "^5.1.22", + "@cspell/dict-cryptocurrencies": "^5.0.3", + "@cspell/dict-csharp": "^4.0.5", + "@cspell/dict-css": "^4.0.16", + "@cspell/dict-dart": "^2.2.4", + "@cspell/dict-django": "^4.1.3", + "@cspell/dict-docker": "^1.1.11", + "@cspell/dict-dotnet": "^5.0.8", + "@cspell/dict-elixir": "^4.0.6", + "@cspell/dict-en_us": "^4.3.26", + "@cspell/dict-en-common-misspellings": "^2.0.7", "@cspell/dict-en-gb": "1.1.33", - "@cspell/dict-filetypes": "^3.0.4", - "@cspell/dict-flutter": "^1.0.0", - "@cspell/dict-fonts": "^4.0.0", - "@cspell/dict-fsharp": "^1.0.1", - "@cspell/dict-fullstack": "^3.2.0", - "@cspell/dict-gaming-terms": "^1.0.5", - "@cspell/dict-git": "^3.0.0", - "@cspell/dict-golang": "^6.0.13", - "@cspell/dict-google": "^1.0.1", - "@cspell/dict-haskell": "^4.0.1", - "@cspell/dict-html": "^4.0.6", - "@cspell/dict-html-symbol-entities": "^4.0.0", - "@cspell/dict-java": "^5.0.7", - "@cspell/dict-julia": "^1.0.1", - "@cspell/dict-k8s": "^1.0.6", - "@cspell/dict-latex": "^4.0.0", - "@cspell/dict-lorem-ipsum": "^4.0.0", - "@cspell/dict-lua": "^4.0.3", - "@cspell/dict-makefile": "^1.0.0", - "@cspell/dict-monkeyc": "^1.0.6", - "@cspell/dict-node": "^5.0.1", - "@cspell/dict-npm": "^5.1.5", - "@cspell/dict-php": "^4.0.10", - "@cspell/dict-powershell": "^5.0.10", - "@cspell/dict-public-licenses": "^2.0.8", - "@cspell/dict-python": "^4.2.8", - "@cspell/dict-r": "^2.0.1", - "@cspell/dict-ruby": "^5.0.4", - "@cspell/dict-rust": "^4.0.6", - "@cspell/dict-scala": "^5.0.3", - "@cspell/dict-software-terms": "^4.1.7", - "@cspell/dict-sql": "^2.1.5", - "@cspell/dict-svelte": "^1.0.2", - "@cspell/dict-swift": "^2.0.1", - "@cspell/dict-terraform": "^1.0.2", - "@cspell/dict-typescript": "^3.1.6", - "@cspell/dict-vue": "^3.0.0" + "@cspell/dict-filetypes": "^3.0.7", + "@cspell/dict-flutter": "^1.0.3", + "@cspell/dict-fonts": "^4.0.3", + "@cspell/dict-fsharp": "^1.0.4", + "@cspell/dict-fullstack": "^3.2.3", + "@cspell/dict-gaming-terms": "^1.0.8", + "@cspell/dict-git": "^3.0.3", + "@cspell/dict-golang": "^6.0.16", + "@cspell/dict-google": "^1.0.4", + "@cspell/dict-haskell": "^4.0.4", + "@cspell/dict-html": "^4.0.9", + "@cspell/dict-html-symbol-entities": "^4.0.3", + "@cspell/dict-java": "^5.0.10", + "@cspell/dict-julia": "^1.0.4", + "@cspell/dict-k8s": "^1.0.9", + "@cspell/dict-latex": "^4.0.3", + "@cspell/dict-lorem-ipsum": "^4.0.3", + "@cspell/dict-lua": "^4.0.6", + "@cspell/dict-makefile": "^1.0.3", + "@cspell/dict-monkeyc": "^1.0.9", + "@cspell/dict-node": "^5.0.4", + "@cspell/dict-npm": "^5.1.8", + "@cspell/dict-php": "^4.0.13", + "@cspell/dict-powershell": "^5.0.13", + "@cspell/dict-public-licenses": "^2.0.11", + "@cspell/dict-python": "^4.2.12", + "@cspell/dict-r": "^2.0.4", + "@cspell/dict-ruby": "^5.0.7", + "@cspell/dict-rust": "^4.0.9", + "@cspell/dict-scala": "^5.0.6", + "@cspell/dict-software-terms": "^4.1.11", + "@cspell/dict-sql": "^2.1.8", + "@cspell/dict-svelte": "^1.0.5", + "@cspell/dict-swift": "^2.0.4", + "@cspell/dict-terraform": "^1.0.5", + "@cspell/dict-typescript": "^3.1.10", + "@cspell/dict-vue": "^3.0.3" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.15.1.tgz", - "integrity": "sha512-mU4eWHYjGGdhmLd4oGz4kEry2udUl3thzz3clLiutijPrmNU/5sS5C6tiKBZCytWhhCkTwA5eDM3rr7cIt4DYQ==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.15.4.tgz", + "integrity": "sha512-solraYhZG4l++NeVCOtpc8DMvwHc46TmJt8DQbgvKtk6wOjTEcFrwKfA6Ei9YKbvyebJlpWMenO3goOll0loYg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.15.1" + "@cspell/cspell-types": "8.15.4" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.15.1.tgz", - "integrity": "sha512-euErNW69K6+rCirGtORbgapcNtvlObTlO7SHftRRjGbvMh1F5J1rEc+KwW3qhM5H73NSwFrQwR5KzWrUrGimog==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.15.4.tgz", + "integrity": "sha512-WfCmZVFC6mX6vYlf02hWwelcSBTbDQgc5YqY+1miuMk+OHSUAHSACjZId6/a4IAID94xScvFfj7jgrdejUVvIQ==", "dev": true, "license": "MIT", "engines": { @@ -790,9 +790,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.15.1.tgz", - "integrity": "sha512-9GVRSZKLc7P4S1aOzBiyXbtVMu3yeDHpp/sAeKd7Z869T2ddvMrmQoOTRBmKW90PNP2j4aQkPebPJe85GnOf+A==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.15.4.tgz", + "integrity": "sha512-Zr428o+uUTqywrdKyjluJVnDPVAJEqZ1chQLKIrHggUah1cgs5aQ7rZ+0Rv5euYMlC2idZnP7IL6TDaIib80oA==", "dev": true, "license": "MIT", "dependencies": { @@ -803,9 +803,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.15.1.tgz", - "integrity": "sha512-SFnJNw0BOagdx29soC8tiDNObENLU2FFhfT7JHbILHbJ5IdtsRLAxYIf99rDb1zLB3pdA/optqPwPUdAgMIQLg==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.15.4.tgz", + "integrity": "sha512-pXYofnV/V9Y3LZdfFGbmhdxPX/ABjiD3wFjGHt5YhIU9hjVVuvjFlgY7pH2AvRjs4F8xKXv1ReWl44BJOL9gLA==", "dev": true, "license": "MIT", "engines": { @@ -813,9 +813,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.15.1.tgz", - "integrity": "sha512-6QY0147RmiXIpTMkwI7a6dx+/CtPserPxxsK2p0DFf4bTHOGExx3dlPg7eGL8UFO0/C/nrXPAMy5kZEstPclXA==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.15.4.tgz", + "integrity": "sha512-1hDtgYDQVW11zgtrr12EmGW45Deoi7IjZOhzPFLb+3WkhZ46ggWdbrRalWwBolQPDDo6+B2Q6WXz5hdND+Tpwg==", "dev": true, "license": "MIT", "engines": { @@ -900,9 +900,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-docker": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.10.tgz", - "integrity": "sha512-vWybMfsG/8jhN6kmPoilMon36GB3+Ef+m/mgYUfY8tJN23K/x4KD1rU1OOiNWzDqePhu3MMWVKO5W5x6VI6Gbw==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.11.tgz", + "integrity": "sha512-s0Yhb16/R+UT1y727ekbR/itWQF3Qz275DR1ahOa66wYtPjHUXmhM3B/LT3aPaX+hD6AWmK23v57SuyfYHUjsw==", "dev": true, "license": "MIT" }, @@ -942,9 +942,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.7.tgz", - "integrity": "sha512-/DN0Ujp9/EXvpTcgih9JmBaE8n+G0wtsspyNdvHT5luRfpfol1xm/CIQb6xloCXCiLkWX+EMPeLSiVIZq+24dA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.8.tgz", + "integrity": "sha512-D3N8sm/iptzfVwsib/jvpX+K/++rM8SRpLDFUaM4jxm8EyGmSIYRbKZvdIv5BkAWmMlTWoRqlLn7Yb1b11jKJg==", "dev": true, "license": "MIT" }, @@ -1012,9 +1012,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-html": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.9.tgz", - "integrity": "sha512-BNp7w3m910K4qIVyOBOZxHuFNbVojUY6ES8Y8r7YjYgJkm2lCuQoVwwhPjurnomJ7BPmZTb+3LLJ58XIkgF7JQ==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.10.tgz", + "integrity": "sha512-I9uRAcdtHbh0wEtYZlgF0TTcgH0xaw1B54G2CW+tx4vHUwlde/+JBOfIzird4+WcMv4smZOfw+qHf7puFUbI5g==", "dev": true, "license": "MIT" }, @@ -1117,9 +1117,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.11.tgz", - "integrity": "sha512-bshNZqP5FYRO0CtZ9GgtVjHidrSuRRF537MU/sPew8oaqWPg066F9KQfPllbRi9AzFqqeS2l7/ACYUrFMe21gw==", + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.12.tgz", + "integrity": "sha512-U25eOFu+RE0aEcF2AsxZmq3Lic7y9zspJ9SzjrC0mfJz+yr3YmSCw4E0blMD3mZoNcf7H/vMshuKIY5AY36U+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1155,9 +1155,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.10.tgz", - "integrity": "sha512-+9PuQ9MHQhlET6Hv1mGcWDh6Rb+StzjBMrjfksDeBHBIVdT66u9uCkaZapIzfgktflY4m9oK7+dEynr+BAxvtQ==", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.11.tgz", + "integrity": "sha512-77CTHxWFTVw6tVoMN8WBMrlNW2F2FbgATwD/6vcOuiyrJUmh8klN5ZK3m+yyK3ZzsnaW2Bduoc0fw2Ckcm/riQ==", "dev": true, "license": "MIT" }, @@ -1190,9 +1190,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-typescript": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.9.tgz", - "integrity": "sha512-ZtO1/cVWvvR477ftTl2TFR09+IIzXG1rcin8CGYA0FO5WhyDAbn8v3A85QikS158BhTVUoq09lPYuSF9HBzqvw==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.11.tgz", + "integrity": "sha512-FwvK5sKbwrVpdw0e9+1lVTl8FPoHYvfHRuQRQz2Ql5XkC0gwPPkpoyD1zYImjIyZRoYXk3yp9j8ss4iz7A7zoQ==", "dev": true, "license": "MIT" }, @@ -1204,9 +1204,9 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.15.1.tgz", - "integrity": "sha512-Zc7tAn1EBFgPcpws0zoZrMyi0likUb3Kpnpq4FGmssmf4PnhSaDF2suqLlcCTPxCML87lF26UT6qUK01G9gIPA==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.15.4.tgz", + "integrity": "sha512-tr0F6EYN6qtniNvt1Uib+PgYQHeo4dQHXE2Optap+hYTOoQ2VoQ+SwBVjZ+Q2bmSAB0fmOyf0AvgsUtnWIpavw==", "dev": true, "license": "MIT", "dependencies": { @@ -1217,9 +1217,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.15.1.tgz", - "integrity": "sha512-SgwTDmy5Omc67ThA89t1+kNZcbwGr43ck0Il+tqSoNOBHbs+S5YftUgfinLFIN2pdRm4COPmAnEN2SEAsMh0UA==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.15.4.tgz", + "integrity": "sha512-sNl6jr3ym/4151EY76qlI/00HHsiLZBqW7Vb1tqCzsgSg3EpL30ddjr74So6Sg2PN26Yf09hvxGTJzXn1R4aYw==", "dev": true, "license": "MIT", "engines": { @@ -1227,9 +1227,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.15.1.tgz", - "integrity": "sha512-QmtDb0TBdLBlDqOCrOtqhg9e7k4T4t8akx+1LgNI/jGqj/mQVyYtHCHWVHYNxh7S7DumrlmmsJo62NzIZLqtCQ==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.15.4.tgz", + "integrity": "sha512-m5DeQksbhJFqcSYF8Q0Af/WXmXCMAJocCUShkzOXK+uZNXnvhBZN7VyQ9hL+GRzX8JTPEPdVcz2lFyVE5p+LzQ==", "dev": true, "license": "MIT", "engines": { @@ -1237,9 +1237,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.15.1.tgz", - "integrity": "sha512-LsLoeLRTrdQY1iLsnOxSta/+YvnT3Jm/Ofohhh6XBSegMl2CoJjzdY8wbfsc3YgdB6SHJ1PSZecftXRhMNIEeg==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.15.4.tgz", + "integrity": "sha512-K2oZu/oLQPs5suRpLS8uu04O3YMUioSlEU1D66fRoOxzI5NzLt7i7yMg3HQHjChGa09N5bzqmrVdhmQrRZXwGg==", "dev": true, "license": "MIT", "engines": { @@ -1390,9 +1390,9 @@ } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.48.0.tgz", - "integrity": "sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw==", + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz", + "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1477,9 +1477,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1553,9 +1553,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", - "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", + "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4270,25 +4270,25 @@ } }, "node_modules/cspell": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.15.1.tgz", - "integrity": "sha512-bF2RNErisDg3pfm1tOrq/74g9n09wprg2Im+TNwDSmivusE9LxFoyhEPOiGBVg25/iMSu/BPx5nDNL1WDGwZqA==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.15.4.tgz", + "integrity": "sha512-hUOxcwmNWuHzVeGHyN5v/T9MkyCE5gi0mvatxsM794B2wOuR1ZORgjZH62P2HY1uBkXe/x5C6ITWrSyh0WgAcg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.15.1", - "@cspell/cspell-pipe": "8.15.1", - "@cspell/cspell-types": "8.15.1", - "@cspell/dynamic-import": "8.15.1", - "@cspell/url": "8.15.1", + "@cspell/cspell-json-reporter": "8.15.4", + "@cspell/cspell-pipe": "8.15.4", + "@cspell/cspell-types": "8.15.4", + "@cspell/dynamic-import": "8.15.4", + "@cspell/url": "8.15.4", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^12.1.0", - "cspell-dictionary": "8.15.1", - "cspell-gitignore": "8.15.1", - "cspell-glob": "8.15.1", - "cspell-io": "8.15.1", - "cspell-lib": "8.15.1", + "cspell-dictionary": "8.15.4", + "cspell-gitignore": "8.15.4", + "cspell-glob": "8.15.4", + "cspell-io": "8.15.4", + "cspell-lib": "8.15.4", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", @@ -4307,30 +4307,43 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.15.1.tgz", - "integrity": "sha512-hDkaRRsqJbvAKA5ZoUBobozAA8iTcNzgo3mHK+FCVbGGaA2903q8mG3yFBviFioXUHsBBlN7Em/3JQDnasO3qQ==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.15.4.tgz", + "integrity": "sha512-vUgikQTRkRMTdkZqSs7F2cTdPpX61cTjr/9L/VCkXkbW38ObCr4650ioiF1Wq3zDF3Gy2bc4ECTpD2PZUXX5SA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.15.1", + "@cspell/cspell-types": "8.15.4", "comment-json": "^4.2.5", - "yaml": "^2.5.1" + "yaml": "^2.6.0" }, "engines": { "node": ">=18" } }, + "node_modules/cspell-config-lib/node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/cspell-dictionary": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.15.1.tgz", - "integrity": "sha512-N0Wz/hQlRDVuAH2OqlU9Uad++XccwsZuTmdV82HUHGCjmtHUxCiHD51+d2tsLX8ZXur0/eL988RIMPFePYIOww==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.15.4.tgz", + "integrity": "sha512-8+p/l9Saac7qyCbqtELneDoT7CwHu9gYmnI8uXMu34/lPGjhVhy10ZeI0+t1djaO2YyASK400YFKq5uP/5KulA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.1", - "@cspell/cspell-types": "8.15.1", - "cspell-trie-lib": "8.15.1", + "@cspell/cspell-pipe": "8.15.4", + "@cspell/cspell-types": "8.15.4", + "cspell-trie-lib": "8.15.4", "fast-equals": "^5.0.1" }, "engines": { @@ -4338,15 +4351,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.15.1.tgz", - "integrity": "sha512-RBJnOIXYKk9ZpYx/y8Hcl/jIhdKposid5Em/GUpj65vXPa0N9arpVXCiIObAtu3645NeHd+Z6RrhNLdKhyZprQ==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.15.4.tgz", + "integrity": "sha512-9n5PpQ8gEf8YcvEtoZGZ2Ma6wnqSFkD2GrmyjISy39DfIX/jNLN7GX2wJm6OD2P4FjXer95ypmIb/JWTlfmbTw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.15.1", - "cspell-glob": "8.15.1", - "cspell-io": "8.15.1", + "@cspell/url": "8.15.4", + "cspell-glob": "8.15.4", + "cspell-io": "8.15.4", "find-up-simple": "^1.0.0" }, "bin": { @@ -4357,13 +4370,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.15.1.tgz", - "integrity": "sha512-INKBWUVGg595+F8V8kEEP07OPqQGJs+qp6Q587UwP+yvxMZ4PYA6PudvZEwa5capVxIbSYDNafqtcc2F3MaPbw==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.15.4.tgz", + "integrity": "sha512-TTfRRHRAN+PN9drIz4MAEgKKYnPThBOlPMdFddyuisvU33Do1sPAnqkkOjTEFdi3jAA5KwnSva68SVH6IzzMBQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.15.1", + "@cspell/url": "8.15.4", "micromatch": "^4.0.8" }, "engines": { @@ -4371,14 +4384,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.15.1.tgz", - "integrity": "sha512-4sZ3uh3rgrcoBMwXCmq8rDazVYKR2AUAm36t/EU5uiD+Ju1FfoEaxw1DTKtVDGMNNad6JmNmqxOoFdLAqL1sQA==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.15.4.tgz", + "integrity": "sha512-MKiKyYi05mRtXOxPoTv3Ksi0GwYLiK84Uq0C+5PaMrnIjXeed0bsddSFXCT+7ywFJc7PdjhTtz0M/9WWK3UgbA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.1", - "@cspell/cspell-types": "8.15.1" + "@cspell/cspell-pipe": "8.15.4", + "@cspell/cspell-types": "8.15.4" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4388,42 +4401,42 @@ } }, "node_modules/cspell-io": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.15.1.tgz", - "integrity": "sha512-PvzOm4utZuhb97hqlWS1F+ZHbMVbFsUUC0HQcubquLkjV8s/yryuBlgP52gOxNGTZjyEULWk9MYUldRZK3oB8g==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.15.4.tgz", + "integrity": "sha512-rXIEREPTFV9dwwg4EKfvzqlCNOvT6910AYED5YrSt8Y68usRJ9lbqdx0BrDndVCd33bp1o+9JBfHuRiFIQC81g==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.15.1", - "@cspell/url": "8.15.1" + "@cspell/cspell-service-bus": "8.15.4", + "@cspell/url": "8.15.4" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.15.1.tgz", - "integrity": "sha512-qwfeok4DKYhNjlXOLDZ1hagKAKIXByfMSizTlwIMmmZVJ+8SL61P+PJG0ggwLteq9fEK+oLwaf/N2bVRH6M28Q==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.15.4.tgz", + "integrity": "sha512-iLp/625fvCyFFxSyZYLMgqHIKcrhN4hT7Hw5+ySa38Bp/OfA81ANqWHpsDQ0bGsALTRn/DHBpQYj4xCW/aN9tw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.15.1", - "@cspell/cspell-pipe": "8.15.1", - "@cspell/cspell-resolver": "8.15.1", - "@cspell/cspell-types": "8.15.1", - "@cspell/dynamic-import": "8.15.1", - "@cspell/filetypes": "8.15.1", - "@cspell/strong-weak-map": "8.15.1", - "@cspell/url": "8.15.1", + "@cspell/cspell-bundled-dicts": "8.15.4", + "@cspell/cspell-pipe": "8.15.4", + "@cspell/cspell-resolver": "8.15.4", + "@cspell/cspell-types": "8.15.4", + "@cspell/dynamic-import": "8.15.4", + "@cspell/filetypes": "8.15.4", + "@cspell/strong-weak-map": "8.15.4", + "@cspell/url": "8.15.4", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.15.1", - "cspell-dictionary": "8.15.1", - "cspell-glob": "8.15.1", - "cspell-grammar": "8.15.1", - "cspell-io": "8.15.1", - "cspell-trie-lib": "8.15.1", + "cspell-config-lib": "8.15.4", + "cspell-dictionary": "8.15.4", + "cspell-glob": "8.15.4", + "cspell-grammar": "8.15.4", + "cspell-io": "8.15.4", + "cspell-trie-lib": "8.15.4", "env-paths": "^3.0.0", "fast-equals": "^5.0.1", "gensequence": "^7.0.0", @@ -4438,14 +4451,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.15.1", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.15.1.tgz", - "integrity": "sha512-/m7GYH2ICictHt4cpuXQDMtcLDnfj3Picc/uV87n1JQPiB1lHyu4IawhaZB5nRS5cZgYab4wQKKVD8dLbwWXHQ==", + "version": "8.15.4", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.15.4.tgz", + "integrity": "sha512-sg9klsNHyrfos0Boiio+qy5d6fI9cCNjBqFYrNxvpKpwZ4gEzDzjgEKdZY1C76RD2KoBQ8I1NF5YcGc0+hhhCw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.1", - "@cspell/cspell-types": "8.15.1", + "@cspell/cspell-pipe": "8.15.4", + "@cspell/cspell-types": "8.15.4", "gensequence": "^7.0.0" }, "engines": { @@ -4913,9 +4926,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "32.2.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.0.tgz", - "integrity": "sha512-Xy82QBQrEiQysoxsv6lnhHAcWNNe6vV6QqH3OPFXhEj/T9oAsBHEhZuuYHINSSsUE7zRSj+J9sNwJYOjisT0Vw==", + "version": "32.2.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.1.tgz", + "integrity": "sha512-GCPI/5hU34pPcNltNpz+uylhhuTm9BM0N8RmrbVgaWBodLSmmcCkvpgN0BseKhO6IwQOPzWaovrcZ/nPIpfGaQ==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5337,17 +5350,17 @@ } }, "node_modules/eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", + "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", + "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", + "@eslint/js": "9.13.0", "@eslint/plugin-kit": "^0.2.0", "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", @@ -5551,13 +5564,13 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.3.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.2.tgz", - "integrity": "sha512-TjgZocG53N3a84PdCFGqVMWLWwDitOUuKjlJftwTu/iTiD7N/Q2Q3eEy/Q4GfJqpM4rTJCkzUYWQfol6RZNDcA==", + "version": "50.4.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.4.3.tgz", + "integrity": "sha512-uWtwFxGRv6B8sU63HZM5dAGDhgsatb+LONwmILZJhdRALLOkCX2HFZhdL/Kw2ls8SQMAVEfK+LmnEfxInRN8HA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.48.0", + "@es-joy/jsdoccomment": "~0.49.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.6", @@ -5577,20 +5590,20 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.3.tgz", - "integrity": "sha512-NRUh+f5orM2/SynPjZqqNqSahdG3qzG5nf8s2S5nEwkhRbEE78S6sSMVGoSmrrtbhcbvZmLVHguVds4lY3Cwkw==", + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.4.tgz", + "integrity": "sha512-qH7q8xETpMqqdhmC/rj6hz7bNFGnzzkTuCQfBLNsupqB4ky596PalZLCMhn39NQocPqb5JIgGs0gnDX/VG22nQ==", "dev": true, "license": "MIT", "dependencies": { "@altano/repository-tools": "^0.1.1", "detect-indent": "6.1.0", "detect-newline": "3.1.0", - "package-json-validator": "^0.6.5", + "package-json-validator": "^0.7.0", "semver": "^7.5.4", "sort-object-keys": "^1.1.3", "sort-package-json": "^1.57.0", - "validate-npm-package-name": "^5.0.0" + "validate-npm-package-name": "^6.0.0" }, "engines": { "node": ">=18" @@ -9547,34 +9560,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", - "dev": true, - "license": "MIT/X11", - "dependencies": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "node_modules/optimist/node_modules/minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/optimist/node_modules/wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -9675,15 +9660,16 @@ } }, "node_modules/package-json-validator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.5.tgz", - "integrity": "sha512-fEG8kM+EfX0j7TbTWAv6/0NRkid0fUHm2afJx35en3+IlrJ6dRQfKUCpuUl/bGM6MvQ0MxAlpaXkJtYVMp0F4A==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.7.0.tgz", + "integrity": "sha512-ufEJ03cPLVxZCHuypSJjmUC2t0xDy0Eru4AfPFe2MfPw14BqedavayQqd49H2/VCrcWONmXsJ47Tp7kzaElX2w==", "dev": true, + "license": "MIT", "dependencies": { - "optimist": "~0.6.0" + "yargs": "~17.7.2" }, - "bin": { - "pjv": "bin/pjv" + "engines": { + "node": ">=18" } }, "node_modules/pako": { @@ -9964,13 +9950,13 @@ } }, "node_modules/playwright": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.0.tgz", - "integrity": "sha512-qPqFaMEHuY/ug8o0uteYJSRfMGFikhUysk8ZvAtfKmUK3kc/6oNl/y3EczF8OFGYIi/Ex2HspMfzYArk6+XQSA==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", + "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.48.0" + "playwright-core": "1.48.1" }, "bin": { "playwright": "cli.js" @@ -9983,9 +9969,9 @@ } }, "node_modules/playwright-core": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.0.tgz", - "integrity": "sha512-RBvzjM9rdpP7UUFrQzRwR8L/xR4HyC1QXMzGYTbf1vjw25/ya9NRAVnXi/0fvFopjebvyPzsmoK58xxeEOaVvA==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", + "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -12631,13 +12617,13 @@ } }, "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.0.tgz", + "integrity": "sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/vary": { diff --git a/package.json b/package.json index 35be4b4424..cf5e23ff28 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.12.0", + "eslint": "^9.13.0", "express": "^4.21.1", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -75,19 +75,19 @@ "systeminformation": "^5.23.5" }, "devDependencies": { - "@eslint/js": "^9.12.0", + "@eslint/js": "^9.13.0", "@stylistic/eslint-plugin": "^2.9.0", - "cspell": "^8.15.1", + "cspell": "^8.15.4", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.3.2", - "eslint-plugin-package-json": "^0.15.3", + "eslint-plugin-jsdoc": "^50.4.3", + "eslint-plugin-package-json": "^0.15.4", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", - "playwright": "^1.48.0", + "playwright": "^1.48.1", "prettier": "^3.3.3", "sinon": "^19.0.2", "stylelint": "^16.10.0", @@ -95,7 +95,7 @@ "stylelint-prettier": "^5.0.2" }, "optionalDependencies": { - "electron": "^32.2.0" + "electron": "^32.2.1" }, "engines": { "node": ">=20.9.0 <21 || 22 || >=23" diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 413d00ea06..19dabcc5ac 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -13,7 +13,7 @@ "animate.css": "^4.1.1", "croner": "^8.1.2", "moment": "^2.30.1", - "moment-timezone": "^0.5.45", + "moment-timezone": "^0.5.46", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" @@ -74,9 +74,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.45", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", - "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "version": "0.5.46", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz", + "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==", "license": "MIT", "dependencies": { "moment": "^2.29.4" diff --git a/vendor/package.json b/vendor/package.json index 8e7365e2e7..58780a2c93 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -15,7 +15,7 @@ "animate.css": "^4.1.1", "croner": "^8.1.2", "moment": "^2.30.1", - "moment-timezone": "^0.5.45", + "moment-timezone": "^0.5.46", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" From aa7e8561707a2906d90212ebb2466ab46da71f15 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 23 Oct 2024 21:42:29 +0200 Subject: [PATCH 130/418] Add wayland and windows start options (#3594) This PR adds start options for Wayland and Windows. This would solve issue #3582. **To Do if this PR is merged:** - [ ] Adjust [Windows section](https://docs.magicmirror.builders/getting-started/installation.html#windows) in documentation - [ ] Add Wayland section to the documentation --- CHANGELOG.md | 7 ++++--- package.json | 10 ++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6913948db..731ef6c30f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,9 @@ _This release is scheduled to be released on 2025-01-01._ ### Added -- [linter] re-added `eslint-plugin-import`now that it supports ESLint v9 -- [docs] Added step for npm publishing in release process +- [core] Add wayland and windows start options to `package.json` (#3594) +- [linter] re-added `eslint-plugin-import`now that it supports ESLint v9 (#3586) +- [docs] Added step for npm publishing in release process (#3595) ### Removed @@ -23,7 +24,7 @@ _This release is scheduled to be released on 2025-01-01._ - [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) - [core] Update electron dependency to v32 (test electron rebuild) - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) -- [core] Run and test with node 23 +- [core] Run and test with node 23 (#3588) ### Fixed diff --git a/package.json b/package.json index cf5e23ff28..dcc8912b99 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,14 @@ ], "main": "js/electron.js", "scripts": { - "start": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js", - "start:dev": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js dev", + "start": "npm run start:x11", + "start:dev": "npm run start -- dev", + "start:wayland": "WAYLAND_DISPLAY=\"${WAYLAND_DISPLAY:=wayland-1}\" ./node_modules/.bin/electron js/electron.js --enable-features=UseOzonePlatform --ozone-platform=wayland", + "start:wayland:dev": "npm run start:wayland -- dev", + "start:windows": ".\\node_modules\\.bin\\electron js\\electron.js", + "start:windows:dev": "npm run start:windows -- dev", + "start:x11": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js", + "start:x11:dev": "npm run start -- dev", "server": "node ./serveronly", "install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev", "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier", From 6946b499778bba8d4a031b225170645a303708e1 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Wed, 23 Oct 2024 16:46:32 -0500 Subject: [PATCH 131/418] Fixtestcase calendar testcase failure (#3596) fix calendar testcase failing after date change (exposes helper failure) --- CHANGELOG.md | 1 + tests/configs/modules/calendar/show-duplicates-in-calendar.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 731ef6c30f..555202530c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ _This release is scheduled to be released on 2025-01-01._ - [updatenotification] Fix pm2 using detection when pm2 script is in MagicMirror root folder (#3576) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) - [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) +- [calendar] fix one testcase which had a date expired problem.. ## [2.29.0] - 2024-10-01 diff --git a/tests/configs/modules/calendar/show-duplicates-in-calendar.js b/tests/configs/modules/calendar/show-duplicates-in-calendar.js index 7ad420944d..a42465816b 100644 --- a/tests/configs/modules/calendar/show-duplicates-in-calendar.js +++ b/tests/configs/modules/calendar/show-duplicates-in-calendar.js @@ -27,6 +27,10 @@ let config = { ] }; +Date.now = () => { + return new Date("15 Sep 2024 12:30:00 GMT").valueOf(); +}; + /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; From cfa5c0d1273096a0c054996255d1102d3d9994b7 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 25 Oct 2024 11:34:35 +0200 Subject: [PATCH 132/418] fix electron tests mocking dates (#3599) fixes #3597 Changes: - electron tests: add mocking to `electron.js` for mocking the server side, before only the browser side was mocked - publish "/tests/configs" and "/tests/mocks" always in `server.js`, this reverts a change done with latest release, we need this for debugging (otherwise you get on the screen that your config has errors but config check is successful ...) - revert hotfix in `tests/configs/modules/calendar/show-duplicates-in-calendar.js` - fix `tests/configs/modules/calendar/custom.js` to allow events in the past (~~I don't know how this could work before~~ when testing css classes `yesterday` and `dayBeforeYesterday` --> it worked before because the server side did not mock and therefore was not in the past) --- CHANGELOG.md | 2 +- js/electron.js | 17 +++++++++++++++++ js/server.js | 6 +----- tests/configs/modules/calendar/custom.js | 2 ++ .../calendar/show-duplicates-in-calendar.js | 4 ---- tests/electron/helpers/global-setup.js | 5 +++++ 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 555202530c..95c7d112c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ _This release is scheduled to be released on 2025-01-01._ - [updatenotification] Fix pm2 using detection when pm2 script is in MagicMirror root folder (#3576) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) - [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) -- [calendar] fix one testcase which had a date expired problem.. +- [tests] fix electron tests with mock dates, the mock on server side was missing (#3597) ## [2.29.0] - 2024-10-01 diff --git a/js/electron.js b/js/electron.js index 4bfe35427f..b0224149a7 100644 --- a/js/electron.js +++ b/js/electron.js @@ -76,6 +76,23 @@ function createWindow () { const electronOptions = Object.assign({}, electronOptionsDefaults, config.electronOptions); + if (process.env.JEST_WORKER_ID !== undefined && process.env.MOCK_DATE !== undefined) { + // if we are running with jest and we want to mock the current date + const fakeNow = new Date(process.env.MOCK_DATE).valueOf(); + Date = class extends Date { + constructor (...args) { + if (args.length === 0) { + super(fakeNow); + } else { + super(...args); + } + } + }; + const __DateNowOffset = fakeNow - Date.now(); + const __DateNow = Date.now; + Date.now = () => __DateNow() + __DateNowOffset; + } + // Create the browser window. mainWindow = new BrowserWindow(electronOptions); diff --git a/js/server.js b/js/server.js index 42b3ff6692..dd8b7b2e98 100644 --- a/js/server.js +++ b/js/server.js @@ -72,11 +72,7 @@ function Server (config) { app.use(helmet(config.httpHeaders)); app.use("/js", express.static(__dirname)); - let directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations"]; - if (process.env.JEST_WORKER_ID !== undefined) { - // add tests directories only when running tests - directories.push("/tests/configs", "/tests/mocks"); - } + let directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations", "/tests/configs", "/tests/mocks"]; for (const directory of directories) { app.use(directory, express.static(path.resolve(global.root_path + directory))); } diff --git a/tests/configs/modules/calendar/custom.js b/tests/configs/modules/calendar/custom.js index 9a2b4c6a95..bc2dc3b26c 100644 --- a/tests/configs/modules/calendar/custom.js +++ b/tests/configs/modules/calendar/custom.js @@ -13,6 +13,8 @@ let config = { calendars: [ { maximumEntries: 5, + pastDaysCount: 5, + broadcastPastEvents: true, maximumNumberOfDays: 10000, symbol: "birthday-cake", fullDaySymbol: "calendar-day", diff --git a/tests/configs/modules/calendar/show-duplicates-in-calendar.js b/tests/configs/modules/calendar/show-duplicates-in-calendar.js index a42465816b..7ad420944d 100644 --- a/tests/configs/modules/calendar/show-duplicates-in-calendar.js +++ b/tests/configs/modules/calendar/show-duplicates-in-calendar.js @@ -27,10 +27,6 @@ let config = { ] }; -Date.now = () => { - return new Date("15 Sep 2024 12:30:00 GMT").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; diff --git a/tests/electron/helpers/global-setup.js b/tests/electron/helpers/global-setup.js index 71dfd0ddbe..e7f8facafd 100644 --- a/tests/electron/helpers/global-setup.js +++ b/tests/electron/helpers/global-setup.js @@ -8,6 +8,10 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar global.page = null; process.env.MM_CONFIG_FILE = configFilename; process.env.TZ = timezone; + if (systemDate) { + process.env.MOCK_DATE = systemDate; + } + global.electronApp = await electron.launch({ args: electronParams }); await global.electronApp.firstWindow(); @@ -34,6 +38,7 @@ exports.stopApplication = async () => { } global.electronApp = null; global.page = null; + process.env.MOCK_DATE = undefined; }; exports.getElement = async (selector) => { From c96326b760d1b84b3ce692cfa17e0ee8878ebe9f Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Fri, 25 Oct 2024 13:52:00 -0500 Subject: [PATCH 133/418] Cleanup testcases that had hard coded Date() values which override the testcase runner (#3601) cleanup testcases with hard coded Date settings after #3597 --- CHANGELOG.md | 1 + tests/configs/modules/calendar/exdate_la_at_midnight_dst.js | 4 ---- tests/configs/modules/calendar/exdate_la_at_midnight_std.js | 4 ---- tests/configs/modules/calendar/exdate_la_before_midnight.js | 4 ---- tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js | 4 ---- tests/configs/modules/calendar/exdate_syd_at_midnight_std.js | 4 ---- tests/configs/modules/calendar/exdate_syd_before_midnight.js | 4 ---- tests/configs/modules/calendar/rrule_until.js | 4 ---- tests/configs/modules/calendar/sliceMultiDayEvents.js | 4 ---- 9 files changed, 1 insertion(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95c7d112c2..d50d7d153d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ _This release is scheduled to be released on 2025-01-01._ - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) - [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) - [tests] fix electron tests with mock dates, the mock on server side was missing (#3597) +- [tests] fix testcases with hard coded Date.now (#3597) ## [2.29.0] - 2024-10-01 diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js index c9fbb4da1c..b58475752f 100644 --- a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js @@ -30,10 +30,6 @@ let config = { ] }; -Date.now = () => { - return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js index e59c4114f5..e9cab5d772 100644 --- a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js @@ -30,10 +30,6 @@ let config = { ] }; -Date.now = () => { - return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; diff --git a/tests/configs/modules/calendar/exdate_la_before_midnight.js b/tests/configs/modules/calendar/exdate_la_before_midnight.js index c91188d3cc..bfb7218224 100644 --- a/tests/configs/modules/calendar/exdate_la_before_midnight.js +++ b/tests/configs/modules/calendar/exdate_la_before_midnight.js @@ -30,10 +30,6 @@ let config = { ] }; -Date.now = () => { - return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js index edd09798a4..7ce81cd779 100644 --- a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js @@ -30,10 +30,6 @@ let config = { ] }; -Date.now = () => { - return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js index a6b5fdfbb6..06f974f05a 100644 --- a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js @@ -30,10 +30,6 @@ let config = { ] }; -Date.now = () => { - return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; diff --git a/tests/configs/modules/calendar/exdate_syd_before_midnight.js b/tests/configs/modules/calendar/exdate_syd_before_midnight.js index b8b3017da2..f83518ed87 100644 --- a/tests/configs/modules/calendar/exdate_syd_before_midnight.js +++ b/tests/configs/modules/calendar/exdate_syd_before_midnight.js @@ -30,10 +30,6 @@ let config = { ] }; -Date.now = () => { - return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; diff --git a/tests/configs/modules/calendar/rrule_until.js b/tests/configs/modules/calendar/rrule_until.js index 90daa9a3e4..ace727f5bc 100644 --- a/tests/configs/modules/calendar/rrule_until.js +++ b/tests/configs/modules/calendar/rrule_until.js @@ -22,10 +22,6 @@ let config = { ] }; -Date.now = () => { - return new Date("07 Mar 2024 10:38:00 GMT-07:00").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; diff --git a/tests/configs/modules/calendar/sliceMultiDayEvents.js b/tests/configs/modules/calendar/sliceMultiDayEvents.js index 987ccd8945..c46e316eb3 100644 --- a/tests/configs/modules/calendar/sliceMultiDayEvents.js +++ b/tests/configs/modules/calendar/sliceMultiDayEvents.js @@ -22,10 +22,6 @@ let config = { ] }; -Date.now = () => { - return new Date("01 Sept 2024 10:38:00 GMT+2:00").valueOf(); -}; - /*************** DO NOT EDIT THE LINE BELOW ***************/ if (typeof module !== "undefined") { module.exports = config; From 399e2ae1da4ae1aa7bd95f453346ae24218a4ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Mon, 28 Oct 2024 10:32:39 +0100 Subject: [PATCH 134/418] [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3605) This will fix #3576 @FrankBlackMG: I don't use `*env.unique_id` because some others modules can use pm2 too for starting a service and unique_id is the same (this will make confusion) So I check `name` and `pm_id` for found it --- CHANGELOG.md | 2 +- modules/default/updatenotification/update_helper.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d50d7d153d..3158a93016 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Fixed -- [updatenotification] Fix pm2 using detection when pm2 script is in MagicMirror root folder (#3576) +- [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) - [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) - [tests] fix electron tests with mock dates, the mock on server side was missing (#3597) diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index 40d0da8a7b..cc6f2b0adc 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -187,7 +187,9 @@ class Updater { return; } list.forEach((pm) => { - if (pm.pm2_env.version === this.version && pm.pm2_env.status === "online" && pm.pm2_env.pm_cwd.includes(`${this.root_path}`)) { + Log.debug(`[PM2] pm2 name: ${pm.name} -- in process env: ${process.env.name}`) + Log.debug(`[PM2] pm2 pm_id: ${pm.pm_id} -- in process env: ${process.env.pm_id}`) + if (pm.pm2_env.status === "online" && process.env.name === pm.name && +process.env.pm_id === +pm.pm_id) { this.PM2 = pm.name; this.usePM2 = true; Log.info("updatenotification: [PM2] You are using pm2 with", this.PM2); From 9114aefecc2efacd817799419bcc394b216d8e80 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 2 Nov 2024 08:22:27 +0100 Subject: [PATCH 135/418] fix missing basePath (#3620) fixes #3613 wanted to write a test for `basePath` but have no idea at the moment to simulate this without a reverse proxy. Here my test setup for documentation: ```yaml networks: proxy: driver: bridge services: socket-proxy: privileged: true image: tecnativa/docker-socket-proxy:edge container_name: socket-proxy restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock:ro environment: CONTAINERS: 1 ports: - "127.0.0.1:2375:2375" networks: - proxy traefik: image: traefik:latest container_name: traefik restart: unless-stopped user: 1000:1000 command: - "--providers.docker=true" - "--providers.docker.network=traefik_proxy" - "--providers.docker.endpoint=tcp://socket-proxy:2375" - "--entryPoints.http.address=:80" - "--global.sendAnonymousUsage=false" - "--log.level=INFO" - "--api=true" - "--api.dashboard=true" # - "--accessLog=true" # - "--accesslog.fields.defaultmode=keep" # - "--accesslog.fields.headers.defaultmode=keep" networks: - proxy ports: - "80:80" magicmirror: image: karsten13/magicmirror:develop container_name: mm restart: unless-stopped entrypoint: - sleep - infinity networks: - proxy labels: - "traefik.http.services.karsten13.loadbalancer.server.port=8080" - "traefik.http.routers.k13-http.service=karsten13" - "traefik.http.routers.k13-http.entrypoints=http" - "traefik.http.routers.k13-http.rule=Host(`localhost`) && PathPrefix(`/testbasepath`)" - "traefik.http.middlewares.k13-stripprefix.stripprefix.prefixes=/testbasepath" - "traefik.http.routers.k13-http.middlewares=k13-stripprefix" ``` --- CHANGELOG.md | 1 + js/loader.js | 2 +- js/main.js | 2 +- modules/default/newsfeed/newsfeed.js | 2 +- modules/default/utils.js | 10 ++++++---- modules/default/weather/weatherprovider.js | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3158a93016..1ccf50e600 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ _This release is scheduled to be released on 2025-01-01._ - [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) - [tests] fix electron tests with mock dates, the mock on server side was missing (#3597) - [tests] fix testcases with hard coded Date.now (#3597) +- [core] Fix missing `basePath` where `location.host` is used (#3613) ## [2.29.0] - 2024-10-01 diff --git a/js/loader.js b/js/loader.js index 9b42dd8493..e823b0b620 100644 --- a/js/loader.js +++ b/js/loader.js @@ -15,7 +15,7 @@ const Loader = (function () { * @returns {object} with key: values as assembled in js/server_functions.js */ const getEnvVars = async function () { - const res = await fetch(`${location.protocol}//${location.host}/env`); + const res = await fetch(`${location.protocol}//${location.host}${config.basePath}env`); return JSON.parse(await res.text()); }; diff --git a/js/main.js b/js/main.js index 16aaa1b1b4..7c0e9db390 100644 --- a/js/main.js +++ b/js/main.js @@ -608,7 +608,7 @@ const MM = (function () { // if server startup time has changed (which means server was restarted) // the client reloads the mm page try { - const res = await fetch(`${location.protocol}//${location.host}/startup`); + const res = await fetch(`${location.protocol}//${location.host}${config.basePath}startup`); const curr = await res.text(); if (startUp === "") startUp = curr; if (startUp !== curr) { diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index c66f8990d8..95c4cde91e 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -38,7 +38,7 @@ Module.register("newsfeed", { getUrlPrefix (item) { if (item.useCorsProxy) { - return `${location.protocol}//${location.host}/cors?url=`; + return `${location.protocol}//${location.host}${config.basePath}cors?url=`; } else { return ""; } diff --git a/modules/default/utils.js b/modules/default/utils.js index ca0166935c..12d9b36a80 100644 --- a/modules/default/utils.js +++ b/modules/default/utils.js @@ -5,13 +5,14 @@ * @param {boolean} useCorsProxy A flag to indicate * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive + * @param {string} basePath, default / * @returns {Promise} resolved when the fetch is done. The response headers is placed in a headers-property (provided the response does not already contain a headers-property). */ -async function performWebRequest (url, type = "json", useCorsProxy = false, requestHeaders = undefined, expectedResponseHeaders = undefined) { +async function performWebRequest (url, type = "json", useCorsProxy = false, requestHeaders = undefined, expectedResponseHeaders = undefined, basePath = "/") { const request = {}; let requestUrl; if (useCorsProxy) { - requestUrl = getCorsUrl(url, requestHeaders, expectedResponseHeaders); + requestUrl = getCorsUrl(url, requestHeaders, expectedResponseHeaders, basePath); } else { requestUrl = url; request.headers = getHeadersToSend(requestHeaders); @@ -37,13 +38,14 @@ async function performWebRequest (url, type = "json", useCorsProxy = false, requ * @param {string} url the url to fetch from * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive + * @param {string} basePath, default / * @returns {string} to be used as URL when calling CORS-method on server. */ -const getCorsUrl = function (url, requestHeaders, expectedResponseHeaders) { +const getCorsUrl = function (url, requestHeaders, expectedResponseHeaders, basePath = "/") { if (!url || url.length < 1) { throw new Error(`Invalid URL: ${url}`); } else { - let corsUrl = `${location.protocol}//${location.host}/cors?`; + let corsUrl = `${location.protocol}//${location.host}${basePath}cors?`; const requestHeaderString = getRequestHeaderString(requestHeaders); if (requestHeaderString) corsUrl = `${corsUrl}sendheaders=${requestHeaderString}`; diff --git a/modules/default/weather/weatherprovider.js b/modules/default/weather/weatherprovider.js index 3646441094..0fa24a69b0 100644 --- a/modules/default/weather/weatherprovider.js +++ b/modules/default/weather/weatherprovider.js @@ -119,7 +119,7 @@ const WeatherProvider = Class.extend({ return JSON.parse(data); } const useCorsProxy = typeof this.config.useCorsProxy !== "undefined" && this.config.useCorsProxy; - return performWebRequest(url, type, useCorsProxy, requestHeaders, expectedResponseHeaders); + return performWebRequest(url, type, useCorsProxy, requestHeaders, expectedResponseHeaders, config.basePath); } }); From 0aae7717991f6b2e468f969770f773778c14393b Mon Sep 17 00:00:00 2001 From: Veeck Date: Sat, 2 Nov 2024 15:58:20 +0100 Subject: [PATCH 136/418] Update dependencies reported by Dependabot (#3621) ... maybe we should group those dependabot PRs someday (see https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups) --------- Co-authored-by: veeck --- CHANGELOG.md | 2 +- package-lock.json | 463 +++++++++++++++++++++++++--------------------- package.json | 14 +- 3 files changed, 257 insertions(+), 222 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ccf50e600..1fa832c91d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated - [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) -- [core] Update electron dependency to v32 (test electron rebuild) +- [core] Update electron dependency to v32 (test electron rebuild) and other dependencies too - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) - [core] Run and test with node 23 (#3588) diff --git a/package-lock.json b/package-lock.json index 34ef5da3ac..3973fc062a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.13.0", + "eslint": "^9.14.0", "express": "^4.21.1", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -25,14 +25,14 @@ "moment": "^2.30.1", "node-ical": "0.18.0", "pm2": "^5.4.2", - "socket.io": "^4.8.0", + "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.23.5" }, "devDependencies": { - "@eslint/js": "^9.13.0", - "@stylistic/eslint-plugin": "^2.9.0", - "cspell": "^8.15.4", + "@eslint/js": "^9.14.0", + "@stylistic/eslint-plugin": "^2.10.1", + "cspell": "^8.15.5", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.4.3", @@ -42,7 +42,7 @@ "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", - "playwright": "^1.48.1", + "playwright": "^1.48.2", "prettier": "^3.3.3", "sinon": "^19.0.2", "stylelint": "^16.10.0", @@ -53,7 +53,7 @@ "node": ">=20.9.0 <21 || 22 || >=23" }, "optionalDependencies": { - "electron": "^32.2.1" + "electron": "^32.2.2" } }, "node_modules/@altano/repository-tools": { @@ -702,17 +702,18 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.15.4.tgz", - "integrity": "sha512-t5b2JwGeUmzmjl319mCuaeKGxTvmzLLRmrpdHr+ZZGRO4nf7L48Lbe9A6uwNUvsZe0cXohiNXsrrsuzRVXswVA==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.15.5.tgz", + "integrity": "sha512-Su1gnTBbE7ouMQvM4DISUmP6sZiFyQRE+ODvjBzW+c/x9ZLbVp+2hBEEmxFSn5fdZCJzPOMwzwsjlLYykb9iUg==", "dev": true, "license": "MIT", "dependencies": { "@cspell/dict-ada": "^4.0.5", + "@cspell/dict-al": "^1.0.3", "@cspell/dict-aws": "^4.0.7", "@cspell/dict-bash": "^4.1.8", "@cspell/dict-companies": "^3.1.7", - "@cspell/dict-cpp": "^5.1.22", + "@cspell/dict-cpp": "^5.1.23", "@cspell/dict-cryptocurrencies": "^5.0.3", "@cspell/dict-csharp": "^4.0.5", "@cspell/dict-css": "^4.0.16", @@ -724,7 +725,7 @@ "@cspell/dict-en_us": "^4.3.26", "@cspell/dict-en-common-misspellings": "^2.0.7", "@cspell/dict-en-gb": "1.1.33", - "@cspell/dict-filetypes": "^3.0.7", + "@cspell/dict-filetypes": "^3.0.8", "@cspell/dict-flutter": "^1.0.3", "@cspell/dict-fonts": "^4.0.3", "@cspell/dict-fsharp": "^1.0.4", @@ -734,7 +735,7 @@ "@cspell/dict-golang": "^6.0.16", "@cspell/dict-google": "^1.0.4", "@cspell/dict-haskell": "^4.0.4", - "@cspell/dict-html": "^4.0.9", + "@cspell/dict-html": "^4.0.10", "@cspell/dict-html-symbol-entities": "^4.0.3", "@cspell/dict-java": "^5.0.10", "@cspell/dict-julia": "^1.0.4", @@ -743,6 +744,7 @@ "@cspell/dict-lorem-ipsum": "^4.0.3", "@cspell/dict-lua": "^4.0.6", "@cspell/dict-makefile": "^1.0.3", + "@cspell/dict-markdown": "^2.0.7", "@cspell/dict-monkeyc": "^1.0.9", "@cspell/dict-node": "^5.0.4", "@cspell/dict-npm": "^5.1.8", @@ -754,12 +756,12 @@ "@cspell/dict-ruby": "^5.0.7", "@cspell/dict-rust": "^4.0.9", "@cspell/dict-scala": "^5.0.6", - "@cspell/dict-software-terms": "^4.1.11", + "@cspell/dict-software-terms": "^4.1.12", "@cspell/dict-sql": "^2.1.8", "@cspell/dict-svelte": "^1.0.5", "@cspell/dict-swift": "^2.0.4", "@cspell/dict-terraform": "^1.0.5", - "@cspell/dict-typescript": "^3.1.10", + "@cspell/dict-typescript": "^3.1.11", "@cspell/dict-vue": "^3.0.3" }, "engines": { @@ -767,22 +769,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.15.4.tgz", - "integrity": "sha512-solraYhZG4l++NeVCOtpc8DMvwHc46TmJt8DQbgvKtk6wOjTEcFrwKfA6Ei9YKbvyebJlpWMenO3goOll0loYg==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.15.5.tgz", + "integrity": "sha512-yXd7KDBfUkA6y+MrOqK3q/UWorZgLIgyCZoFb0Pj67OU2ZMtgJ1VGFXAdzpKAEgEmdcblyoFzHkleYbg08qS6g==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.15.4" + "@cspell/cspell-types": "8.15.5" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.15.4.tgz", - "integrity": "sha512-WfCmZVFC6mX6vYlf02hWwelcSBTbDQgc5YqY+1miuMk+OHSUAHSACjZId6/a4IAID94xScvFfj7jgrdejUVvIQ==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.15.5.tgz", + "integrity": "sha512-X8QY73060hkR8040jabNJsvydeTG0owpqr9S0QJDdhG1z8uzenNcwR3hfwaIwQq5d6sIKcDFZY5qrO4x6eEAMw==", "dev": true, "license": "MIT", "engines": { @@ -790,9 +792,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.15.4.tgz", - "integrity": "sha512-Zr428o+uUTqywrdKyjluJVnDPVAJEqZ1chQLKIrHggUah1cgs5aQ7rZ+0Rv5euYMlC2idZnP7IL6TDaIib80oA==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.15.5.tgz", + "integrity": "sha512-ejzUGLEwI8TQWXovQzzvAgSNToRrQe3h97YrH2XaB9rZDKkeA7dIBZDQ/OgOfidO+ZAsPIOxdHai3CBzEHYX3A==", "dev": true, "license": "MIT", "dependencies": { @@ -803,9 +805,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.15.4.tgz", - "integrity": "sha512-pXYofnV/V9Y3LZdfFGbmhdxPX/ABjiD3wFjGHt5YhIU9hjVVuvjFlgY7pH2AvRjs4F8xKXv1ReWl44BJOL9gLA==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.15.5.tgz", + "integrity": "sha512-zZJRRvNhvUJntnw8sX4J5gE4uIHpX2oe+Tqs3lu2vRwogadNEXE4QNJbEQyQqgMePgmqULtRdxSBzG4wy4HoQg==", "dev": true, "license": "MIT", "engines": { @@ -813,9 +815,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.15.4.tgz", - "integrity": "sha512-1hDtgYDQVW11zgtrr12EmGW45Deoi7IjZOhzPFLb+3WkhZ46ggWdbrRalWwBolQPDDo6+B2Q6WXz5hdND+Tpwg==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.15.5.tgz", + "integrity": "sha512-bMRq9slD/D0vXckxe9vubG02HXrV4cASo6Ytkaw8rTfxMKpkBgxJWjFWphCFLOCICD71q45fUSg+W5vCp83f/Q==", "dev": true, "license": "MIT", "engines": { @@ -829,6 +831,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@cspell/dict-al": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.0.3.tgz", + "integrity": "sha512-V1HClwlfU/qwSq2Kt+MkqRAsonNu3mxjSCDyGRecdLGIHmh7yeEeaxqRiO/VZ4KP+eVSiSIlbwrb5YNFfxYZbw==", + "dev": true, + "license": "MIT" + }, "node_modules/@cspell/dict-aws": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.7.tgz", @@ -851,9 +860,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "5.1.22", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.22.tgz", - "integrity": "sha512-g1/8P5/Q+xnIc8Js4UtBg3XOhcFrFlFbG3UWVtyEx49YTf0r9eyDtDt1qMMDBZT91pyCwLcAEbwS+4i5PIfNZw==", + "version": "5.1.23", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.23.tgz", + "integrity": "sha512-59VUam6bYWzn50j8FASWWLww0rBPA0PZfjMZBvvt0aqMpkvXzoJPnAAI4eDDSibPWVHKutjpqLmast+uMLHVsQ==", "dev": true, "license": "MIT" }, @@ -1074,6 +1083,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@cspell/dict-markdown": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.7.tgz", + "integrity": "sha512-F9SGsSOokFn976DV4u/1eL4FtKQDSgJHSZ3+haPRU5ki6OEqojxKa8hhj4AUrtNFpmBaJx/WJ4YaEzWqG7hgqg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@cspell/dict-css": "^4.0.16", + "@cspell/dict-html": "^4.0.10", + "@cspell/dict-html-symbol-entities": "^4.0.3", + "@cspell/dict-typescript": "^3.1.11" + } + }, "node_modules/@cspell/dict-monkeyc": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.9.tgz", @@ -1155,9 +1177,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.11.tgz", - "integrity": "sha512-77CTHxWFTVw6tVoMN8WBMrlNW2F2FbgATwD/6vcOuiyrJUmh8klN5ZK3m+yyK3ZzsnaW2Bduoc0fw2Ckcm/riQ==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.12.tgz", + "integrity": "sha512-MHDAK/WlEdMJiDQ6lJ3SF7VogdfJcRXGYWfO4v90rxW8HDVfKDXVk3zpJhjoZGq56ujR1qmeYkQsM6MlB69uJA==", "dev": true, "license": "MIT" }, @@ -1204,9 +1226,9 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.15.4.tgz", - "integrity": "sha512-tr0F6EYN6qtniNvt1Uib+PgYQHeo4dQHXE2Optap+hYTOoQ2VoQ+SwBVjZ+Q2bmSAB0fmOyf0AvgsUtnWIpavw==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.15.5.tgz", + "integrity": "sha512-xfLRVi8zHKCGK1fg1ixXQ0bAlIU9sGm7xfbTmGG8TQt+iaKHVMIlt+XeCAo0eE7aKjIaIfqcC/PCIdUJiODuGA==", "dev": true, "license": "MIT", "dependencies": { @@ -1217,9 +1239,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.15.4.tgz", - "integrity": "sha512-sNl6jr3ym/4151EY76qlI/00HHsiLZBqW7Vb1tqCzsgSg3EpL30ddjr74So6Sg2PN26Yf09hvxGTJzXn1R4aYw==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.15.5.tgz", + "integrity": "sha512-ljEFUp61mw5RWZ3S6ke6rvGKy8m4lZZjRd5KO07RYyGwSeLa4PX9AyTgSzuqXiN9y1BwogD3xolCMfPsMrtZIQ==", "dev": true, "license": "MIT", "engines": { @@ -1227,9 +1249,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.15.4.tgz", - "integrity": "sha512-m5DeQksbhJFqcSYF8Q0Af/WXmXCMAJocCUShkzOXK+uZNXnvhBZN7VyQ9hL+GRzX8JTPEPdVcz2lFyVE5p+LzQ==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.15.5.tgz", + "integrity": "sha512-7VzDAXsJPDXllTIi9mvQwd7PR43TPk1Ix3ocLTZDVNssf1cQbmLiQX6YWk0k8FWGfIPoIMlByw4tTSizRJcTcw==", "dev": true, "license": "MIT", "engines": { @@ -1237,9 +1259,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.15.4.tgz", - "integrity": "sha512-K2oZu/oLQPs5suRpLS8uu04O3YMUioSlEU1D66fRoOxzI5NzLt7i7yMg3HQHjChGa09N5bzqmrVdhmQrRZXwGg==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.15.5.tgz", + "integrity": "sha512-z8q7LUppFiNvytX2qrKDkXcsmOrwjqFf/5RkcpNppDezLrFejaMZu4BEVNcPrFCeS2J04K+uksNL1LYSob8jCg==", "dev": true, "license": "MIT", "engines": { @@ -1432,9 +1454,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -1553,9 +1575,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1583,27 +1605,40 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1618,9 +1653,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz", + "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==", "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -2504,15 +2539,15 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.9.0.tgz", - "integrity": "sha512-OrDyFAYjBT61122MIY1a3SfEgy3YCMgt2vL4eoPmvTwDBwyQhAXurxNQznlRD/jESNfYWfID8Ej+31LljvF7Xg==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.10.1.tgz", + "integrity": "sha512-U+4yzNXElTf9q0kEfnloI9XbOyD4cnEQCxjUI94q0+W++0GAEQvJ/slwEj9lwjDHfGADRSr+Tco/z0XJvmDfCQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.8.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "@typescript-eslint/utils": "^8.12.2", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -2760,14 +2795,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz", - "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", + "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1" + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2778,9 +2813,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz", - "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", + "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", "dev": true, "license": "MIT", "engines": { @@ -2792,14 +2827,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz", - "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", + "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2821,16 +2856,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz", - "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", + "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.1", - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/typescript-estree": "8.8.1" + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/typescript-estree": "8.12.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2844,13 +2879,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz", - "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", + "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/types": "8.12.2", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2888,9 +2923,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4270,30 +4305,30 @@ } }, "node_modules/cspell": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.15.4.tgz", - "integrity": "sha512-hUOxcwmNWuHzVeGHyN5v/T9MkyCE5gi0mvatxsM794B2wOuR1ZORgjZH62P2HY1uBkXe/x5C6ITWrSyh0WgAcg==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.15.5.tgz", + "integrity": "sha512-Vp1WI6axghVvenZS7GUlsZf6JFF7jDXdV5f4nXWjrZLbTrH+wbnFEO2mg+QJWa4IN35igjNYeu9TbA9/EGJzog==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.15.4", - "@cspell/cspell-pipe": "8.15.4", - "@cspell/cspell-types": "8.15.4", - "@cspell/dynamic-import": "8.15.4", - "@cspell/url": "8.15.4", + "@cspell/cspell-json-reporter": "8.15.5", + "@cspell/cspell-pipe": "8.15.5", + "@cspell/cspell-types": "8.15.5", + "@cspell/dynamic-import": "8.15.5", + "@cspell/url": "8.15.5", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^12.1.0", - "cspell-dictionary": "8.15.4", - "cspell-gitignore": "8.15.4", - "cspell-glob": "8.15.4", - "cspell-io": "8.15.4", - "cspell-lib": "8.15.4", + "cspell-dictionary": "8.15.5", + "cspell-gitignore": "8.15.5", + "cspell-glob": "8.15.5", + "cspell-io": "8.15.5", + "cspell-lib": "8.15.5", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", "semver": "^7.6.3", - "tinyglobby": "^0.2.9" + "tinyglobby": "^0.2.10" }, "bin": { "cspell": "bin.mjs", @@ -4307,13 +4342,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.15.4.tgz", - "integrity": "sha512-vUgikQTRkRMTdkZqSs7F2cTdPpX61cTjr/9L/VCkXkbW38ObCr4650ioiF1Wq3zDF3Gy2bc4ECTpD2PZUXX5SA==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.15.5.tgz", + "integrity": "sha512-16XBjAlUWO46uEuUKHQvSeiU7hQzG9Pqg6lwKQOyZ/rVLZyihk7JGtnWuG83BbW0RFokB/BcgT1q6OegWJiEZw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.15.4", + "@cspell/cspell-types": "8.15.5", "comment-json": "^4.2.5", "yaml": "^2.6.0" }, @@ -4335,15 +4370,15 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.15.4.tgz", - "integrity": "sha512-8+p/l9Saac7qyCbqtELneDoT7CwHu9gYmnI8uXMu34/lPGjhVhy10ZeI0+t1djaO2YyASK400YFKq5uP/5KulA==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.15.5.tgz", + "integrity": "sha512-L+4MD3KItFGsxR8eY2ed6InsD7hZU1TIAeV2V4sG0wIbUXJXbPFxBTNZJrPLxTzAeCutHmkZwAl4ZCGu18bgtw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.4", - "@cspell/cspell-types": "8.15.4", - "cspell-trie-lib": "8.15.4", + "@cspell/cspell-pipe": "8.15.5", + "@cspell/cspell-types": "8.15.5", + "cspell-trie-lib": "8.15.5", "fast-equals": "^5.0.1" }, "engines": { @@ -4351,15 +4386,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.15.4.tgz", - "integrity": "sha512-9n5PpQ8gEf8YcvEtoZGZ2Ma6wnqSFkD2GrmyjISy39DfIX/jNLN7GX2wJm6OD2P4FjXer95ypmIb/JWTlfmbTw==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.15.5.tgz", + "integrity": "sha512-z5T0Xswfiu2NbkoVdf6uwEWzOgxCBb3L8kwB6lxzK5iyQDW2Bqlk+5b6KQaY38OtjTjJ9zzIJfFN3MfFlMFd3A==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.15.4", - "cspell-glob": "8.15.4", - "cspell-io": "8.15.4", + "@cspell/url": "8.15.5", + "cspell-glob": "8.15.5", + "cspell-io": "8.15.5", "find-up-simple": "^1.0.0" }, "bin": { @@ -4370,13 +4405,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.15.4.tgz", - "integrity": "sha512-TTfRRHRAN+PN9drIz4MAEgKKYnPThBOlPMdFddyuisvU33Do1sPAnqkkOjTEFdi3jAA5KwnSva68SVH6IzzMBQ==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.15.5.tgz", + "integrity": "sha512-VpfP16bRbkHEyGGjf6/EifFxETfS7lpcHbYt1tRi6VhCv1FTMqbB7H7Aw+DQkDezOUN8xdw0gYe/fk5AJGOBDg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.15.4", + "@cspell/url": "8.15.5", "micromatch": "^4.0.8" }, "engines": { @@ -4384,14 +4419,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.15.4.tgz", - "integrity": "sha512-MKiKyYi05mRtXOxPoTv3Ksi0GwYLiK84Uq0C+5PaMrnIjXeed0bsddSFXCT+7ywFJc7PdjhTtz0M/9WWK3UgbA==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.15.5.tgz", + "integrity": "sha512-2YnlSATtWHNL6cgx1qmTsY5ZO0zu8VdEmfcLQKgHr67T7atLRUnWAlmh06WMLd5qqp8PpWNPaOJF2prEYAXsUA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.4", - "@cspell/cspell-types": "8.15.4" + "@cspell/cspell-pipe": "8.15.5", + "@cspell/cspell-types": "8.15.5" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4401,42 +4436,42 @@ } }, "node_modules/cspell-io": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.15.4.tgz", - "integrity": "sha512-rXIEREPTFV9dwwg4EKfvzqlCNOvT6910AYED5YrSt8Y68usRJ9lbqdx0BrDndVCd33bp1o+9JBfHuRiFIQC81g==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.15.5.tgz", + "integrity": "sha512-6kBK+EGTG9hiUDfB55r3xbhc7YUA5vJTXoc65pe9PXd4vgXXfrPRuy+5VRtvgSMoQj59oWOQw3ZqTAR95gbGnw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.15.4", - "@cspell/url": "8.15.4" + "@cspell/cspell-service-bus": "8.15.5", + "@cspell/url": "8.15.5" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.15.4.tgz", - "integrity": "sha512-iLp/625fvCyFFxSyZYLMgqHIKcrhN4hT7Hw5+ySa38Bp/OfA81ANqWHpsDQ0bGsALTRn/DHBpQYj4xCW/aN9tw==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.15.5.tgz", + "integrity": "sha512-DGieMWc82ouHb6Rq2LRKAlG4ExeQL1D5uvemgaouVHMZq4GvPtVaTwA6qHhw772/5z665oOVsRCicYbDtP4V3w==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.15.4", - "@cspell/cspell-pipe": "8.15.4", - "@cspell/cspell-resolver": "8.15.4", - "@cspell/cspell-types": "8.15.4", - "@cspell/dynamic-import": "8.15.4", - "@cspell/filetypes": "8.15.4", - "@cspell/strong-weak-map": "8.15.4", - "@cspell/url": "8.15.4", + "@cspell/cspell-bundled-dicts": "8.15.5", + "@cspell/cspell-pipe": "8.15.5", + "@cspell/cspell-resolver": "8.15.5", + "@cspell/cspell-types": "8.15.5", + "@cspell/dynamic-import": "8.15.5", + "@cspell/filetypes": "8.15.5", + "@cspell/strong-weak-map": "8.15.5", + "@cspell/url": "8.15.5", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.15.4", - "cspell-dictionary": "8.15.4", - "cspell-glob": "8.15.4", - "cspell-grammar": "8.15.4", - "cspell-io": "8.15.4", - "cspell-trie-lib": "8.15.4", + "cspell-config-lib": "8.15.5", + "cspell-dictionary": "8.15.5", + "cspell-glob": "8.15.5", + "cspell-grammar": "8.15.5", + "cspell-io": "8.15.5", + "cspell-trie-lib": "8.15.5", "env-paths": "^3.0.0", "fast-equals": "^5.0.1", "gensequence": "^7.0.0", @@ -4451,14 +4486,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.15.4", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.15.4.tgz", - "integrity": "sha512-sg9klsNHyrfos0Boiio+qy5d6fI9cCNjBqFYrNxvpKpwZ4gEzDzjgEKdZY1C76RD2KoBQ8I1NF5YcGc0+hhhCw==", + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.15.5.tgz", + "integrity": "sha512-DAEkp51aFgpp9DFuJkNki0kVm2SVR1Hp0hD3Pnta7S4X2h5424TpTVVPltAIWtcdxRLGbX6N2x26lTI4K/YfpQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.4", - "@cspell/cspell-types": "8.15.4", + "@cspell/cspell-pipe": "8.15.5", + "@cspell/cspell-types": "8.15.5", "gensequence": "^7.0.0" }, "engines": { @@ -4926,9 +4961,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "32.2.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.1.tgz", - "integrity": "sha512-GCPI/5hU34pPcNltNpz+uylhhuTm9BM0N8RmrbVgaWBodLSmmcCkvpgN0BseKhO6IwQOPzWaovrcZ/nPIpfGaQ==", + "version": "32.2.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.2.tgz", + "integrity": "sha512-c7TRE42JcgEmJ4elJyCdKk/2os0UX7YMkRDeXBkxFEoM34iX1/2x+c5T9PgeroKz8FEG7omRU5TvjulqVtXvdw==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4991,9 +5026,9 @@ } }, "node_modules/engine.io": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.1.tgz", - "integrity": "sha512-NEpDCw9hrvBW+hVEOK4T7v0jFJ++KgtPl4jKFwsZVfG1XhS0dCrSb3VMb9gPAd7VAdW52VT1EnaNiU2vM8C0og==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", "license": "MIT", "dependencies": { "@types/cookie": "^0.4.1", @@ -5001,7 +5036,7 @@ "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~0.4.1", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", @@ -5021,9 +5056,9 @@ } }, "node_modules/engine.io/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -5350,21 +5385,21 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -5372,9 +5407,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5614,9 +5649,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -5630,9 +5665,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5711,14 +5746,14 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6103,9 +6138,9 @@ } }, "node_modules/fdir": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.0.tgz", - "integrity": "sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -9950,13 +9985,13 @@ } }, "node_modules/playwright": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", - "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.48.1" + "playwright-core": "1.48.2" }, "bin": { "playwright": "cli.js" @@ -9969,9 +10004,9 @@ } }, "node_modules/playwright-core": { - "version": "1.48.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", - "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -11251,9 +11286,9 @@ } }, "node_modules/socket.io": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", - "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "license": "MIT", "dependencies": { "accepts": "~1.3.4", @@ -12163,13 +12198,13 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.9.tgz", - "integrity": "sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", + "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.0", + "fdir": "^6.4.2", "picomatch": "^4.0.2" }, "engines": { @@ -12261,9 +12296,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index dcc8912b99..ad47d7ff1c 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "ansis": "^3.3.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.13.0", + "eslint": "^9.14.0", "express": "^4.21.1", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -76,14 +76,14 @@ "moment": "^2.30.1", "node-ical": "0.18.0", "pm2": "^5.4.2", - "socket.io": "^4.8.0", + "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.23.5" }, "devDependencies": { - "@eslint/js": "^9.13.0", - "@stylistic/eslint-plugin": "^2.9.0", - "cspell": "^8.15.4", + "@eslint/js": "^9.14.0", + "@stylistic/eslint-plugin": "^2.10.1", + "cspell": "^8.15.5", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.4.3", @@ -93,7 +93,7 @@ "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", - "playwright": "^1.48.1", + "playwright": "^1.48.2", "prettier": "^3.3.3", "sinon": "^19.0.2", "stylelint": "^16.10.0", @@ -101,7 +101,7 @@ "stylelint-prettier": "^5.0.2" }, "optionalDependencies": { - "electron": "^32.2.1" + "electron": "^32.2.2" }, "engines": { "node": ">=20.9.0 <21 || 22 || >=23" From 6ce3622c6113f6475d851ada488a09c50c50f2fc Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 3 Nov 2024 21:49:00 +0100 Subject: [PATCH 137/418] Add spelling check to GitHub workflow (#3623) Besides updating cspell and handling spelling issues, the important change is adding the spelling check to the GitHub workflow. I'm not sure if it will bother us too much when people create PRs. But I wanted to give it a try. Or do you have any other ideas on how we can run the spelling check on a regular basis? --- .github/workflows/spellcheck.yaml | 31 +++++ CHANGELOG.md | 7 +- cspell.config.json | 9 ++ package-lock.json | 218 +++++++++++++++--------------- package.json | 2 +- 5 files changed, 154 insertions(+), 113 deletions(-) create mode 100644 .github/workflows/spellcheck.yaml diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml new file mode 100644 index 0000000000..78a13cdbe8 --- /dev/null +++ b/.github/workflows/spellcheck.yaml @@ -0,0 +1,31 @@ +# This workflow will run a spellcheck on the codebase. +# It runs a few days before each release. At 00:00 on day-of-month 27 in March, June, September, and December. + +name: Run Spellcheck + +on: + schedule: + - cron: "0 0 27 3,6,9,12 *" + +permissions: + contents: read + +jobs: + spellcheck: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: develop + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + check-latest: true + cache: "npm" + - name: Install dependencies + run: | + npm run install-mm:dev + - name: Run Spellcheck + run: npm run test:spellcheck diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fa832c91d..6f664fad3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ _This release is scheduled to be released on 2025-01-01._ - [core] Add wayland and windows start options to `package.json` (#3594) - [linter] re-added `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [docs] Added step for npm publishing in release process (#3595) +- [core] Add GitHub workflow to run spellcheck a few days before each release. ### Removed @@ -30,9 +31,9 @@ _This release is scheduled to be released on 2025-01-01._ - [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) -- [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) -- [tests] fix electron tests with mock dates, the mock on server side was missing (#3597) -- [tests] fix testcases with hard coded Date.now (#3597) +- [weather] Changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) +- [tests] Fix electron tests with mock dates, the mock on server side was missing (#3597) +- [tests] Fix test cases with hard coded Date.now (#3597) - [core] Fix missing `basePath` where `location.host` is used (#3613) ## [2.29.0] - 2024-10-01 diff --git a/cspell.config.json b/cspell.config.json index 16addf44a9..ba8aa98e14 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -38,6 +38,7 @@ "currentweather", "CUSTOMCSS", "customregions", + "cxmj", "Cymraeg", "dariom", "darksky", @@ -48,6 +49,8 @@ "DAYBEFOREYESTERDAY", "defaultmodules", "dgoth", + "dkallen", + "drivelist", "DTEND", "Duffman", "earlman", @@ -79,6 +82,7 @@ "fullday", "fullscreen", "Gevoelstemperatuur", + "GHSA", "ghsas", "grenagit", "Hirschberger", @@ -92,6 +96,7 @@ "jakemulley", "jakobsarwary", "jalibu", + "jargordon", "jetson", "jkriegshauser", "jsdocs", @@ -112,8 +117,10 @@ "krekos", "Kristjan", "krukle", + "Landis", "larryare", "letsencrypt", + "libgpiod", "Lightspeed", "locationforecast", "lockstring", @@ -162,6 +169,7 @@ "psieg", "radokristof", "rajniszp", + "rebuilded", "Reis", "rejas", "Resig", @@ -172,6 +180,7 @@ "sdetweil", "sendheaders", "serveronly", + "skpanagiotis", "SMHI", "Snille", "socketclient", diff --git a/package-lock.json b/package-lock.json index 3973fc062a..9de1ee5089 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,7 @@ "devDependencies": { "@eslint/js": "^9.14.0", "@stylistic/eslint-plugin": "^2.10.1", - "cspell": "^8.15.5", + "cspell": "^8.15.7", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.4.3", @@ -702,9 +702,9 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.15.5.tgz", - "integrity": "sha512-Su1gnTBbE7ouMQvM4DISUmP6sZiFyQRE+ODvjBzW+c/x9ZLbVp+2hBEEmxFSn5fdZCJzPOMwzwsjlLYykb9iUg==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.15.7.tgz", + "integrity": "sha512-lNbrlHhDnOWCJh/vNCliZJz4X1KMEZqWJZpTgmdPrEGS9ZyfEiCmZyoQzw+fauC5Xo7dwd2KdS9VMHftAJqMPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -713,7 +713,7 @@ "@cspell/dict-aws": "^4.0.7", "@cspell/dict-bash": "^4.1.8", "@cspell/dict-companies": "^3.1.7", - "@cspell/dict-cpp": "^5.1.23", + "@cspell/dict-cpp": "^6.0.0", "@cspell/dict-cryptocurrencies": "^5.0.3", "@cspell/dict-csharp": "^4.0.5", "@cspell/dict-css": "^4.0.16", @@ -747,7 +747,7 @@ "@cspell/dict-markdown": "^2.0.7", "@cspell/dict-monkeyc": "^1.0.9", "@cspell/dict-node": "^5.0.4", - "@cspell/dict-npm": "^5.1.8", + "@cspell/dict-npm": "^5.1.9", "@cspell/dict-php": "^4.0.13", "@cspell/dict-powershell": "^5.0.13", "@cspell/dict-public-licenses": "^2.0.11", @@ -760,7 +760,7 @@ "@cspell/dict-sql": "^2.1.8", "@cspell/dict-svelte": "^1.0.5", "@cspell/dict-swift": "^2.0.4", - "@cspell/dict-terraform": "^1.0.5", + "@cspell/dict-terraform": "^1.0.6", "@cspell/dict-typescript": "^3.1.11", "@cspell/dict-vue": "^3.0.3" }, @@ -769,22 +769,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.15.5.tgz", - "integrity": "sha512-yXd7KDBfUkA6y+MrOqK3q/UWorZgLIgyCZoFb0Pj67OU2ZMtgJ1VGFXAdzpKAEgEmdcblyoFzHkleYbg08qS6g==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.15.7.tgz", + "integrity": "sha512-kOcJaThztX1A8jkALBiAyp8dWrHPMuDOXki8Q5ZG1dL25wKsAnPyqflXhXg6Up4VGVIkkgy1S3T0Q/i+G5f12w==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.15.5" + "@cspell/cspell-types": "8.15.7" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.15.5.tgz", - "integrity": "sha512-X8QY73060hkR8040jabNJsvydeTG0owpqr9S0QJDdhG1z8uzenNcwR3hfwaIwQq5d6sIKcDFZY5qrO4x6eEAMw==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.15.7.tgz", + "integrity": "sha512-EyVSJPqJFrDA9Sj4Nzx13vytloMS0V3HaevhqMFLHJ53QNz/ZP7vuECbXApRAJwLonuToJBvY3b9xzB6eEhU/A==", "dev": true, "license": "MIT", "engines": { @@ -792,9 +792,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.15.5.tgz", - "integrity": "sha512-ejzUGLEwI8TQWXovQzzvAgSNToRrQe3h97YrH2XaB9rZDKkeA7dIBZDQ/OgOfidO+ZAsPIOxdHai3CBzEHYX3A==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.15.7.tgz", + "integrity": "sha512-9RPZ5VwjYPYLTLWkoPGHqV3Kuai5QwTWgZJW3Yk2GgJkxss/LDsXME+9CalPcPBQpnCIBEOtE2DjDQbFjAiMnA==", "dev": true, "license": "MIT", "dependencies": { @@ -805,9 +805,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.15.5.tgz", - "integrity": "sha512-zZJRRvNhvUJntnw8sX4J5gE4uIHpX2oe+Tqs3lu2vRwogadNEXE4QNJbEQyQqgMePgmqULtRdxSBzG4wy4HoQg==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.15.7.tgz", + "integrity": "sha512-kL+1+K4VApdwZccGlg7Vjmh4CzzjoT+G556/gErdESQFPY0y9/4OPPVKLrFkbEDODtp9Py7aTRHdhl6w1xxCCw==", "dev": true, "license": "MIT", "engines": { @@ -815,9 +815,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.15.5.tgz", - "integrity": "sha512-bMRq9slD/D0vXckxe9vubG02HXrV4cASo6Ytkaw8rTfxMKpkBgxJWjFWphCFLOCICD71q45fUSg+W5vCp83f/Q==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.15.7.tgz", + "integrity": "sha512-QMbGJsUXTdV8/V9Gsc/kBgdkBwm4hvcChhQf6KE9yeg3CZlbd95NkFJuSiqp1phJOWMTzHCZ0Ro7v7P/LGKdVA==", "dev": true, "license": "MIT", "engines": { @@ -860,9 +860,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "5.1.23", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.1.23.tgz", - "integrity": "sha512-59VUam6bYWzn50j8FASWWLww0rBPA0PZfjMZBvvt0aqMpkvXzoJPnAAI4eDDSibPWVHKutjpqLmast+uMLHVsQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.0.tgz", + "integrity": "sha512-z9Mv3/Ool19aw/kl1C+NmLdHF5WN6XCDmP4UkM/sYIfBO4WMUmrhiKiqK/pzSih9jyC5C2AuxujtB/IdHmyfVg==", "dev": true, "license": "MIT" }, @@ -1111,9 +1111,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.8.tgz", - "integrity": "sha512-AJELYXeB4fQdIoNfmuaQxB1Hli3cX6XPsQCjfBxlu0QYXhrjB/IrCLLQAjWIywDqJiWyGUFTz4DqaANm8C/r9Q==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.9.tgz", + "integrity": "sha512-ZH10gepefFee03SYQXH4mMmYbI3iwwEg5+B0ujsUohGJR789SyieelY0xPiDeh1y9gcQAp62k1QxbUwpcCYe5A==", "dev": true, "license": "MIT" }, @@ -1205,9 +1205,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-terraform": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.5.tgz", - "integrity": "sha512-qH3epPB2d6d5w1l4hR2OsnN8qDQ4P0z6oDB7+YiNH+BoECXv4Z38MIV1H8cxIzD2wkzkt2JTcFYaVW72MDZAlg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.6.tgz", + "integrity": "sha512-Sqm5vGbXuI9hCFcr4w6xWf4Y25J9SdleE/IqfM6RySPnk8lISEmVdax4k6+Kinv9qaxyvnIbUUN4WFLWcBPQAg==", "dev": true, "license": "MIT" }, @@ -1226,9 +1226,9 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.15.5.tgz", - "integrity": "sha512-xfLRVi8zHKCGK1fg1ixXQ0bAlIU9sGm7xfbTmGG8TQt+iaKHVMIlt+XeCAo0eE7aKjIaIfqcC/PCIdUJiODuGA==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.15.7.tgz", + "integrity": "sha512-qFlVisdP2lvFcS4Kre4Dl+f4Y7U9w/Y7IQAS+XXl5KlInImMaYhNUDEru8DoUPQHYsXKAPJsu/Y2JloHNE502Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1239,9 +1239,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.15.5.tgz", - "integrity": "sha512-ljEFUp61mw5RWZ3S6ke6rvGKy8m4lZZjRd5KO07RYyGwSeLa4PX9AyTgSzuqXiN9y1BwogD3xolCMfPsMrtZIQ==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.15.7.tgz", + "integrity": "sha512-MeP6gh8Om9vHSxYoYey2BFCib4m+vEyMLQCSub1Gk+uXiJjj1l/S5MFWM9zHhjGBBNNdvuopuUKP6Gcgcw+3Cw==", "dev": true, "license": "MIT", "engines": { @@ -1249,9 +1249,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.15.5.tgz", - "integrity": "sha512-7VzDAXsJPDXllTIi9mvQwd7PR43TPk1Ix3ocLTZDVNssf1cQbmLiQX6YWk0k8FWGfIPoIMlByw4tTSizRJcTcw==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.15.7.tgz", + "integrity": "sha512-SGlkhRnHXoBzLY2SxVppMsREhyaDHpyXQrPDUfsCnyG5DC8UVmXnTVQp9c2kqhAZw6g6g6V7uoqTLqJQmrWOFQ==", "dev": true, "license": "MIT", "engines": { @@ -1259,9 +1259,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.15.5.tgz", - "integrity": "sha512-z8q7LUppFiNvytX2qrKDkXcsmOrwjqFf/5RkcpNppDezLrFejaMZu4BEVNcPrFCeS2J04K+uksNL1LYSob8jCg==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.15.7.tgz", + "integrity": "sha512-IzBsrl54TyO5Ezbyr25ZOUZA3Sg2UbSWDZZar9jSRAsoikcsoy1ivgSumcYJYOH8HAtanfr8YGN0+8UF/kbYqg==", "dev": true, "license": "MIT", "engines": { @@ -4305,25 +4305,25 @@ } }, "node_modules/cspell": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.15.5.tgz", - "integrity": "sha512-Vp1WI6axghVvenZS7GUlsZf6JFF7jDXdV5f4nXWjrZLbTrH+wbnFEO2mg+QJWa4IN35igjNYeu9TbA9/EGJzog==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.15.7.tgz", + "integrity": "sha512-68Bs/brr31M0W6tljNCgHcz09xdfDnRobyyRQJ8z0ZrovfTHHj9gSQldJJt5Fq3AMlCeYbECnKPsY9DkzIP1sQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.15.5", - "@cspell/cspell-pipe": "8.15.5", - "@cspell/cspell-types": "8.15.5", - "@cspell/dynamic-import": "8.15.5", - "@cspell/url": "8.15.5", + "@cspell/cspell-json-reporter": "8.15.7", + "@cspell/cspell-pipe": "8.15.7", + "@cspell/cspell-types": "8.15.7", + "@cspell/dynamic-import": "8.15.7", + "@cspell/url": "8.15.7", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^12.1.0", - "cspell-dictionary": "8.15.5", - "cspell-gitignore": "8.15.5", - "cspell-glob": "8.15.5", - "cspell-io": "8.15.5", - "cspell-lib": "8.15.5", + "cspell-dictionary": "8.15.7", + "cspell-gitignore": "8.15.7", + "cspell-glob": "8.15.7", + "cspell-io": "8.15.7", + "cspell-lib": "8.15.7", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", @@ -4342,13 +4342,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.15.5.tgz", - "integrity": "sha512-16XBjAlUWO46uEuUKHQvSeiU7hQzG9Pqg6lwKQOyZ/rVLZyihk7JGtnWuG83BbW0RFokB/BcgT1q6OegWJiEZw==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.15.7.tgz", + "integrity": "sha512-orxPKLMLQjk+Px1wlZdMElsHlKFGiwlXhQcG/36hODFKsle9DnGqVefOjH6aWFO5DyDF+Z678leiO2F30wtXEQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.15.5", + "@cspell/cspell-types": "8.15.7", "comment-json": "^4.2.5", "yaml": "^2.6.0" }, @@ -4370,15 +4370,15 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.15.5.tgz", - "integrity": "sha512-L+4MD3KItFGsxR8eY2ed6InsD7hZU1TIAeV2V4sG0wIbUXJXbPFxBTNZJrPLxTzAeCutHmkZwAl4ZCGu18bgtw==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.15.7.tgz", + "integrity": "sha512-jmOk9kJ/bsVFg0/ObnNMUHA3wPgHb4eGFx6yF+Lx28eYx9j2XkLZuXXicbNyOWqJ9AzP0CavPmHwAS6bJrxD3Q==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.5", - "@cspell/cspell-types": "8.15.5", - "cspell-trie-lib": "8.15.5", + "@cspell/cspell-pipe": "8.15.7", + "@cspell/cspell-types": "8.15.7", + "cspell-trie-lib": "8.15.7", "fast-equals": "^5.0.1" }, "engines": { @@ -4386,15 +4386,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.15.5.tgz", - "integrity": "sha512-z5T0Xswfiu2NbkoVdf6uwEWzOgxCBb3L8kwB6lxzK5iyQDW2Bqlk+5b6KQaY38OtjTjJ9zzIJfFN3MfFlMFd3A==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.15.7.tgz", + "integrity": "sha512-LxX/PS3z6UqXHUqw3wIB1OJwZrexxKn/EUertYcLce/K2M2wLsUA+uneU5EvUqzkM6vwMHvdv/hl/tROFQJIbw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.15.5", - "cspell-glob": "8.15.5", - "cspell-io": "8.15.5", + "@cspell/url": "8.15.7", + "cspell-glob": "8.15.7", + "cspell-io": "8.15.7", "find-up-simple": "^1.0.0" }, "bin": { @@ -4405,13 +4405,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.15.5.tgz", - "integrity": "sha512-VpfP16bRbkHEyGGjf6/EifFxETfS7lpcHbYt1tRi6VhCv1FTMqbB7H7Aw+DQkDezOUN8xdw0gYe/fk5AJGOBDg==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.15.7.tgz", + "integrity": "sha512-BI0mF0IWqVxEGpRkH2kBgT9Ey7lAMlEhvY/zKCy3JQY5PSn/qI3RhlsXrsTDt2RJxhicuzJIe3KiNdUKXQM0Ig==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.15.5", + "@cspell/url": "8.15.7", "micromatch": "^4.0.8" }, "engines": { @@ -4419,14 +4419,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.15.5.tgz", - "integrity": "sha512-2YnlSATtWHNL6cgx1qmTsY5ZO0zu8VdEmfcLQKgHr67T7atLRUnWAlmh06WMLd5qqp8PpWNPaOJF2prEYAXsUA==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.15.7.tgz", + "integrity": "sha512-g7ocpFG9Gam4+b2bHrqhmXVaFNV4BjFjVnaEKS3RoqcMjJuQUa9wD5HWO6AvBJeJf/auvQS7CgmumQqSo9xxCw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.5", - "@cspell/cspell-types": "8.15.5" + "@cspell/cspell-pipe": "8.15.7", + "@cspell/cspell-types": "8.15.7" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4436,42 +4436,42 @@ } }, "node_modules/cspell-io": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.15.5.tgz", - "integrity": "sha512-6kBK+EGTG9hiUDfB55r3xbhc7YUA5vJTXoc65pe9PXd4vgXXfrPRuy+5VRtvgSMoQj59oWOQw3ZqTAR95gbGnw==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.15.7.tgz", + "integrity": "sha512-GEnMPu+xyyHTal2QdCbuRrPUEpjCYo0mF/Tz/YkcZNJdn0sj6MylH2EA0A+d6WzheRpw9ijd1dRvq3h5jJgmuQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.15.5", - "@cspell/url": "8.15.5" + "@cspell/cspell-service-bus": "8.15.7", + "@cspell/url": "8.15.7" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.15.5.tgz", - "integrity": "sha512-DGieMWc82ouHb6Rq2LRKAlG4ExeQL1D5uvemgaouVHMZq4GvPtVaTwA6qHhw772/5z665oOVsRCicYbDtP4V3w==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.15.7.tgz", + "integrity": "sha512-RxxPEymTENc76f8ny1LN+aPyR4Efwyah8m5c20xOwxD/lAhBrNs2PPE1taEMPkI7WTXWjKm4D0DJpZatD+W6pg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.15.5", - "@cspell/cspell-pipe": "8.15.5", - "@cspell/cspell-resolver": "8.15.5", - "@cspell/cspell-types": "8.15.5", - "@cspell/dynamic-import": "8.15.5", - "@cspell/filetypes": "8.15.5", - "@cspell/strong-weak-map": "8.15.5", - "@cspell/url": "8.15.5", + "@cspell/cspell-bundled-dicts": "8.15.7", + "@cspell/cspell-pipe": "8.15.7", + "@cspell/cspell-resolver": "8.15.7", + "@cspell/cspell-types": "8.15.7", + "@cspell/dynamic-import": "8.15.7", + "@cspell/filetypes": "8.15.7", + "@cspell/strong-weak-map": "8.15.7", + "@cspell/url": "8.15.7", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.15.5", - "cspell-dictionary": "8.15.5", - "cspell-glob": "8.15.5", - "cspell-grammar": "8.15.5", - "cspell-io": "8.15.5", - "cspell-trie-lib": "8.15.5", + "cspell-config-lib": "8.15.7", + "cspell-dictionary": "8.15.7", + "cspell-glob": "8.15.7", + "cspell-grammar": "8.15.7", + "cspell-io": "8.15.7", + "cspell-trie-lib": "8.15.7", "env-paths": "^3.0.0", "fast-equals": "^5.0.1", "gensequence": "^7.0.0", @@ -4486,14 +4486,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.15.5.tgz", - "integrity": "sha512-DAEkp51aFgpp9DFuJkNki0kVm2SVR1Hp0hD3Pnta7S4X2h5424TpTVVPltAIWtcdxRLGbX6N2x26lTI4K/YfpQ==", + "version": "8.15.7", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.15.7.tgz", + "integrity": "sha512-b8WWWOx5wfhT72K43fk3dMoE4H2c1UpbCEVB2JXJ5scub7mjqoT/CRiZlw1IDfQT6BmUtJuD7sZ8NRFanF9hQA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.5", - "@cspell/cspell-types": "8.15.5", + "@cspell/cspell-pipe": "8.15.7", + "@cspell/cspell-types": "8.15.7", "gensequence": "^7.0.0" }, "engines": { diff --git a/package.json b/package.json index ad47d7ff1c..a9e7e61fa5 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "devDependencies": { "@eslint/js": "^9.14.0", "@stylistic/eslint-plugin": "^2.10.1", - "cspell": "^8.15.5", + "cspell": "^8.15.7", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.4.3", From 7e6349c0934c640bb8cfddf67c1b9bf9f3a5b1a0 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Mon, 4 Nov 2024 10:41:48 -0600 Subject: [PATCH 138/418] Fix compliments croner (#3625) croner changed the filename we need to use in the latest version fix the alias table in vendor/vendor.js fixes #3624 --- CHANGELOG.md | 1 + vendor/package.json | 2 +- vendor/vendor.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f664fad3c..579eff945d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ _This release is scheduled to be released on 2025-01-01._ - [tests] Fix electron tests with mock dates, the mock on server side was missing (#3597) - [tests] Fix test cases with hard coded Date.now (#3597) - [core] Fix missing `basePath` where `location.host` is used (#3613) +- [compliments] croner library changed filenames used in latest version (#3624) ## [2.29.0] - 2024-10-01 diff --git a/vendor/package.json b/vendor/package.json index 58780a2c93..e31453747c 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -13,7 +13,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.6.0", "animate.css": "^4.1.1", - "croner": "^8.1.2", + "croner": "^9.0.0", "moment": "^2.30.1", "moment-timezone": "^0.5.46", "nunjucks": "^3.2.4", diff --git a/vendor/vendor.js b/vendor/vendor.js index ee3f0bb777..e808efdd1e 100644 --- a/vendor/vendor.js +++ b/vendor/vendor.js @@ -6,7 +6,7 @@ const vendor = { "font-awesome.css": "css/font-awesome.css", "nunjucks.js": "node_modules/nunjucks/browser/nunjucks.min.js", "suncalc.js": "node_modules/suncalc/suncalc.js", - "croner.js": "node_modules/croner/dist/croner.umd.min.js" + "croner.js": "node_modules/croner/dist/croner.umd.js" }; if (typeof module !== "undefined") { From b250cfa0ee209ea4d358267cc2be2d7d44a86c2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:50:09 +0100 Subject: [PATCH 139/418] Bump croner from 8.1.2 to 9.0.0 in /vendor (#3614) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [croner](https://github.com/hexagon/croner) from 8.1.2 to 9.0.0.
Release notes

Sourced from croner's releases.

9.0.0

Croner 9.0.0

This major release brings significant changes to Croner, improving consistency, fixing bugs, and modernizing the codebase.

Changes

  • Bug Fixes:

    • Fixed an issue where "every X seconds" crons would fail with a "maximum call stack exceeded" error (#260).
    • Fixed an issue where types were not supported when using ES module via jsr.io (#258).
  • API Changes:

    • The new keyword is now mandatory when instantiating Croner (e.g., new Cron(/* ... */)).
    • The default export has been removed. You now need to use import { Cron } from 'croner'; or const { Cron } = require('croner');.
  • File Structure Changes (relevant for direct file access):

    • All files in the /dist directory are now minified. croner.min.js has been renamed to croner.js.
    • Typings have been moved from /types to /dist.
    • Only the /src directory is exposed in the jsr module jsr.io/@​hexagon/croner.
  • Codebase Modernization:

    • The entire codebase has been migrated from JavaScript with JSDoc to TypeScript.
    • Deno is now used for formatting, type checking, and linting, resulting in a cleaner and more maintainable repository. Esbuild is used to build the npm module and typings.

Upgrade Notice:

Due to the API and file structure changes, upgrading from 8.x to 9.x may require modifications to your existing code. Please review the above changes carefully before migrating.

9.0.0-dev.12

  • Test new release workflow
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=croner&package-manager=npm_and_yarn&previous-version=8.1.2&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- vendor/package-lock.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 19dabcc5ac..291e20ac50 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.6.0", "animate.css": "^4.1.1", - "croner": "^8.1.2", + "croner": "^9.0.0", "moment": "^2.30.1", "moment-timezone": "^0.5.46", "nunjucks": "^3.2.4", @@ -56,10 +56,9 @@ } }, "node_modules/croner": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/croner/-/croner-8.1.2.tgz", - "integrity": "sha512-ypfPFcAXHuAZRCzo3vJL6ltENzniTjwe/qsLleH1V2/7SRDjgvRQyrLmumFTLmjFax4IuSxfGXEn79fozXcJog==", - "license": "MIT", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/croner/-/croner-9.0.0.tgz", + "integrity": "sha512-onMB0OkDjkXunhdW9htFjEhqrD54+M94i6ackoUkjHKbRnXdyEyKRelp4nJ1kAz32+s27jP1FsebpJCVl0BsvA==", "engines": { "node": ">=18.0" } From cd6f10c843a355a5e8e1d316122974309166c742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Thu, 7 Nov 2024 11:38:46 +0100 Subject: [PATCH 140/418] PM2 Fix (again): add `pm2_env.unique_id` checking and cleaning (#3626) #3605 : new purpose code with `pm2_env.unique_id` checking --- CHANGELOG.md | 2 +- .../updatenotification/update_helper.js | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 579eff945d..e2b8da0d36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Fixed -- [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) +- [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) (#3626) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) - [weather] Changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) - [tests] Fix electron tests with mock dates, the mock on server side was missing (#3597) diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index cc6f2b0adc..89e8ddf72e 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -1,7 +1,7 @@ const Exec = require("node:child_process").exec; const Spawn = require("node:child_process").spawn; const fs = require("node:fs"); - +const pm2 = require("pm2"); const Log = require("logger"); /* @@ -142,7 +142,6 @@ class Updater { // restart MagicMiror with "pm2" pm2Restart () { Log.info("updatenotification: PM2 will restarting MagicMirror..."); - const pm2 = require("pm2"); pm2.restart(this.PM2, (err, proc) => { if (err) { Log.error("updatenotification:[PM2] restart Error", err); @@ -171,7 +170,15 @@ class Updater { return; } - const pm2 = require("pm2"); + if (process.env.unique_id === undefined) { + Log.info("updatenotification: [PM2] You are not using pm2"); + this.usePM2 = false; + resolve(false); + return; + } + + Log.debug(`updatenotification: [PM2] Search for pm2 id: ${process.env.pm_id} -- name: ${process.env.name} -- unique_id: ${process.env.unique_id}`); + pm2.connect((err) => { if (err) { Log.error("updatenotification: [PM2]", err); @@ -187,13 +194,14 @@ class Updater { return; } list.forEach((pm) => { - Log.debug(`[PM2] pm2 name: ${pm.name} -- in process env: ${process.env.name}`) - Log.debug(`[PM2] pm2 pm_id: ${pm.pm_id} -- in process env: ${process.env.pm_id}`) - if (pm.pm2_env.status === "online" && process.env.name === pm.name && +process.env.pm_id === +pm.pm_id) { - this.PM2 = pm.name; + Log.debug(`updatenotification: [PM2] found pm2 process id: ${pm.pm_id} -- name: ${pm.name} -- unique_id: ${pm.pm2_env.unique_id}`); + if (pm.pm2_env.status === "online" && process.env.name === pm.name && +process.env.pm_id === +pm.pm_id && process.env.unique_id === pm.pm2_env.unique_id) { + this.PM2 = pm.pm_id; this.usePM2 = true; - Log.info("updatenotification: [PM2] You are using pm2 with", this.PM2); + Log.info(`updatenotification: [PM2] You are using pm2 with id: ${this.PM2} (${pm.name})`); resolve(true); + } else { + Log.debug(`updatenotification: [PM2] pm2 process id: ${pm.pm_id} don't match...`); } }); pm2.disconnect(); From 4259d7c075acbb34dad9866934fd30b36f5036bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Sat, 9 Nov 2024 09:59:12 +0100 Subject: [PATCH 141/418] updatenotification: some fixes (#3628) continue from #3626 Is it ok for you ? --- CHANGELOG.md | 2 +- .../updatenotification/update_helper.js | 25 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2b8da0d36..7f6856c88d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Fixed -- [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) (#3626) +- [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) (#3626) (#3628) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) - [weather] Changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) - [tests] Fix electron tests with mock dates, the mock on server side was missing (#3597) diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index 89e8ddf72e..fc7cc10b78 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -1,7 +1,7 @@ const Exec = require("node:child_process").exec; const Spawn = require("node:child_process").spawn; const fs = require("node:fs"); -const pm2 = require("pm2"); + const Log = require("logger"); /* @@ -47,8 +47,8 @@ class Updater { this.autoRestart = config.updateAutorestart; this.moduleList = {}; this.updating = false; - this.usePM2 = false; - this.PM2 = null; + this.usePM2 = false; // don't use pm2 by default + this.PM2Id = null; // pm2 process number this.version = global.version; this.root_path = global.root_path; Log.info("updatenotification: Updater Class Loaded!"); @@ -139,10 +139,11 @@ class Updater { else this.npmRestart(); } - // restart MagicMiror with "pm2" + // restart MagicMiror with "pm2": use PM2Id for restart it pm2Restart () { Log.info("updatenotification: PM2 will restarting MagicMirror..."); - pm2.restart(this.PM2, (err, proc) => { + const pm2 = require("pm2"); + pm2.restart(this.PM2Id, (err, proc) => { if (err) { Log.error("updatenotification:[PM2] restart Error", err); } @@ -155,7 +156,7 @@ class Updater { const out = process.stdout; const err = process.stderr; const subprocess = Spawn("npm start", { cwd: this.root_path, shell: true, detached: true, stdio: ["ignore", out, err] }); - subprocess.unref(); + subprocess.unref(); // detach the newly launched process from the master process process.exit(); } @@ -165,49 +166,45 @@ class Updater { return new Promise((resolve) => { if (fs.existsSync("/.dockerenv")) { Log.info("updatenotification: Running in docker container, not using PM2 ..."); - this.usePM2 = false; resolve(false); return; } if (process.env.unique_id === undefined) { Log.info("updatenotification: [PM2] You are not using pm2"); - this.usePM2 = false; resolve(false); return; } Log.debug(`updatenotification: [PM2] Search for pm2 id: ${process.env.pm_id} -- name: ${process.env.name} -- unique_id: ${process.env.unique_id}`); + const pm2 = require("pm2"); pm2.connect((err) => { if (err) { Log.error("updatenotification: [PM2]", err); - this.usePM2 = false; resolve(false); return; } pm2.list((err, list) => { if (err) { Log.error("updatenotification: [PM2] Can't get process List!"); - this.usePM2 = false; resolve(false); return; } list.forEach((pm) => { Log.debug(`updatenotification: [PM2] found pm2 process id: ${pm.pm_id} -- name: ${pm.name} -- unique_id: ${pm.pm2_env.unique_id}`); if (pm.pm2_env.status === "online" && process.env.name === pm.name && +process.env.pm_id === +pm.pm_id && process.env.unique_id === pm.pm2_env.unique_id) { - this.PM2 = pm.pm_id; + this.PM2Id = pm.pm_id; this.usePM2 = true; - Log.info(`updatenotification: [PM2] You are using pm2 with id: ${this.PM2} (${pm.name})`); + Log.info(`updatenotification: [PM2] You are using pm2 with id: ${this.PM2Id} (${pm.name})`); resolve(true); } else { Log.debug(`updatenotification: [PM2] pm2 process id: ${pm.pm_id} don't match...`); } }); pm2.disconnect(); - if (!this.PM2) { + if (!this.usePM2) { Log.info("updatenotification: [PM2] You are not using pm2"); - this.usePM2 = false; resolve(false); } }); From 56cb536df12acfdc598a337f2c4f728ffb53068e Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Tue, 12 Nov 2024 08:58:36 -0600 Subject: [PATCH 142/418] add support for test mode detection in modulename.js via index.html (#3631) in some cases the modulename.js may need to detect running in test mode (compliments pr #3630) window.name is not set web mode add a new field to the index.html window.intest and use the server_function to replace the hard coded string like we do for window.mmversion=#VERSION# then change the two test helpers to set the env variable app.js detects and sets global.intest=true server func replace with value of global.intest then module can use if(window.intest) --- CHANGELOG.md | 1 + index.html | 1 + js/app.js | 1 + js/server_functions.js | 1 + tests/e2e/helpers/global-setup.js | 1 + tests/electron/helpers/global-setup.js | 1 + 6 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f6856c88d..3a0ddfeeb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ _This release is scheduled to be released on 2025-01-01._ - [linter] re-added `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [docs] Added step for npm publishing in release process (#3595) - [core] Add GitHub workflow to run spellcheck a few days before each release. +- [core] Add intest flag to index.html to pass to module js for test mode detection (needed by #3630) ### Removed diff --git a/index.html b/index.html index 09addfe37f..df64a08203 100644 --- a/index.html +++ b/index.html @@ -18,6 +18,7 @@ diff --git a/js/app.js b/js/app.js index 5ab23356ee..9d111c7eb9 100644 --- a/js/app.js +++ b/js/app.js @@ -13,6 +13,7 @@ const { getEnvVarsAsObj } = require(`${__dirname}/server_functions`); // Get version number. global.version = require(`${__dirname}/../package.json`).version; +global.mmTestMode = process.env.mmTestMode === "true" ? true : false; Log.log(`Starting MagicMirror: v${global.version}`); // Log system information. diff --git a/js/server_functions.js b/js/server_functions.js index 65928d732e..07c6df534c 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -109,6 +109,7 @@ function geExpectedReceivedHeaders (url) { function getHtml (req, res) { let html = fs.readFileSync(path.resolve(`${global.root_path}/index.html`), { encoding: "utf8" }); html = html.replace("#VERSION#", global.version); + html = html.replace("#TESTMODE#", global.mmTestMode); let configFile = "config/config.js"; if (typeof global.configuration_file !== "undefined") { diff --git a/tests/e2e/helpers/global-setup.js b/tests/e2e/helpers/global-setup.js index ef90c0fdd9..3155e747c2 100644 --- a/tests/e2e/helpers/global-setup.js +++ b/tests/e2e/helpers/global-setup.js @@ -26,6 +26,7 @@ exports.startApplication = async (configFilename, exec) => { } else { process.env.MM_CONFIG_FILE = configFilename; } + process.env.mmTestMode = "true"; if (exec) exec; global.app = require("../../../js/app"); diff --git a/tests/electron/helpers/global-setup.js b/tests/electron/helpers/global-setup.js index e7f8facafd..505cb5e3c0 100644 --- a/tests/electron/helpers/global-setup.js +++ b/tests/electron/helpers/global-setup.js @@ -11,6 +11,7 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar if (systemDate) { process.env.MOCK_DATE = systemDate; } + process.env.mmTestMode = "true"; global.electronApp = await electron.launch({ args: electronParams }); From f1522da1534f567cdd978fab846c782d576c44fb Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 12 Nov 2024 21:05:31 +0100 Subject: [PATCH 143/418] Fix eslint ignores (#3633) This will fix #3632. --- CHANGELOG.md | 1 + eslint.config.mjs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a0ddfeeb3..0d20067c0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ _This release is scheduled to be released on 2025-01-01._ - [tests] Fix test cases with hard coded Date.now (#3597) - [core] Fix missing `basePath` where `location.host` is used (#3613) - [compliments] croner library changed filenames used in latest version (#3624) +- [linter] Fix ESLint ignore pattern which caused that default modules not to be linted. (#3632). ## [2.29.0] - 2024-10-01 diff --git a/eslint.config.mjs b/eslint.config.mjs index 9fac7b7fec..54aad11a81 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -65,7 +65,7 @@ const config = [ "jest/prefer-mock-promise-shorthand": "warn", "jest/prefer-to-be": "warn", "jest/prefer-to-have-length": "warn", - "max-lines-per-function": ["warn", 350], + "max-lines-per-function": ["warn", 400], "max-statements": "off", "no-global-assign": "off", "no-inline-comments": "off", @@ -119,7 +119,7 @@ const config = [ } }, { - ignores: ["config/**", "modules/**", "!modules/default/**", "js/positions.js"] + ignores: ["config/**", "modules/**/*", "!modules/default/**", "js/positions.js"] } ]; From bd620e0061cce62fbdb9b2288006e8004eea6e1c Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Wed, 13 Nov 2024 02:57:55 -0600 Subject: [PATCH 144/418] Enhance compliments remote file with refresh support (#3630) add support to refresh the compliments remotefile add testcases for both without refresh (testcase missing) and with refresh doc to be updated --- CHANGELOG.md | 1 + modules/default/compliments/compliments.js | 44 ++++++++++++++++++- .../modules/compliments/compliments_file.js | 17 +++++++ .../compliments/compliments_file_change.js | 19 ++++++++ tests/electron/modules/compliments_spec.js | 16 +++++++ tests/mocks/compliments_file.json | 5 +++ 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 tests/configs/modules/compliments/compliments_file.js create mode 100644 tests/configs/modules/compliments/compliments_file_change.js create mode 100644 tests/mocks/compliments_file.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d20067c0a..ac9c51eafa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ _This release is scheduled to be released on 2025-01-01._ - [docs] Added step for npm publishing in release process (#3595) - [core] Add GitHub workflow to run spellcheck a few days before each release. - [core] Add intest flag to index.html to pass to module js for test mode detection (needed by #3630) +- [compliments] add support for refreshing remote compliments file, and testcases ### Removed diff --git a/modules/default/compliments/compliments.js b/modules/default/compliments/compliments.js index 4c4bef471f..9f9270f199 100644 --- a/modules/default/compliments/compliments.js +++ b/modules/default/compliments/compliments.js @@ -12,6 +12,7 @@ Module.register("compliments", { }, updateInterval: 30000, remoteFile: null, + remoteFileRefreshInterval: 0, fadeSpeed: 4000, morningStartTime: 3, morningEndTime: 12, @@ -20,6 +21,9 @@ Module.register("compliments", { random: true, specialDayUnique: false }, + urlSuffix: "", + compliments_new: null, + refreshMinimumDelay: 15 * 60 * 60 * 1000, // 15 minutes lastIndexUsed: -1, // Set currentweather from module currentWeatherType: "", @@ -41,6 +45,17 @@ Module.register("compliments", { const response = await this.loadComplimentFile(); this.config.compliments = JSON.parse(response); this.updateDom(); + if (this.config.remoteFileRefreshInterval !== 0) { + if ((this.config.remoteFileRefreshInterval >= this.refreshMinimumDelay) || window.mmTestMode === "true") { + setInterval(async () => { + const response = await this.loadComplimentFile(); + this.compliments_new = JSON.parse(response); + }, + this.config.remoteFileRefreshInterval); + } else { + Log.error(`${this.name} remoteFileRefreshInterval less than minimum`); + } + } } let minute_sync_delay = 1; // loop thru all the configured when events @@ -185,7 +200,13 @@ Module.register("compliments", { async loadComplimentFile () { const isRemote = this.config.remoteFile.indexOf("http://") === 0 || this.config.remoteFile.indexOf("https://") === 0, url = isRemote ? this.config.remoteFile : this.file(this.config.remoteFile); - const response = await fetch(url); + // because we may be fetching the same url, + // we need to force the server to not give us the cached result + // create an extra property (ignored by the server handler) just so the url string is different + // that will never be the same, using the ms value of date + if (this.config.remoteFileRefreshInterval !== 0) this.urlSuffix = `?dummy=${Date.now()}`; + // + const response = await fetch(url + this.urlSuffix); return await response.text(); }, @@ -236,6 +257,27 @@ Module.register("compliments", { compliment.lastElementChild.remove(); wrapper.appendChild(compliment); } + // if a new set of compliments was loaded from the refresh task + // we do this here to make sure no other function is using the compliments list + if (this.compliments_new) { + // use them + if (JSON.stringify(this.config.compliments) !== JSON.stringify(this.compliments_new)) { + // only reset if the contents changes + this.config.compliments = this.compliments_new; + // reset the index + this.lastIndexUsed = -1; + } + // clear new file list so we don't waste cycles comparing between refreshes + this.compliments_new = null; + } + // only in test mode + if (window.mmTestMode === "true") { + // check for (undocumented) remoteFile2 to test new file load + if (this.config.remoteFile2 !== null && this.config.remoteFileRefreshInterval !== 0) { + // switch the file so that next time it will be loaded from a changed file + this.config.remoteFile = this.config.remoteFile2; + } + } return wrapper; }, diff --git a/tests/configs/modules/compliments/compliments_file.js b/tests/configs/modules/compliments/compliments_file.js new file mode 100644 index 0000000000..d73e1b5c10 --- /dev/null +++ b/tests/configs/modules/compliments/compliments_file.js @@ -0,0 +1,17 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + modules: [ + { + module: "compliments", + position: "bottom_bar", + config: { + updateInterval: 3000, + remoteFile: "http://localhost:8080/tests/mocks/compliments_test.json" + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { module.exports = config; } diff --git a/tests/configs/modules/compliments/compliments_file_change.js b/tests/configs/modules/compliments/compliments_file_change.js new file mode 100644 index 0000000000..51fd4f6408 --- /dev/null +++ b/tests/configs/modules/compliments/compliments_file_change.js @@ -0,0 +1,19 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + modules: [ + { + module: "compliments", + position: "bottom_bar", + config: { + updateInterval: 3000, + remoteFileRefreshInterval: 1500, + remoteFile: "http://localhost:8080/tests/mocks/compliments_test.json", + remoteFile2: "http://localhost:8080/tests/mocks/compliments_file.json" + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { module.exports = config; } diff --git a/tests/electron/modules/compliments_spec.js b/tests/electron/modules/compliments_spec.js index 15c3c37c08..8626b503c8 100644 --- a/tests/electron/modules/compliments_spec.js +++ b/tests/electron/modules/compliments_spec.js @@ -78,6 +78,22 @@ describe("Compliments module", () => { await expect(doTest(["just a test"])).resolves.toBe(true); }); }); + }); + describe("Feature remote compliments file", () => { + describe("get list from remote file", () => { + it("shows 'Remote compliment file works!' as only anytime list set", async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_file.js", "01 Jan 2022 10:00:00 GMT"); + await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true); + }); + }); + describe("get updated list from remote file", () => { + it("shows 'test in morning' as test time set to 10am", async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_file_change.js", "01 Jan 2022 10:00:00 GMT"); + await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true); + await new Promise((r) => setTimeout(r, 10000)); + await expect(doTest(["test in morning"])).resolves.toBe(true); + }); + }); }); }); diff --git a/tests/mocks/compliments_file.json b/tests/mocks/compliments_file.json new file mode 100644 index 0000000000..89171b16ed --- /dev/null +++ b/tests/mocks/compliments_file.json @@ -0,0 +1,5 @@ +{ + "morning": ["test in morning"], + "afternoon": ["test in afternoon"], + "evening": ["test in evening"] +} From 15baffdede321f7aacd10554b5f9bf6cf98b25bd Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 14 Nov 2024 19:05:41 +0100 Subject: [PATCH 145/418] Adapt to "Keep a Changelog" (#3634) - Adapt heading and description to "Keep a Changelog" guideline v1.1.0 - Add missing links at the end - with this, users can click on the version number to see the diffs (I think this was intended from the beginning) - Fix two bare URLs ## The link fix Before (the link on the version number doesn't work): ![Screenshot from 2024-11-14 01-15-07](https://github.com/user-attachments/assets/e0ff4eee-abc8-4ba8-9fb7-f18fd3279ddf) After (the link on the version number works): ![Screenshot from 2024-11-14 01-15-52](https://github.com/user-attachments/assets/7b2997e7-cf6d-4e23-b4fc-50536174f4c6) --- CHANGELOG.md | 57 ++++++++++++++++++++++++++++++++++++++++++++---- Collaboration.md | 2 ++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac9c51eafa..eb38b2d8e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ -# MagicMirror² Change Log +# Changelog All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](https://semver.org/). + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². @@ -48,7 +50,7 @@ Thanks to: @bugsounet, @dkallen78, @jargordon, @khassel, @KristjanESPERANTO, @Ma ### Added -- [compliments] Added support for cron type date/time format entries mm hh DD MM dow (minutes/hours/days/months and day of week) see https://crontab.cronhub.io for construction (#3481) +- [compliments] Added support for cron type date/time format entries mm hh DD MM dow (minutes/hours/days/months and day of week) see for construction (#3481) - [core] Check config at every start of MagicMirror² (#3450) - [core] Add spelling check (cspell): `npm run test:spelling` and handle spelling issues (#3544) - [core] removed `config.paths.vendor` (could not work because `vendor` is hardcoded in `index.html`), renamed `config.paths.modules` to `config.foreignModulesDir`, added variable `MM_CUSTOMCSS_FILE` which - if set - overrides `config.customCss`, added variable `MM_MODULES_DIR` which - if set - overrides `config.foreignModulesDir`, added test for `MM_MODULES_DIR` (#3530) @@ -477,7 +479,7 @@ Special thanks to the following contributors: @eouia, @khassel, @kolbyjack, @Kri ### Added -- Added a new config option `httpHeaders` used by helmet (see https://helmetjs.github.io/). You can now set own httpHeaders which will override the defaults in `js/defaults.js` which is useful e.g. if you want to embed MagicMirror into another website (solves #2847). +- Added a new config option `httpHeaders` used by helmet (see ). You can now set own httpHeaders which will override the defaults in `js/defaults.js` which is useful e.g. if you want to embed MagicMirror into another website (solves #2847). - Show endDate for calendar events when dateHeader is enabled and showEnd is set to true (#2192). - Added the notification emitting from the weather module on information updated. - Use recommended file extension for YAML files (#2864). @@ -1641,3 +1643,50 @@ It includes (but is not limited to) the following features: ### Initial release of MagicMirror This was part of the blogpost: [https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the](https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the) + +[2.30.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.29.0...v2.30.0 +[2.29.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.28.0...v2.29.0 +[2.28.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.27.0...v2.28.0 +[2.27.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.26.0...v2.27.0 +[2.26.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.25.0...v2.26.0 +[2.25.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.24.0...v2.25.0 +[2.24.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.23.0...v2.24.0 +[2.23.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.22.0...v2.23.0 +[2.22.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.21.0...v2.22.0 +[2.21.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.20.0...v2.21.0 +[2.20.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.19.0...v2.20.0 +[2.19.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.18.0...v2.19.0 +[2.18.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.17.1...v2.18.0 +[2.17.1]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.17.0...v2.17.1 +[2.17.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.16.0...v2.17.0 +[2.16.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.15.0...v2.16.0 +[2.15.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.14.0...v2.15.0 +[2.14.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.13.0...v2.14.0 +[2.13.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.12.0...v2.13.0 +[2.12.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.11.0...v2.12.0 +[2.11.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.10.1...v2.11.0 +[2.10.1]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.10.0...v2.10.1 +[2.10.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.9.0...v2.10.0 +[2.9.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.8.0...v2.9.0 +[2.8.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.7.1...v2.8.0 +[2.7.1]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.7.0...v2.7.1 +[2.7.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.6.0...v2.7.0 +[2.6.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.5.0...v2.6.0 +[2.5.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.4.1...v2.5.0 +[2.4.1]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.4.0...v2.4.1 +[2.4.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.3.1...v2.4.0 +[2.3.1]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.3.0...v2.3.1 +[2.3.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.2.2...v2.3.0 +[2.2.2]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.2.1...v2.2.2 +[2.2.1]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.2.0...v2.2.1 +[2.2.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.1.3...v2.2.0 +[2.1.3]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.1.2...v2.1.3 +[2.1.2]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.1.1...v2.1.2 +[2.1.1]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.1.0...v2.1.1 +[2.1.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.0.5...v2.1.0 +[2.0.5]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.0.4...v2.0.5 +[2.0.4]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.0.3...v2.0.4 +[2.0.3]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.0.2...v2.0.3 +[2.0.2]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.0.1...v2.0.2 +[2.0.1]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.0.0...v2.0.1 +[2.0.0]: https://github.com/MagicMirrorOrg/MagicMirror/releases/tag/v2.0.0 diff --git a/Collaboration.md b/Collaboration.md index 1bb69e5ba4..b61ca52826 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -33,6 +33,7 @@ Are done by - [ ] update `CHANGELOG.md` - [ ] add all contributor names: `...` - [ ] add min. node version: > ⚠️ This release needs nodejs version `v20` or `v22`, minimum version is `v20.9.0` + - [ ] check release link at the bottom of the file - [ ] commit and push all changes - [ ] after successful test run via github actions: create pull request from `develop` to `master` branch - [ ] add label `mastermerge` @@ -49,6 +50,7 @@ Are done by - [ ] checkout `develop` branch - [ ] update `package.json` and `package-lock.json` to reflect correct version number `2.xx.0-develop` - [ ] draft new section in `CHANGELOG.md` + - [ ] create new release link at the bottom of the file - [ ] commit and publish `develop` branch ### After release From bd1324cc423950a5d286a8acf48ad57d1c96737d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Sun, 17 Nov 2024 13:15:51 +0100 Subject: [PATCH 146/418] Remove `@eslint/js` dependency. Already installed with `eslint` in deep (#3636) I lint my modules and just see this: `@eslint/js` is now not needed. it's installed by `eslint` it self --- CHANGELOG.md | 1 + package-lock.json | 1 - package.json | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb38b2d8e5..61f2416109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Removed - [tests] Removed node-pty and drivelist from rebuilded test (#3575) +- [deps] Remove `@eslint/js` dependency. Already installed with `eslint` in deep (#3636) ### Updated diff --git a/package-lock.json b/package-lock.json index 9de1ee5089..d30fbb938d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,6 @@ "systeminformation": "^5.23.5" }, "devDependencies": { - "@eslint/js": "^9.14.0", "@stylistic/eslint-plugin": "^2.10.1", "cspell": "^8.15.7", "eslint-plugin-import": "^2.31.0", diff --git a/package.json b/package.json index a9e7e61fa5..32e3bc157f 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,6 @@ "systeminformation": "^5.23.5" }, "devDependencies": { - "@eslint/js": "^9.14.0", "@stylistic/eslint-plugin": "^2.10.1", "cspell": "^8.15.7", "eslint-plugin-import": "^2.31.0", From 3627bebc3a09a124757ad10599006be197790434 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 11:59:23 +0100 Subject: [PATCH 147/418] Bump stylelint from 16.10.0 to 16.11.0 (#3639) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [stylelint](https://github.com/stylelint/stylelint) from 16.10.0 to 16.11.0.
Release notes

Sourced from stylelint's releases.

16.11.0

Changelog

Sourced from stylelint's changelog.

16.11.0

Commits
  • 4385d8f 16.11.0
  • d24438b Prepare 16.11.0 (#8049)
  • cce8a86 Fix font-family-no-missing-generic-family-keyword false positives for `font...
  • 49f32a5 Bump typescript from 5.6.3 to 5.7.2 in the typescript group (#8141)
  • 25cf2b3 Bump rollup from 4.27.2 to 4.27.4 (#8142)
  • 4a82b50 Fix media-feature-name-value-no-unknown false positives for `display-mode: ...
  • e1460bd Bump @​changesets/cli from 2.27.9 to 2.27.10 in the changesets group (#8140)
  • aefbb7a Bump rollup from 4.25.0 to 4.27.2 (#8130)
  • 3de7212 Enable tokenless upload for Codecov (#8131)
  • bda98ab Bump eslint from 9.14.0 to 9.15.0 in the eslint group (#8128)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=stylelint&package-manager=npm_and_yarn&previous-version=16.10.0&new-version=16.11.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 96 +++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index d30fbb938d..2dc005d0f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1268,9 +1268,9 @@ } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.1.tgz", - "integrity": "sha512-lSquqZCHxDfuTg/Sk2hiS0mcSFCEBuj49JfzPHJogDBT0mGCyY5A1AQzBWngitrp7i1/HAZpIgzF/VjhOEIJIg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", "dev": true, "funding": [ { @@ -1287,13 +1287,13 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.1" + "@csstools/css-tokenizer": "^3.0.3" } }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.1.tgz", - "integrity": "sha512-UBqaiu7kU0lfvaP982/o3khfXccVlHPWp0/vwwiIgDF0GmqqqxoiXC/6FCjlS9u92f7CoEz6nXKQnrn1kIAkOw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", "dev": true, "funding": [ { @@ -1311,9 +1311,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", - "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", + "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", "dev": true, "funding": [ { @@ -1330,14 +1330,14 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.1", - "@csstools/css-tokenizer": "^3.0.1" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" } }, "node_modules/@csstools/selector-specificity": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", - "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", "dev": true, "funding": [ { @@ -1354,7 +1354,7 @@ "node": ">=18" }, "peerDependencies": { - "postcss-selector-parser": "^6.1.0" + "postcss-selector-parser": "^7.0.0" } }, "node_modules/@dual-bundle/import-meta-resolve": { @@ -4523,13 +4523,13 @@ } }, "node_modules/css-tree": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.0.0.tgz", - "integrity": "sha512-o88DVQ6GzsABn1+6+zo2ct801dBO5OASVyxbbvA2W20ue2puSh/VOuqUj90eUeMSX/xqGqBmOKiRQN7tJOuBXw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.0.1.tgz", + "integrity": "sha512-8Fxxv+tGhORlshCdCwnNJytvlvq46sOLSYEx2ZIGurahWvMucSRnyjPA3AmrMq4VPRYbHVpWj5VkiVasrM2H4Q==", "dev": true, "license": "MIT", "dependencies": { - "mdn-data": "2.10.0", + "mdn-data": "2.12.1", "source-map-js": "^1.0.1" }, "engines": { @@ -8546,9 +8546,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", - "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", + "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", "dev": true, "license": "MIT" }, @@ -9010,9 +9010,9 @@ } }, "node_modules/mdn-data": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.10.0.tgz", - "integrity": "sha512-qq7C3EtK3yJXMwz1zAab65pjl+UhohqMOctTgcqjLOWABqmwj+me02LSsCuEUxnst9X1lCBpoE0WArGKgdGDzw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.1.tgz", + "integrity": "sha512-rsfnCbOHjqrhWxwt5/wtSLzpoKTzW7OXdT5lLOIH1OTYhWu9rRJveGq0sKvDZODABH7RX+uoR+DYcpFnq4Tf6Q==", "dev": true, "license": "CC0-1.0" }, @@ -9860,9 +9860,9 @@ "optional": true }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -10194,9 +10194,9 @@ } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -10215,7 +10215,7 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -10257,9 +10257,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11681,9 +11681,9 @@ } }, "node_modules/stylelint": { - "version": "16.10.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.10.0.tgz", - "integrity": "sha512-z/8X2rZ52dt2c0stVwI9QL2AFJhLhbPkyfpDFcizs200V/g7v+UYY6SNcB9hKOLcDDX/yGLDsY/pX08sLkz9xQ==", + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.11.0.tgz", + "integrity": "sha512-zrl4IrKmjJQ+h9FoMp69UMCq5SxeHk0URhxUBj4d3ISzo/DplOFBJZc7t7Dr6otB+1bfbbKNLOmCDpzKSlW+Nw==", "dev": true, "funding": [ { @@ -11697,16 +11697,16 @@ ], "license": "MIT", "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.1", - "@csstools/css-tokenizer": "^3.0.1", - "@csstools/media-query-list-parser": "^3.0.1", - "@csstools/selector-specificity": "^4.0.0", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2", + "@csstools/selector-specificity": "^5.0.0", "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.3", - "css-tree": "^3.0.0", + "css-tree": "^3.0.1", "debug": "^4.3.7", "fast-glob": "^3.3.2", "fastest-levenshtein": "^1.0.16", @@ -11718,16 +11718,16 @@ "ignore": "^6.0.2", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.34.0", + "known-css-properties": "^0.35.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", - "picocolors": "^1.0.1", - "postcss": "^8.4.47", + "picocolors": "^1.1.1", + "postcss": "^8.4.49", "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^6.1.2", + "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", From f417bc020474155d41a0e489c015a6b51e95c69f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 12:00:28 +0100 Subject: [PATCH 148/418] Bump prettier from 3.3.3 to 3.4.1 (#3638) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [prettier](https://github.com/prettier/prettier) from 3.3.3 to 3.4.1.
Release notes

Sourced from prettier's releases.

3.4.1

🔗 Changelog

3.4.0

diff

🔗 Release note

Changelog

Sourced from prettier's changelog.

3.4.1

diff

Remove unnecessary parentheses around assignment in v-on (#16887 by @​fisker)

<!-- Input -->
\<template>
  <button @click="foo += 2">Click</button>
</template>

<!-- Prettier 3.4.0 -->
&lt;template>
<button @​click="(foo += 2)">Click</button>
</template>

<!-- Prettier 3.4.1 -->
&lt;template>
<button @​click="foo += 2">Click</button>
</template>

3.4.0

diff

🔗 Release Notes

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=prettier&package-manager=npm_and_yarn&previous-version=3.3.3&new-version=3.4.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2dc005d0f8..20a5e646b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10287,9 +10287,9 @@ } }, "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", + "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", "dev": true, "license": "MIT", "bin": { From 28341d4a5484bbb61f3e12e013dee9c8385d6665 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 12:01:50 +0100 Subject: [PATCH 149/418] Bump eslint-plugin-package-json from 0.15.4 to 0.17.0 (#3637) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [eslint-plugin-package-json](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json) from 0.15.4 to 0.17.0.
Release notes

Sourced from eslint-plugin-package-json's releases.

v0.17.0

What's Changed

Full Changelog: https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.16.0...v0.17.0

v0.16.0

What's Changed

... (truncated)

Changelog

Sourced from eslint-plugin-package-json's changelog.

0.17.0 (2024-11-30)

Features

0.16.0 (2024-11-30)

Features

0.15.6 (2024-11-09)

Bug Fixes

0.15.5 (2024-11-06)

Bug Fixes

Commits
  • a16b6ba chore: release v0.17.0
  • 4ccae4f feat: sort alphabetically with co-located hooks for scripts (#632)
  • 100ce08 docs: add sasial-dev as a contributor for code (#669)
  • 79a18e2 chore: release v0.16.0
  • 18129cd feat(sort-collections): should sort overrides (#668)
  • 36e68b7 chore(deps): update dependency cspell to v8.16.1 (#667)
  • 189345d docs: add rakleed as a contributor for doc (#666)
  • 3b23f4a docs: add Development section in README (#665)
  • 383fe63 docs: add rakleed as a contributor for tool (#664)
  • 4a6e3c4 chore(deps): update dependency knip to v5.38.1 (#663)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=eslint-plugin-package-json&package-manager=npm_and_yarn&previous-version=0.15.4&new-version=0.17.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 20a5e646b8..5dbf244707 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.4.3", - "eslint-plugin-package-json": "^0.15.4", + "eslint-plugin-package-json": "^0.17.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", @@ -5624,9 +5624,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.15.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.15.4.tgz", - "integrity": "sha512-qH7q8xETpMqqdhmC/rj6hz7bNFGnzzkTuCQfBLNsupqB4ky596PalZLCMhn39NQocPqb5JIgGs0gnDX/VG22nQ==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.17.0.tgz", + "integrity": "sha512-Yyf+hPjOhLGzr+m5ibw61yzvTQQMCCis06cTbnQuVQqblZqn5MLQHpRkKcdNzp28yxffLStKPPx9xvmVUdDBxQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 32e3bc157f..7bce12efcd 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.3", "eslint-plugin-jsdoc": "^50.4.3", - "eslint-plugin-package-json": "^0.15.4", + "eslint-plugin-package-json": "^0.17.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.6", "jest": "^29.7.0", From 8d61336e8b9d978486b8f4831a11c1ececcbefdb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 12:27:20 +0100 Subject: [PATCH 150/418] Bump @fortawesome/fontawesome-free from 6.6.0 to 6.7.1 in /vendor (#3641) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) from 6.6.0 to 6.7.1.
Release notes

Sourced from @​fortawesome/fontawesome-free's releases.

Release 6.7.1

Change log available at https://fontawesome.com/docs/changelog/

Release 6.7.0

Change log available at https://fontawesome.com/docs/changelog/

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@fortawesome/fontawesome-free&package-manager=npm_and_yarn&previous-version=6.6.0&new-version=6.7.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- vendor/package-lock.json | 8 ++++---- vendor/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 291e20ac50..6edb0dd58d 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-free": "^6.6.0", + "@fortawesome/fontawesome-free": "^6.7.1", "animate.css": "^4.1.1", "croner": "^9.0.0", "moment": "^2.30.1", @@ -20,9 +20,9 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz", - "integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.1.tgz", + "integrity": "sha512-ALIk/MOh5gYe1TG/ieS5mVUsk7VUIJTJKPMK9rFFqOgfp0Q3d5QiBXbcOMwUvs37fyZVCz46YjOE6IFeOAXCHA==", "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", "engines": { "node": ">=6" diff --git a/vendor/package.json b/vendor/package.json index e31453747c..34b3593898 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-free": "^6.6.0", + "@fortawesome/fontawesome-free": "^6.7.1", "animate.css": "^4.1.1", "croner": "^9.0.0", "moment": "^2.30.1", From 07768c3a88e2b139ae37210b662a44ea2aeeac0b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 1 Dec 2024 15:26:23 +0100 Subject: [PATCH 151/418] Reactivate eslint-plugin-package-json (#3643) Somehow the plugin get lost when we moved to ESLint flat config. Now I reactivated it. One rules caused sorting the scripts. If this is not okay, I can undo this and switch off the rule. Thank's @bugsounet for the pinging in https://github.com/MagicMirrorOrg/MagicMirror/pull/3637#issuecomment-2509771362. --- CHANGELOG.md | 9 +++++---- eslint.config.mjs | 3 +++ package.json | 34 +++++++++++++++++----------------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61f2416109..62d02f6179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,12 @@ _This release is scheduled to be released on 2025-01-01._ ### Added - [core] Add wayland and windows start options to `package.json` (#3594) -- [linter] re-added `eslint-plugin-import`now that it supports ESLint v9 (#3586) -- [docs] Added step for npm publishing in release process (#3595) -- [core] Add GitHub workflow to run spellcheck a few days before each release. +- [docs] Add step for npm publishing in release process (#3595) +- [core] Add GitHub workflow to run spellcheck a few days before each release (#3623) - [core] Add intest flag to index.html to pass to module js for test mode detection (needed by #3630) -- [compliments] add support for refreshing remote compliments file, and testcases +- [compliments] add support for refreshing remote compliments file, and testcases (#3630) +- [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) +- [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` ### Removed diff --git a/eslint.config.mjs b/eslint.config.mjs index 54aad11a81..e8800a5144 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,12 +1,14 @@ import eslintPluginImport from "eslint-plugin-import"; import eslintPluginJest from "eslint-plugin-jest"; import eslintPluginJs from "@eslint/js"; +import eslintPluginPackageJson from "eslint-plugin-package-json/configs/recommended"; import eslintPluginStylistic from "@stylistic/eslint-plugin"; import globals from "globals"; const config = [ eslintPluginJs.configs.recommended, eslintPluginImport.flatConfigs.recommended, + eslintPluginPackageJson, { files: ["**/*.js"], languageOptions: { @@ -106,6 +108,7 @@ const config = [ "@stylistic/quote-props": ["error", "as-needed"], "func-style": "off", "import/namespace": "off", + "import/no-unresolved": "off", "max-lines-per-function": ["error", 100], "no-magic-numbers": "off", "one-var": "off", diff --git a/package.json b/package.json index 7bce12efcd..372b3196a4 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,18 @@ ], "main": "js/electron.js", "scripts": { + "config:check": "node js/check_config.js", + "install-fonts": "echo \"Installing fonts ...\n\" && cd fonts && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", + "install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev", + "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier", + "install-vendor": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", + "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix", + "lint:js": "eslint . --fix", + "lint:prettier": "prettier . --write", + "lint:staged": "lint-staged", + "postinstall": "npm run install-vendor && npm run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"", + "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.", + "server": "node ./serveronly", "start": "npm run start:x11", "start:dev": "npm run start -- dev", "start:wayland": "WAYLAND_DISPLAY=\"${WAYLAND_DISPLAY:=wayland-1}\" ./node_modules/.bin/electron js/electron.js --enable-features=UseOzonePlatform --ozone-platform=wayland", @@ -32,28 +44,16 @@ "start:windows:dev": "npm run start:windows -- dev", "start:x11": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js", "start:x11:dev": "npm run start -- dev", - "server": "node ./serveronly", - "install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev", - "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier", - "install-vendor": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", - "install-fonts": "echo \"Installing fonts ...\n\" && cd fonts && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", - "postinstall": "npm run install-vendor && npm run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"", "test": "NODE_ENV=test jest -i --forceExit", + "test:calendar": "node ./modules/default/calendar/debug.js", "test:coverage": "NODE_ENV=test jest --coverage -i --verbose false --forceExit", - "test:electron": "NODE_ENV=test jest --selectProjects electron -i --forceExit", + "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json", "test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit", - "test:unit": "NODE_ENV=test jest --selectProjects unit", - "test:prettier": "prettier . --check", + "test:electron": "NODE_ENV=test jest --selectProjects electron -i --forceExit", "test:js": "eslint .", - "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json", - "test:calendar": "node ./modules/default/calendar/debug.js", + "test:prettier": "prettier . --check", "test:spelling": "cspell . --gitignore", - "config:check": "node js/check_config.js", - "lint:prettier": "prettier . --write", - "lint:js": "eslint . --fix", - "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix", - "lint:staged": "lint-staged", - "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed." + "test:unit": "NODE_ENV=test jest --selectProjects unit" }, "lint-staged": { "*": "prettier --write", From 63178eba7202288e111faa5da3a7080cbf17652d Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Mon, 2 Dec 2024 03:17:19 -0600 Subject: [PATCH 152/418] Export animations (#3644) I am adding the animateIn/Out support to MMM-Config, but I need the list of animations.. but they are not visible in js/animateCSS.js (from require) adding an export satisfies that side issue, these would go in a dropdown list what value can I use for the default behavior? none/default? don't want an error produced.. should I add code to check for this value to prevent error? --- CHANGELOG.md | 1 + js/animateCSS.js | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62d02f6179..9cdc31ec37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ _This release is scheduled to be released on 2025-01-01._ - [compliments] add support for refreshing remote compliments file, and testcases (#3630) - [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` +- [core] Add export on animation names ### Removed diff --git a/js/animateCSS.js b/js/animateCSS.js index 057d53c72d..a503e1067b 100644 --- a/js/animateCSS.js +++ b/js/animateCSS.js @@ -155,3 +155,4 @@ function removeAnimateCSS (element, animation) { node.classList.remove("animate__animated", animationName); node.style.removeProperty("--animate-duration"); } +module.exports = { AnimateCSSIn, AnimateCSSOut }; From 291ae8546cb5ec54162135bd8bcaad2cef1a06f9 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 7 Dec 2024 08:17:04 +0100 Subject: [PATCH 153/418] Handle "module is not defined" in e2e tests (#3647) Even in successful tests, there are many module not defined` error entries. Like this: https://github.com/MagicMirrorOrg/MagicMirror/actions/runs/12199106844/job/34032254241#step:5:353 I think we can suppress them. --- CHANGELOG.md | 5 +++-- tests/e2e/helpers/mock-console.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cdc31ec37..40e3802fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Removed -- [tests] Removed node-pty and drivelist from rebuilded test (#3575) +- [tests] Remove `node-pty` and `drivelist` from rebuilded test (#3575) - [deps] Remove `@eslint/js` dependency. Already installed with `eslint` in deep (#3636) ### Updated @@ -43,7 +43,8 @@ _This release is scheduled to be released on 2025-01-01._ - [tests] Fix test cases with hard coded Date.now (#3597) - [core] Fix missing `basePath` where `location.host` is used (#3613) - [compliments] croner library changed filenames used in latest version (#3624) -- [linter] Fix ESLint ignore pattern which caused that default modules not to be linted. (#3632). +- [linter] Fix ESLint ignore pattern which caused that default modules not to be linted (#3632) +- [tests] Suppress "module is not defined" in e2e tests ## [2.29.0] - 2024-10-01 diff --git a/tests/e2e/helpers/mock-console.js b/tests/e2e/helpers/mock-console.js index c593b7062e..b903b7ac51 100644 --- a/tests/e2e/helpers/mock-console.js +++ b/tests/e2e/helpers/mock-console.js @@ -8,6 +8,7 @@ const mockError = (err) => { || err.includes("ECONNRESET") || err.includes("socket hang up") || err.includes("exports is not defined") + || err.includes("module is not defined") || err.includes("write EPIPE") || err.includes("AggregateError") || err.includes("ERR_SOCKET_CONNECTION_TIMEOUT") From 19bd76ab932866baf49404582398b7dbce83dd15 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sat, 7 Dec 2024 02:51:11 -0600 Subject: [PATCH 154/418] Fixcaldates2 fix calendar module date processing, using node-ical@0.20.1 (#3587) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit here is an updated test version of the fixes for all kinds of calendar date problems. NOTE: the changed branch name NOTE: this used the node-cal@0.19.0 library UNCHANGED best to make a new folder and git clone there git clone https://github.com/sdetweil/MagicMirror cd MagicMirror git checkout fixcaldates2 // <------ note this is a changed branch name npm run install-mm copy your config.js and custom.css from the prior folder and the non-default modules you have installed… this ONLY changes the default calendar but DOES ship an updated node-ical library too if you need to fall back, just rename the folders around again so that your original is called MagicMirror all the testcases for node-ical and MagicMirror execute successfully. the ‘BIG’ change here is to get the local NON-TZ dates for the rrule.between() all the checking and conversion code is commented out or not used the node-ical fixes are for excluded dates (exdate) values being adjusted for DST/STD time… waiting to submit that PR one fix in calendar.js for checking if a past date was too far back, but it never checked to see IF the event date was in the past… (before today) so it chopped off too many and one change in calendarfetcher.js to put out a better diagnostic message of the parsed data… (exdate was excluded cause JSON stringify couldn’t convert the complex structure) I added the tests you all have documented please re-pull and checkout the new branch (I deleted the old branch) and npm run install-mm again --------- Co-authored-by: Veeck --- CHANGELOG.md | 11 +- modules/default/calendar/calendar.js | 55 ++- modules/default/calendar/calendarfetcher.js | 2 +- .../default/calendar/calendarfetcherutils.js | 343 ++++++++++++++---- modules/default/compliments/compliments.js | 17 +- package-lock.json | 29 +- package.json | 2 +- .../3_move_first_allday_repeating_event.js | 35 ++ .../calendar/berlin_end_of_day_repeating.js | 33 ++ .../configs/modules/calendar/berlin_multi.js | 33 ++ ...n_whole_day_event_moved_over_dst_change.js | 33 ++ .../calendar/chicago_late_in_timezone.js | 33 ++ .../modules/calendar/diff_tz_start_end.js | 34 ++ .../calendar/end_of_day_berlin_moved.js | 33 ++ ...multiple_days_non_repeating_display_end.js | 33 ++ ...tiple_days_non_repeating_no_display_end.js | 34 ++ .../exdate_and_recurrence_together.js | 33 ++ ...y_event_over_multiple_days_nonrepeating.js | 32 ++ .../germany_at_end_of_day_repeating.js | 33 ++ tests/e2e/modules/compliments_spec.js | 33 ++ tests/electron/modules/calendar_spec.js | 132 +++++++ tests/electron/modules/compliments_spec.js | 2 +- .../3_move_first_allday_repeating_event.ics | 35 ++ tests/mocks/RepeatingEvent.Oct21.ics | 28 ++ tests/mocks/chicago_late_in_timezone.ics | 15 + tests/mocks/compliments_file.json | 4 +- tests/mocks/diff_tz_start_end.ics | 14 + tests/mocks/end_of_day_berlin_moved.ics | 54 +++ ..._time_over_multiple_days_non_repeating.ics | 14 + .../mocks/exdate_and_recurrence_together.ics | 48 +++ ..._event_over_multiple_days_nonrepeating.ics | 15 + .../mocks/germany_at_end_of_day_repeating.ics | 15 + ...whole_day_moved_over_dst_change_berlin.ics | 28 ++ 33 files changed, 1182 insertions(+), 113 deletions(-) create mode 100644 tests/configs/modules/calendar/3_move_first_allday_repeating_event.js create mode 100644 tests/configs/modules/calendar/berlin_end_of_day_repeating.js create mode 100644 tests/configs/modules/calendar/berlin_multi.js create mode 100644 tests/configs/modules/calendar/berlin_whole_day_event_moved_over_dst_change.js create mode 100644 tests/configs/modules/calendar/chicago_late_in_timezone.js create mode 100644 tests/configs/modules/calendar/diff_tz_start_end.js create mode 100644 tests/configs/modules/calendar/end_of_day_berlin_moved.js create mode 100644 tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js create mode 100644 tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js create mode 100644 tests/configs/modules/calendar/exdate_and_recurrence_together.js create mode 100644 tests/configs/modules/calendar/fullday_event_over_multiple_days_nonrepeating.js create mode 100644 tests/configs/modules/calendar/germany_at_end_of_day_repeating.js create mode 100644 tests/mocks/3_move_first_allday_repeating_event.ics create mode 100644 tests/mocks/RepeatingEvent.Oct21.ics create mode 100644 tests/mocks/chicago_late_in_timezone.ics create mode 100644 tests/mocks/diff_tz_start_end.ics create mode 100644 tests/mocks/end_of_day_berlin_moved.ics create mode 100644 tests/mocks/event_with_time_over_multiple_days_non_repeating.ics create mode 100644 tests/mocks/exdate_and_recurrence_together.ics create mode 100644 tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics create mode 100644 tests/mocks/germany_at_end_of_day_repeating.ics create mode 100644 tests/mocks/whole_day_moved_over_dst_change_berlin.ics diff --git a/CHANGELOG.md b/CHANGELOG.md index 40e3802fa1..e3cef7e281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ _This release is scheduled to be released on 2025-01-01._ - [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` - [core] Add export on animation names +- [calendar] - added ability to display end date for full date events, where end is not same day (showEnd=true) ### Removed @@ -38,12 +39,16 @@ _This release is scheduled to be released on 2025-01-01._ - [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) (#3626) (#3628) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) -- [weather] Changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) -- [tests] Fix electron tests with mock dates, the mock on server side was missing (#3597) -- [tests] Fix test cases with hard coded Date.now (#3597) +- [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) +- [tests] fix electron tests with mock dates, the mock on server side was missing (#3597) +- [tests] fix testcases with hard coded Date.now (#3597) - [core] Fix missing `basePath` where `location.host` is used (#3613) - [compliments] croner library changed filenames used in latest version (#3624) - [linter] Fix ESLint ignore pattern which caused that default modules not to be linted (#3632) +- [calendar] - update to resolve issues #3098 #3144 #3351 #3422 #3443 #3467 #3537 related to timezone changes +- [calendar] - fixes #3267 (styles array), also fixes event with both exdate AND recurrence(and testcase) +- [calendar] - fix showEndsOnlyWithDuration not working, #3598, applies ONLY to full day events +- [calendar] - fix showEnd for Full Day events #3602 - [tests] Suppress "module is not defined" in e2e tests ## [2.29.0] - 2024-10-01 diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 31b863eb28..6af652ba77 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -168,12 +168,17 @@ Module.register("calendar", { this.selfUpdate(); }, + notificationReceived (notification, payload, sender) { - // Override socket notification handler. - socketNotificationReceived (notification, payload) { if (notification === "FETCH_CALENDAR") { - this.sendSocketNotification(notification, { url: payload.url, id: this.identifier }); + if (this.hasCalendarURL(payload.url)) { + this.sendSocketNotification(notification, { url: payload.url, id: this.identifier }); + } } + }, + + // Override socket notification handler. + socketNotificationReceived (notification, payload) { if (this.identifier !== payload.id) { return; @@ -417,18 +422,26 @@ Module.register("calendar", { timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").format(this.config.dateFormat)); // Add end time if showEnd if (this.config.showEnd) { - if (this.config.showEndsOnlyWithDuration && event.startDate === event.endDate) { - // no duration here, don't display end - } else { + // and has a duation + if (event.startDate !== event.endDate) { timeWrapper.innerHTML += "-"; timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat)); } } + // For full day events we use the fullDayEventDateFormat if (event.fullDayEvent) { //subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day event.endDate -= ONE_SECOND; timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").format(this.config.fullDayEventDateFormat)); + // only show end if requested and allowed and the dates are different + if (this.config.showEnd && !this.config.showEndsOnlyWithDuration && moment(event.startDate, "x").format("YYYYMMDD") !== moment(event.endDate, "x").format("YYYYMMDD")) { + timeWrapper.innerHTML += "-"; + timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.fullDayEventDateFormat)); + } else + if ((moment(event.startDate, "x").format("YYYYMMDD") !== moment(event.endDate, "x").format("YYYYMMDD")) && (moment(event.startDate, "x") < moment(now, "x"))) { + timeWrapper.innerHTML = CalendarUtils.capFirst(moment(now, "x").format(this.config.fullDayEventDateFormat)); + } } else if (this.config.getRelative > 0 && event.startDate < now) { // Ongoing and getRelative is set timeWrapper.innerHTML = CalendarUtils.capFirst( @@ -460,16 +473,18 @@ Module.register("calendar", { if (event.startDate >= now || (event.fullDayEvent && this.eventEndingWithinNextFullTimeUnit(event, ONE_DAY))) { // Use relative time if (!this.config.hideTime && !event.fullDayEvent) { - timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").calendar(null, { sameElse: this.config.dateFormat })); + Log.debug("event not hidden and not fullday"); + timeWrapper.innerHTML = `${CalendarUtils.capFirst(moment(event.startDate, "x").calendar(null, { sameElse: this.config.dateFormat }))}`; } else { - timeWrapper.innerHTML = CalendarUtils.capFirst( + Log.debug("event full day or hidden"); + timeWrapper.innerHTML = `${CalendarUtils.capFirst( moment(event.startDate, "x").calendar(null, { sameDay: this.config.showTimeToday ? "LT" : `[${this.translate("TODAY")}]`, nextDay: `[${this.translate("TOMORROW")}]`, nextWeek: "dddd", sameElse: event.fullDayEvent ? this.config.fullDayEventDateFormat : this.config.dateFormat }) - ); + )}`; } if (event.fullDayEvent) { // Full days events within the next two days @@ -488,9 +503,11 @@ Module.register("calendar", { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW")); } } + Log.info("event fullday"); } else if (event.startDate - now < this.config.getRelative * ONE_HOUR) { + Log.info("not full day but within getrelative size"); // If event is within getRelative hours, display 'in xxx' time format or moment.fromNow() - timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").fromNow()); + timeWrapper.innerHTML = `${CalendarUtils.capFirst(moment(event.startDate, "x").fromNow())}`; } } else { // Ongoing event @@ -603,6 +620,7 @@ Module.register("calendar", { const calendar = this.calendarData[calendarUrl]; let remainingEntries = this.maximumEntriesForUrl(calendarUrl); let maxPastDaysCompare = now - this.maximumPastDaysForUrl(calendarUrl) * ONE_DAY; + let by_url_calevents = []; for (const e in calendar) { const event = JSON.parse(JSON.stringify(calendar[e])); // clone object @@ -620,9 +638,6 @@ Module.register("calendar", { if (this.config.hideDuplicates && this.listContainsEvent(events, event)) { continue; } - if (--remainingEntries < 0) { - break; - } } event.url = calendarUrl; @@ -667,15 +682,21 @@ Module.register("calendar", { for (let splitEvent of splitEvents) { if (splitEvent.endDate > now && splitEvent.endDate <= future) { - events.push(splitEvent); + by_url_calevents.push(splitEvent); } } } else { - events.push(event); + by_url_calevents.push(event); } } + by_url_calevents.sort(function (a, b) { + return a.startDate - b.startDate; + }); + Log.debug(`pushing ${by_url_calevents.length} events to total with room for ${remainingEntries}`); + events = events.concat(by_url_calevents.slice(0, remainingEntries)); + Log.debug(`events for calendar=${events.length}`); } - + Log.info(`sorting events count=${events.length}`); events.sort(function (a, b) { return a.startDate - b.startDate; }); @@ -715,7 +736,7 @@ Module.register("calendar", { } events = newEvents; } - + Log.info(`slicing events total maxcount=${this.config.maximumEntries}`); return events.slice(0, this.config.maximumEntries); }, diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 824c7c5b4f..2a56ff5b4d 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -56,7 +56,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn try { data = ical.parseICS(responseData); - Log.debug(`parsed data=${JSON.stringify(data)}`); + Log.debug(`parsed data=${JSON.stringify(data, null, 2)}`); events = CalendarFetcherUtils.filterEvents(data, { excludedEvents, includePastEvents, diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index eec3540f29..b89f5962c2 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -160,7 +160,7 @@ const CalendarFetcherUtils = { } if (event.type === "VEVENT") { - Log.debug(`Event:\n${JSON.stringify(event)}`); + Log.debug(`Event:\n${JSON.stringify(event, null, 2)}`); let startMoment = eventDate(event, "start"); let endMoment; @@ -246,6 +246,8 @@ const CalendarFetcherUtils = { const location = event.location || false; const geo = event.geo || false; const description = event.description || false; + let d1; + let d2; if (event.rrule && typeof event.rrule !== "undefined" && !isFacebookBirthday) { const rule = event.rrule; @@ -261,9 +263,10 @@ const CalendarFetcherUtils = { // For recurring events, get the set of start dates that fall within the range // of dates we're looking for. - // kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time + let pastLocal; let futureLocal; + if (CalendarFetcherUtils.isFullDayEvent(event)) { Log.debug("fullday"); // if full day event, only use the date part of the ranges @@ -283,52 +286,52 @@ const CalendarFetcherUtils = { } futureLocal = futureMoment.toDate(); // future } - Log.debug(`Search for recurring events between: ${pastLocal} and ${futureLocal}`); - const hasByWeekdayRule = rule.options.byweekday !== undefined && rule.options.byweekday !== null; const oneDayInMs = 24 * 60 * 60 * 1000; + d1 = new Date(new Date(pastLocal.valueOf() - oneDayInMs).getTime()); + d2 = new Date(new Date(futureLocal.valueOf() + oneDayInMs).getTime()); + Log.debug(`Search for recurring events between: ${d1} and ${d2}`); + + event.start = rule.options.dtstart; + + Log.debug("fix rrule start=", rule.options.dtstart); + Log.debug("event before rrule.between=", JSON.stringify(event, null, 2), "exdates=", event.exdate); + // fixup the exdate and recurrence date to local time too for post between() handling + CalendarFetcherUtils.fixEventtoLocal(event); + Log.debug(`RRule: ${rule.toString()}`); rule.options.tzid = null; // RRule gets *very* confused with timezones - let dates = rule.between(new Date(pastLocal.valueOf() - oneDayInMs), new Date(futureLocal.valueOf() + oneDayInMs), true, () => { return true; }); - Log.debug(`Title: ${event.summary}, with dates: ${JSON.stringify(dates)}`); + + let dates = rule.between(d1, d2, true, () => { return true; }); + + Log.debug(`Title: ${event.summary}, with dates: \n\n${JSON.stringify(dates)}\n`); + + // shouldn't need this anymore, as RRULE not passed junk dates = dates.filter((d) => { if (JSON.stringify(d) === "null") return false; else return true; }); - // RRule can generate dates with an incorrect recurrence date. Process the array here and apply date correction. - if (hasByWeekdayRule) { - Log.debug("Rule has byweekday, checking for correction"); - dates.forEach((date, index, arr) => { - // NOTE: getTimezoneOffset() is negative of the expected value. For America/Los_Angeles under DST (GMT-7), - // this value is +420. For Australia/Sydney under DST (GMT+11), this value is -660. - const tzOffset = date.getTimezoneOffset() / 60; - const hour = date.getHours(); - if ((tzOffset < 0) && (hour < -tzOffset)) { // east of GMT - Log.debug(`East of GMT (tzOffset: ${tzOffset}) and hour=${hour} < ${-tzOffset}, Subtracting 1 day from ${date}`); - arr[index] = new Date(date.valueOf() - oneDayInMs); - } else if ((tzOffset > 0) && (hour >= (24 - tzOffset))) { // west of GMT - Log.debug(`West of GMT (tzOffset: ${tzOffset}) and hour=${hour} >= 24-${tzOffset}, Adding 1 day to ${date}`); - arr[index] = new Date(date.valueOf() + oneDayInMs); - } - }); - // Adjusting the dates could push it beyond the 'until' date, so filter those out here. - if (rule.options.until !== null) { - dates = dates.filter((date) => { - return date.valueOf() <= rule.options.until.valueOf(); - }); - } - } - - // The dates array from rrule can be confused by DST. If the event was created during DST and we - // are querying a date range during non-DST, rrule can have the incorrect time for the date range. - // Reprocess the array here computing and applying the time offset. - dates.forEach((date, index, arr) => { - let adjustHours = CalendarFetcherUtils.calculateTimezoneAdjustment(event, date); - if (adjustHours !== 0) { - Log.debug(`Applying timezone adjustment hours=${adjustHours} to ${date}`); - arr[index] = new Date(date.valueOf() + (adjustHours * 60 * 60 * 1000)); - } + // go thru all the rrule.between() dates and put back the tz offset removed so rrule.between would work + let datesLocal = []; + let offset = d1.getTimezoneOffset(); + Log.debug("offset =", offset); + dates.forEach((d) => { + let dtext = d.toISOString().slice(0, -5); + Log.debug(" date text form without tz=", dtext); + let dLocal = new Date(d.valueOf() + (offset * 60000)); + let offset2 = dLocal.getTimezoneOffset(); + Log.debug("date after offset applied=", dLocal); + if (offset !== offset2) { + // woops, dst/std switch + let delta = offset - offset2; + Log.debug("offset delta=", delta); + dLocal = new Date(d.valueOf() + ((offset - delta) * 60000)); + Log.debug("corrected normalized date=", dLocal); + } else Log.debug(" neutralized date=", dLocal); + datesLocal.push(dLocal); }); + dates = datesLocal; + // The "dates" array contains the set of dates within our desired date range range that are valid // for the recurrence rule. *However*, it's possible for us to have a specific recurrence that @@ -337,29 +340,22 @@ const CalendarFetcherUtils = { // because the logic below will filter out any recurrences that don't actually belong within // our display range. // Would be great if there was a better way to handle this. - Log.debug(`event.recurrences: ${event.recurrences}`); + // + // i don't think we will ever see this anymore (oct 2024) due to code fixes for rrule.between() + // + Log.debug("event.recurrences:", event.recurrences); if (event.recurrences !== undefined) { for (let dateKey in event.recurrences) { // Only add dates that weren't already in the range we added from the rrule so that // we don't double-add those events. let d = new Date(dateKey); - if (!moment(d).isBetween(pastMoment, futureMoment)) { + if (!moment(d).isBetween(d1, d2)) { + Log.debug("adding recurring event not found in between list =", d, " should not happen now using local dates oct 17,24"); dates.push(d); } } } - // Lastly, sometimes rrule doesn't include the event.start even if it is in the requested range. Ensure - // inclusion here. Unfortunately dates.includes() doesn't find it so we have to do forEach(). - { - let found = false; - dates.forEach((d) => { if (d.valueOf() === event.start.valueOf()) found = true; }); - if (!found) { - Log.debug(`event.start=${event.start} was not included in results from rrule; adding`); - dates.splice(0, 0, event.start); - } - } - // Loop through the set of date entries to see which recurrences should be added to our event list. for (let d in dates) { let date = dates[d]; @@ -367,30 +363,42 @@ const CalendarFetcherUtils = { let curDurationMs = durationMs; let showRecurrence = true; - startMoment = moment(date); + let startMoment = moment(date); - // Remove the time information of each date by using its substring, using the following method: - // .toISOString().substring(0,10). - // since the date is given as ISOString with YYYY-MM-DDTHH:MM:SS.SSSZ - // (see https://momentjs.com/docs/#/displaying/as-iso-string/). - // This must be done after `date` is adjusted - const dateKey = date.toISOString().substring(0, 10); + let dateKey = CalendarFetcherUtils.getDateKeyFromDate(date); + Log.debug("event date dateKey=", dateKey); // For each date that we're checking, it's possible that there is a recurrence override for that one day. - if (curEvent.recurrences !== undefined && curEvent.recurrences[dateKey] !== undefined) { - // We found an override, so for this recurrence, use a potentially different title, start date, and duration. - curEvent = curEvent.recurrences[dateKey]; - startMoment = moment(curEvent.start); - curDurationMs = curEvent.end.valueOf() - startMoment.valueOf(); + if (curEvent.recurrences !== undefined) { + Log.debug("have recurrences=", curEvent.recurrences); + if (curEvent.recurrences[dateKey] !== undefined) { + Log.debug("have a recurrence match for dateKey=", dateKey); + // We found an override, so for this recurrence, use a potentially different title, start date, and duration. + curEvent = curEvent.recurrences[dateKey]; + curEvent.start = new Date(new Date(curEvent.start.valueOf()).getTime()); + curEvent.end = new Date(new Date(curEvent.end.valueOf()).getTime()); + startMoment = CalendarFetcherUtils.getAdjustedStartMoment(curEvent.start, event); + endMoment = CalendarFetcherUtils.getAdjustedStartMoment(curEvent.end, event); + date = curEvent.start; + curDurationMs = new Date(endMoment).valueOf() - startMoment.valueOf(); + } else { + Log.debug("recurrence key ", dateKey, " doesn't match"); + } } // If there's no recurrence override, check for an exception date. Exception dates represent exceptions to the rule. - else if (curEvent.exdate !== undefined && curEvent.exdate[dateKey] !== undefined) { - // This date is an exception date, which means we should skip it in the recurrence pattern. - showRecurrence = false; + if (curEvent.exdate !== undefined) { + Log.debug("have datekey=", dateKey, " exdates=", curEvent.exdate); + if (curEvent.exdate[dateKey] !== undefined) { + // This date is an exception date, which means we should skip it in the recurrence pattern. + showRecurrence = false; + } } Log.debug(`duration: ${curDurationMs}`); + startMoment = CalendarFetcherUtils.getAdjustedStartMoment(date, event); + endMoment = moment(startMoment.valueOf() + curDurationMs); + if (startMoment.valueOf() === endMoment.valueOf()) { endMoment = endMoment.endOf("day"); } @@ -408,7 +416,7 @@ const CalendarFetcherUtils = { } if (showRecurrence === true) { - Log.debug(`saving event: ${description}`); + Log.debug(`saving event: ${recurrenceTitle}`); newEvents.push({ title: recurrenceTitle, startDate: startMoment.format("x"), @@ -421,7 +429,10 @@ const CalendarFetcherUtils = { geo: geo, description: description }); + } else { + Log.debug("not saving event ", recurrenceTitle, new Date(startMoment)); } + Log.debug(" "); } // End recurring event parsing. } else { @@ -472,7 +483,9 @@ const CalendarFetcherUtils = { startDate: startMoment.add(adjustHours, "hours").format("x"), endDate: endMoment.add(adjustHours, "hours").format("x"), fullDayEvent: fullDayEvent, + recurringEvent: false, class: event.class, + firstYear: event.start.getFullYear(), location: location, geo: geo, description: description @@ -488,6 +501,200 @@ const CalendarFetcherUtils = { return newEvents; }, + /** + * fixup thew event fields that have dates to use local time + * BEFORE calling rrule.between + * @param the event being processed + * @returns nothing + */ + fixEventtoLocal (event) { + // if there are excluded dates, their date is incorrect and possibly key as well. + if (event.exdate !== undefined) { + Object.keys(event.exdate).forEach((dateKey) => { + // get the date + let exdate = event.exdate[dateKey]; + Log.debug("exdate w key=", exdate); + //exdate=CalendarFetcherUtils.convertDateToLocalTime(exdate, event.end.tz) + exdate = new Date(new Date(exdate.valueOf() - ((120 * 60 * 1000))).getTime()); + Log.debug("new exDate item=", exdate, " with old key=", dateKey); + let newkey = exdate.toISOString().slice(0, 10); + if (newkey !== dateKey) { + Log.debug("new exDate item=", exdate, ` key=${newkey}`); + event.exdate[newkey] = exdate; + //delete event.exdate[dateKey] + } + }); + Log.debug("updated exdate list=", event.exdate); + } + if (event.recurrences) { + Object.keys(event.recurrences).forEach((dateKey) => { + let exdate = event.recurrences[dateKey]; + //exdate=new Date(new Date(exdate.valueOf()-(60*60*1000)).getTime()) + Log.debug("new recurrence item=", exdate, " with old key=", dateKey); + exdate.start = CalendarFetcherUtils.convertDateToLocalTime(exdate.start, exdate.start.tz); + exdate.end = CalendarFetcherUtils.convertDateToLocalTime(exdate.end, exdate.end.tz); + Log.debug("adjusted recurringEvent start=", exdate.start, " end=", exdate.end); + }); + } + Log.debug("modified recurrences before rrule.between", event.recurrences); + }, + + /** + * convert a UTC date to local time + * BEFORE calling rrule.between + * @param date ti conert + * tz event is currently in + * @returns updated date object + */ + convertDateToLocalTime (date, tz) { + let delta_tz_offset = 0; + let now_offset = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(moment.tz.guess()); + let event_offset = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(tz); + Log.debug("date to convert=", date); + if (Math.sign(now_offset) !== Math.sign(event_offset)) { + delta_tz_offset = Math.abs(now_offset) + Math.abs(event_offset); + } else { + // signs are the same + // if negative + if (Math.sign(now_offset) === -1) { + // la looking at chicago + if (now_offset < event_offset) { // 5 -7 + delta_tz_offset = now_offset - event_offset; + } + else { //7 -5 , chicago looking at LA + delta_tz_offset = event_offset - now_offset; + } + } + else { + // berlin looking at sydney + if (now_offset < event_offset) { // 5 -7 + delta_tz_offset = event_offset - now_offset; + Log.debug("less delta=", delta_tz_offset); + } + else { // 11 - 2, sydney looking at berlin + delta_tz_offset = -(now_offset - event_offset); + Log.debug("more delta=", delta_tz_offset); + } + } + } + const newdate = new Date(new Date(date.valueOf() + (delta_tz_offset * 60 * 1000)).getTime()); + Log.debug("modified date =", newdate); + return newdate; + }, + + /** + * get the exdate/recurrence hash key from the date object + * BEFORE calling rrule.between + * @param the date of the event + * @returns string date key YYYY-MM-DD + */ + getDateKeyFromDate (date) { + // get our runtime timezone offset + const nowDiff = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(moment.tz.guess()); + let startday = date.getDate(); + let adjustment = 0; + Log.debug(" day of month=", (`0${startday}`).slice(-2), " nowDiff=", nowDiff, ` start time=${date.toString().split(" ")[4].slice(0, 2)}`); + Log.debug("date string= ", date.toString()); + Log.debug("date iso string ", date.toISOString()); + // if the dates are different + if (date.toString().slice(8, 10) < date.toISOString().slice(8, 10)) { + startday = date.toString().slice(8, 10); + Log.debug("< ", startday); + } else { // tostring is more + if (date.toString().slice(8, 10) > date.toISOString().slice(8, 10)) { + startday = date.toISOString().slice(8, 10); + Log.debug("> ", startday); + } + } + return date.toISOString().substring(0, 8) + (`0${startday}`).slice(-2); + }, + + /** + * get the timezone offset from the timezone string + * + * @param the timezone string + * @returns the numerical offset + */ + getTimezoneOffsetFromTimezone (timeZone) { + const str = new Date().toLocaleString("en", { timeZone, timeZoneName: "longOffset" }); + Log.debug("tz offset=", str); + const [_, h, m] = str.match(/([+-]\d+):(\d+)$/) || ["", "+00", "00"]; + return h * 60 + (h > 0 ? +m : -m); + }, + + /** + * fixup the date start moment after rrule.between returns date array + * + * @param date object from rrule.between results + * the event object it came from + * @returns moment object + */ + getAdjustedStartMoment (date, event) { + + let startMoment = moment(date); + + Log.debug("startMoment pre=", startMoment); + // get our runtime timezone offset + const nowDiff = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(moment.tz.guess()); // 10/18 16:49, 300 + let eventDiff = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(event.end.tz); // watch out, start tz is cleared to handle rrule 120 23:49 + + Log.debug("tz diff event=", eventDiff, " local=", nowDiff, " end event timezone=", event.end.tz); + + // if the diffs are different (not same tz for processing as event) + if (nowDiff !== eventDiff) { + // if signs are different + if (Math.sign(nowDiff) !== Math.sign(eventDiff)) { + // its the accumulated total + Log.debug("diff signs, accumulate"); + eventDiff = Math.abs(eventDiff) + Math.abs(nowDiff); + // sign of diff depends on where you are looking at which event. + // australia looking at US, add to get same time + Log.debug("new different event diff=", eventDiff); + if (Math.sign(nowDiff) === -1) { + eventDiff *= -1; + // US looking at australia event have to subtract + Log.debug("new diff, same sign, total event diff=", eventDiff); + } + } + else { + // signs are the same, all east of UTC or all west of UTC + // if the signs are negative (west of UTC) + Log.debug("signs are the same"); + if (Math.sign(eventDiff) === -1) { + //if west, looking at more west + if (nowDiff < eventDiff) { + //-600 -420 + eventDiff = -(eventDiff - (nowDiff - eventDiff)); //-180 + Log.debug("now looking back east delta diff=", eventDiff); + } + else { + Log.debug("now looking more west"); + eventDiff = Math.abs(eventDiff - nowDiff); + } + } else { + Log.debug("signs are both positive"); + // signs are positive (east of UTC) + // berlin < sydney + if (nowDiff < eventDiff) { + // germany vs australia + eventDiff = -(eventDiff - nowDiff); + } + else { + // australia vs germany + //eventDiff = eventDiff; //- nowDiff + } + } + } + startMoment = moment.tz(new Date(date.valueOf() + (eventDiff * (60 * 1000))), event.end.tz); + } else { + Log.debug("same tz event and display"); + eventDiff = 0; + startMoment = moment.tz(new Date(date.valueOf() - (eventDiff * (60 * 1000))), event.end.tz); + } + Log.debug("startMoment post=", startMoment); + return startMoment; + }, + /** * Lookup iana tz from windows * @param {string} msTZName the timezone name to lookup diff --git a/modules/default/compliments/compliments.js b/modules/default/compliments/compliments.js index 9f9270f199..b7dc1295b0 100644 --- a/modules/default/compliments/compliments.js +++ b/modules/default/compliments/compliments.js @@ -49,7 +49,12 @@ Module.register("compliments", { if ((this.config.remoteFileRefreshInterval >= this.refreshMinimumDelay) || window.mmTestMode === "true") { setInterval(async () => { const response = await this.loadComplimentFile(); - this.compliments_new = JSON.parse(response); + if (response) { + this.compliments_new = JSON.parse(response); + } + else { + Log.error(`${this.name} remoteFile refresh failed`); + } }, this.config.remoteFileRefreshInterval); } else { @@ -204,10 +209,14 @@ Module.register("compliments", { // we need to force the server to not give us the cached result // create an extra property (ignored by the server handler) just so the url string is different // that will never be the same, using the ms value of date - if (this.config.remoteFileRefreshInterval !== 0) this.urlSuffix = `?dummy=${Date.now()}`; + if (isRemote && this.config.remoteFileRefreshInterval !== 0) this.urlSuffix = `?dummy=${Date.now()}`; // - const response = await fetch(url + this.urlSuffix); - return await response.text(); + try { + const response = await fetch(url + this.urlSuffix); + return await response.text(); + } catch (error) { + Log.info(`${this.name} fetch failed error=`, error); + } }, /** diff --git a/package-lock.json b/package-lock.json index 5dbf244707..4c2a3adb81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "0.18.0", + "node-ical": "^0.20.1", "pm2": "^5.4.2", "socket.io": "^4.8.1", "suncalc": "^1.9.0", @@ -3285,12 +3285,12 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -9370,15 +9370,14 @@ } }, "node_modules/node-ical": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.18.0.tgz", - "integrity": "sha512-FrOUPztjw9OUgSB9o/ffhl86BiVClQTut97C2NqCwKIgOAcKPEw5UQMuSuNJO/Y4hqTyJdKZh2TCqNHQnE9YFg==", - "license": "Apache-2.0", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.20.1.tgz", + "integrity": "sha512-NrXgzDJd6XcyX9kDMJVA3xYCZmntY7ghA2BOdBeYr3iu8tydHOAb+68jPQhF9V2CRQ0/386X05XhmLzQUN0+Hw==", "dependencies": { - "axios": "1.6.7", - "moment-timezone": "^0.5.44", + "axios": "^1.7.7", + "moment-timezone": "^0.5.45", "rrule": "2.8.1", - "uuid": "^9.0.0" + "uuid": "^10.0.0" } }, "node_modules/node-int64": { @@ -12623,9 +12622,9 @@ } }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" diff --git a/package.json b/package.json index 372b3196a4..8e6f4108a7 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "node-ical": "0.18.0", + "node-ical": "^0.20.1", "pm2": "^5.4.2", "socket.io": "^4.8.1", "suncalc": "^1.9.0", diff --git a/tests/configs/modules/calendar/3_move_first_allday_repeating_event.js b/tests/configs/modules/calendar/3_move_first_allday_repeating_event.js new file mode 100644 index 0000000000..30afae2ccb --- /dev/null +++ b/tests/configs/modules/calendar/3_move_first_allday_repeating_event.js @@ -0,0 +1,35 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + units: "metric", + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + hideDuplicates: false, + maximumEntries: 100, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 28, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/3_move_first_allday_repeating_event.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/berlin_end_of_day_repeating.js b/tests/configs/modules/calendar/berlin_end_of_day_repeating.js new file mode 100644 index 0000000000..b706347897 --- /dev/null +++ b/tests/configs/modules/calendar/berlin_end_of_day_repeating.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 28, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/end_of_day_berlin_moved.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/berlin_multi.js b/tests/configs/modules/calendar/berlin_multi.js new file mode 100644 index 0000000000..50069371ba --- /dev/null +++ b/tests/configs/modules/calendar/berlin_multi.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 28, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/RepeatingEvent.Oct21.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/berlin_whole_day_event_moved_over_dst_change.js b/tests/configs/modules/calendar/berlin_whole_day_event_moved_over_dst_change.js new file mode 100644 index 0000000000..255bbd950e --- /dev/null +++ b/tests/configs/modules/calendar/berlin_whole_day_event_moved_over_dst_change.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 28, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/whole_day_moved_over_dst_change_berlin.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/chicago_late_in_timezone.js b/tests/configs/modules/calendar/chicago_late_in_timezone.js new file mode 100644 index 0000000000..3591b4cb79 --- /dev/null +++ b/tests/configs/modules/calendar/chicago_late_in_timezone.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 20, + calendars: [ + { + maximumEntries: 100, + //url: "http://localhost:8080/tests/mocks/chicago_late_in_timezone.ics" + url: "http://localhost:8080/tests/mocks/chicago_late_in_timezone.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/diff_tz_start_end.js b/tests/configs/modules/calendar/diff_tz_start_end.js new file mode 100644 index 0000000000..829ef3a0ad --- /dev/null +++ b/tests/configs/modules/calendar/diff_tz_start_end.js @@ -0,0 +1,34 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 28, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/diff_tz_start_end.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/end_of_day_berlin_moved.js b/tests/configs/modules/calendar/end_of_day_berlin_moved.js new file mode 100644 index 0000000000..b706347897 --- /dev/null +++ b/tests/configs/modules/calendar/end_of_day_berlin_moved.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 28, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/end_of_day_berlin_moved.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js b/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js new file mode 100644 index 0000000000..95989648ca --- /dev/null +++ b/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js b/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js new file mode 100644 index 0000000000..ef60df4c94 --- /dev/null +++ b/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js @@ -0,0 +1,34 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + showEndsOnlyWithDuration: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/exdate_and_recurrence_together.js b/tests/configs/modules/calendar/exdate_and_recurrence_together.js new file mode 100644 index 0000000000..b1dc06389b --- /dev/null +++ b/tests/configs/modules/calendar/exdate_and_recurrence_together.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 28, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/exdate_and_recurrence_together.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/fullday_event_over_multiple_days_nonrepeating.js b/tests/configs/modules/calendar/fullday_event_over_multiple_days_nonrepeating.js new file mode 100644 index 0000000000..7ec5885cb7 --- /dev/null +++ b/tests/configs/modules/calendar/fullday_event_over_multiple_days_nonrepeating.js @@ -0,0 +1,32 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/germany_at_end_of_day_repeating.js b/tests/configs/modules/calendar/germany_at_end_of_day_repeating.js new file mode 100644 index 0000000000..e9d7e88337 --- /dev/null +++ b/tests/configs/modules/calendar/germany_at_end_of_day_repeating.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + hideDuplicates: false, + maximumEntries: 100, + sliceMultiDayEvents: true, + dateFormat: "MMM Do, HH:mm", + timeFormat: "absolute", + getRelative: 0, + urgency: 0, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/germany_at_end_of_day_repeating.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/e2e/modules/compliments_spec.js b/tests/e2e/modules/compliments_spec.js index 7763dc689b..47214781ab 100644 --- a/tests/e2e/modules/compliments_spec.js +++ b/tests/e2e/modules/compliments_spec.js @@ -89,4 +89,37 @@ describe("Compliments module", () => { }); }); }); + + describe("Feature remote compliments file", () => { + describe("get list from remote file", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_file.js"); + await helpers.getDocument(); + }); + it("shows 'Remote compliment file works!' as only anytime list set", async () => { + //await helpers.startApplication("tests/configs/modules/compliments/compliments_file.js", "01 Jan 2022 10:00:00 GMT"); + await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true); + }); + // afterAll(async () =>{ + // await helpers.stopApplication() + // }); + }); + + describe("get list from remote file w update", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_file_change.js"); + await helpers.getDocument(); + }); + it("shows 'test in morning' as test time set to 10am", async () => { + //await helpers.startApplication("tests/configs/modules/compliments/compliments_file_change.js", "01 Jan 2022 10:00:00 GMT"); + await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true); + await new Promise((r) => setTimeout(r, 10000)); + await expect(doTest(["test in morning"])).resolves.toBe(true); + }); + // afterAll(async () =>{ + // await helpers.stopApplication() + // }); + }); + }); + }); diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 8731c3cd1a..f73d673489 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -22,6 +22,21 @@ describe("Calendar module", () => { return await loc.count(); }; + const first = 0; + const second = 1; + const third = 2; + const last = -1; + + // get results of table row and column, can select specific row of results, + // row is 0 based index -1 is last, 0 is first... need 10th(human count), use 9 as row + // uses playwright nth locator syntax + const doTestTableContent = async (table_row, table_column, content, row = first) => { + const elem = await global.page.locator(table_row); + const date = await global.page.locator(table_column).locator(`nth=${row}`); + await expect(date.textContent()).resolves.toContain(content); + return true; + }; + afterEach(async () => { await helpers.stopApplication(); }); @@ -147,4 +162,121 @@ describe("Calendar module", () => { }); }); + describe("sliceMultiDayEvents direct count", () => { + it("Issue #3452 split multiday in Europe", async () => { + await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await expect(doTestCount()).resolves.toBe(6); + }); + }); + + describe("germany timezone", () => { + it("Issue #unknown fullday timezone East of UTC edge", async () => { + await helpers.startApplication("tests/configs/modules/calendar/germany_at_end_of_day_repeating.js", "01 Oct 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await expect(doTestTableContent(".calendar .event", ".time", "Oct 22nd, 23:00", first)).resolves.toBe(true); + }); + }); + + describe("germany all day repeating moved (recurrence and exdate)", () => { + it("Issue #unknown fullday timezone East of UTC event moved", async () => { + await helpers.startApplication("tests/configs/modules/calendar/3_move_first_allday_repeating_event.js", "01 Oct 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await expect(doTestTableContent(".calendar .event", ".time", "12th.Oct")).resolves.toBe(true); + }); + }); + + describe("chicago late in timezone", () => { + it("Issue #unknown rrule US close to timezone edge", async () => { + await helpers.startApplication("tests/configs/modules/calendar/chicago_late_in_timezone.js", "01 Sept 2024 10:38:00 GMT-5:00", ["js/electron.js"], "America/Chicago"); + await expect(doTestTableContent(".calendar .event", ".time", "10th.Sep, 20:15")).resolves.toBe(true); + }); + }); + + describe("berlin late in day event moved, viewed from berlin", () => { + it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { + await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 23:00-00:00", last)).resolves.toBe(true); + }); + }); + + describe("berlin late in day event moved, viewed from sydney", () => { + it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { + await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Australia/Sydney"); + await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 01:00-02:00", last)).resolves.toBe(true); + }); + }); + + describe("berlin late in day event moved, viewed from chicago", () => { + it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { + await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "America/Chicago"); + await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 16:00-17:00", last)).resolves.toBe(true); + }); + }); + + describe("berlin multi-events inside offset", () => { + it("some events before DST. some after midnight", async () => { + await helpers.startApplication("tests/configs/modules/calendar/berlin_multi.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await expect(doTestTableContent(".calendar .event", ".time", "30th.Oct, 00:00-01:00", last)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "21st.Oct, 00:00-01:00", first)).resolves.toBe(true); + }); + }); + + describe("berlin whole day repeating, start moved after end", () => { + it("some events before DST. some after", async () => { + await helpers.startApplication("tests/configs/modules/calendar/berlin_whole_day_event_moved_over_dst_change.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await expect(doTestTableContent(".calendar .event", ".time", "30th.Oct", last)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "27th.Oct", first)).resolves.toBe(true); + }); + }); + + describe("berlin 11pm-midnight", () => { + it("right inside the offset, before midnight", async () => { + await helpers.startApplication("tests/configs/modules/calendar/berlin_end_of_day_repeating.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 23:00-00:00", last)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "22nd.Oct, 23:00-00:00", first)).resolves.toBe(true); + }); + }); + + describe("both moved and delete events in recurring list", () => { + it("with moved before and after original", async () => { + await helpers.startApplication("tests/configs/modules/calendar/exdate_and_recurrence_together.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + // moved after end at oct 26 + await expect(doTestTableContent(".calendar .event", ".time", "27th.Oct, 14:30-15:30", last)).resolves.toBe(true); + // moved before start at oct 23 + await expect(doTestTableContent(".calendar .event", ".time", "22nd.Oct, 14:30-15:30", first)).resolves.toBe(true); + // remaining original 4th, now 3rd + await expect(doTestTableContent(".calendar .event", ".time", "26th.Oct, 14:30-15:30", second)).resolves.toBe(true); + }); + }); + + describe("one event diff tz", () => { + it("start/end in diff timezones", async () => { + await helpers.startApplication("tests/configs/modules/calendar/diff_tz_start_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + // just + await expect(doTestTableContent(".calendar .event", ".time", "29th.Oct, 05:00-30th.Oct, 18:00", first)).resolves.toBe(true); + }); + }); + + describe("one event non repeating", () => { + it("fullday non-repeating", async () => { + await helpers.startApplication("tests/configs/modules/calendar/fullday_event_over_multiple_days_nonrepeating.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + // just + await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct-30th.Oct", first)).resolves.toBe(true); + }); + }); + + describe("one event no end display", () => { + it("don't display end", async () => { + await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + // just + await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 20:00", first)).resolves.toBe(true); + }); + }); + + describe("display end display end", () => { + it("display end", async () => { + await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + // just + await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 20:00-26th.Oct, 06:00", first)).resolves.toBe(true); + }); + }); + }); diff --git a/tests/electron/modules/compliments_spec.js b/tests/electron/modules/compliments_spec.js index 8626b503c8..4555ffcbf7 100644 --- a/tests/electron/modules/compliments_spec.js +++ b/tests/electron/modules/compliments_spec.js @@ -88,7 +88,7 @@ describe("Compliments module", () => { }); }); describe("get updated list from remote file", () => { - it("shows 'test in morning' as test time set to 10am", async () => { + it("shows 'test in morning'", async () => { await helpers.startApplication("tests/configs/modules/compliments/compliments_file_change.js", "01 Jan 2022 10:00:00 GMT"); await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true); await new Promise((r) => setTimeout(r, 10000)); diff --git a/tests/mocks/3_move_first_allday_repeating_event.ics b/tests/mocks/3_move_first_allday_repeating_event.ics new file mode 100644 index 0000000000..d0587e35e1 --- /dev/null +++ b/tests/mocks/3_move_first_allday_repeating_event.ics @@ -0,0 +1,35 @@ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:TestCal +X-WR-TIMEZONE:Europe/Berlin +X-WR-CALDESC:Calendar for testing purposes +BEGIN:VEVENT +DTSTART;VALUE=DATE:20241011 +DTEND;VALUE=DATE:20241012 +RRULE:FREQ=WEEKLY;WKST=MO;COUNT=5;BYDAY=FR +DTSTAMP:20241009T153220Z +UID:2m6mt1p89l2anl74915ur3hsgm@google.com +CREATED:20241009T153058Z +LAST-MODIFIED:20241009T153205Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:TestCal_AllDayRepeatingEvent +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20241012 +DTEND;VALUE=DATE:20241013 +DTSTAMP:20241009T153220Z +UID:2m6mt1p89l2anl74915ur3hsgm@google.com +RECURRENCE-ID;VALUE=DATE:20241011 +CREATED:20241009T153058Z +LAST-MODIFIED:20241009T153205Z +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:TestCal_AllDayRepeatingEvent +TRANSP:TRANSPARENT +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/RepeatingEvent.Oct21.ics b/tests/mocks/RepeatingEvent.Oct21.ics new file mode 100644 index 0000000000..9eb6130960 --- /dev/null +++ b/tests/mocks/RepeatingEvent.Oct21.ics @@ -0,0 +1,28 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20241028T000000 +DTEND;TZID=Europe/Berlin:20241028T010000 +RRULE:FREQ=DAILY;COUNT=3 +DTSTAMP:20241020T093758Z +UID:053fdshnnibo92lu97rsoeqoti@google.com +CREATED:20241020T093230Z +LAST-MODIFIED:20241020T093230Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:RepeatingEventWeekAfterToday +TRANSP:OPAQUE +END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20241021T000000 +DTEND;TZID=Europe/Berlin:20241021T010000 +RRULE:FREQ=DAILY;COUNT=3 +DTSTAMP:20241020T093758Z +UID:1a6kk47pp61k4td2h9rlf0lv69@google.com +CREATED:20241020T093255Z +LAST-MODIFIED:20241020T093437Z +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:RepeatingEventDayAfterToday +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/chicago_late_in_timezone.ics b/tests/mocks/chicago_late_in_timezone.ics new file mode 100644 index 0000000000..2c9447723c --- /dev/null +++ b/tests/mocks/chicago_late_in_timezone.ics @@ -0,0 +1,15 @@ +BEGIN:VEVENT +CREATED:20240904T053053Z +DTEND;TZID=America/Chicago:20240910T211500 +DTSTAMP:20240925T005517Z +DTSTART;TZID=America/Chicago:20240910T201500 +LAST-MODIFIED:20240925T005515Z +LOCATION:Dance Class +RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:2D48CA37-FCE5-4E16-871 +9-1F47160BDBA3 +RRULE:FREQ=WEEKLY;UNTIL=20250601T011500Z +SEQUENCE:3 +SUMMARY:Wife Barre Class +UID:39669340-7AFD-4685-9BD6-6CE4B715486E +X-APPLE-CREATOR-IDENTITY:com.apple.mobilecal +END:VEVENT \ No newline at end of file diff --git a/tests/mocks/compliments_file.json b/tests/mocks/compliments_file.json index 89171b16ed..03e2e8b109 100644 --- a/tests/mocks/compliments_file.json +++ b/tests/mocks/compliments_file.json @@ -1,5 +1,3 @@ { - "morning": ["test in morning"], - "afternoon": ["test in afternoon"], - "evening": ["test in evening"] + "anytime": ["test in morning"] } diff --git a/tests/mocks/diff_tz_start_end.ics b/tests/mocks/diff_tz_start_end.ics new file mode 100644 index 0000000000..b59ba41ed4 --- /dev/null +++ b/tests/mocks/diff_tz_start_end.ics @@ -0,0 +1,14 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART:20241029T100000Z +DTEND:20241030T230000Z +DTSTAMP:20241022T203806Z +UID:04ivnntdi20rqsk0iesabsdhmj@google.com +CREATED:20241022T203738Z +LAST-MODIFIED:20241022T203738Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:start/end on diff tz +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/end_of_day_berlin_moved.ics b/tests/mocks/end_of_day_berlin_moved.ics new file mode 100644 index 0000000000..c5a02d0336 --- /dev/null +++ b/tests/mocks/end_of_day_berlin_moved.ics @@ -0,0 +1,54 @@ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:test for mirror +X-WR-TIMEZONE:America/Chicago +X-WR-CALDESC:used to test mirror +BEGIN:VTIMEZONE +TZID:Europe/Berlin +X-LIC-LOCATION:Europe/Berlin +BEGIN:DAYLIGHT +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:GMT+2 +DTSTART:19700329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:GMT+1 +DTSTART:19701025T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20241021T230000 +DTEND;TZID=Europe/Berlin:20241022T000000 +RRULE:FREQ=DAILY;WKST=SU;COUNT=3 +DTSTAMP:20241019T133432Z +UID:0kj3dtvgskhhpli1392n111145@google.com +CREATED:20241018T213040Z +LAST-MODIFIED:20241018T213126Z +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:test +TRANSP:OPAQUE +END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20241024T230000 +DTEND;TZID=Europe/Berlin:20241025T000000 +DTSTAMP:20241019T133432Z +UID:0kj3dtvgskhhpli1392n111145@google.com +RECURRENCE-ID;TZID=Europe/Berlin:20241021T230000 +CREATED:20241018T213040Z +LAST-MODIFIED:20241018T213126Z +SEQUENCE:2 +STATUS:CONFIRMED +SUMMARY:test +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR + diff --git a/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics b/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics new file mode 100644 index 0000000000..a12d58dd1c --- /dev/null +++ b/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics @@ -0,0 +1,14 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART:20241026T010000Z +DTEND:20241026T110000Z +DTSTAMP:20241024T153358Z +UID:4maud6s79m41a99pj2g7j5km0a@google.com +CREATED:20241024T153313Z +LAST-MODIFIED:20241024T153330Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Sleep over at Bobs +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/exdate_and_recurrence_together.ics b/tests/mocks/exdate_and_recurrence_together.ics new file mode 100644 index 0000000000..d366cc42df --- /dev/null +++ b/tests/mocks/exdate_and_recurrence_together.ics @@ -0,0 +1,48 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;TZID=America/Los_Angeles:20241023T143000 +DTEND;TZID=America/Los_Angeles:20241023T153000 +RRULE:FREQ=DAILY;COUNT=4 +EXDATE;TZID=America/Los_Angeles:20241025T143000 +DTSTAMP:20241021T193426Z +UID:18rd721lfqpue2o08icsqek198@google.com +CREATED:20241021T192450Z +DESCRIPTION:we will move one entry and delete another  ending w 3 of the 4  + start/end\, middle moved after end and 3rd deleted +LAST-MODIFIED:20241021T193419Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:recurrence and exclusion together +TRANSP:OPAQUE +END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=America/Los_Angeles:20241022T143000 +DTEND;TZID=America/Los_Angeles:20241022T153000 +DTSTAMP:20241021T193426Z +UID:18rd721lfqpue2o08icsqek198@google.com +RECURRENCE-ID;TZID=America/Los_Angeles:20241023T143000 +CREATED:20241021T192450Z +DESCRIPTION:we will move one entry and delete another  ending w 3 of the 4  + start/end\, middle moved after end and 3rd deleted +LAST-MODIFIED:20241021T193419Z +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:recurrence and exclusion together +TRANSP:OPAQUE +END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=America/Los_Angeles:20241027T143000 +DTEND;TZID=America/Los_Angeles:20241027T153000 +DTSTAMP:20241021T193426Z +UID:18rd721lfqpue2o08icsqek198@google.com +RECURRENCE-ID;TZID=America/Los_Angeles:20241024T143000 +CREATED:20241021T192450Z +DESCRIPTION:we will move one entry and delete another  ending w 3 of the 4  + start/end\, middle moved after end and 3rd deleted +LAST-MODIFIED:20241021T193419Z +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:recurrence and exclusion together +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics b/tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics new file mode 100644 index 0000000000..8d506e5479 --- /dev/null +++ b/tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics @@ -0,0 +1,15 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;VALUE=DATE:20241025 +DTEND;VALUE=DATE:20241031 +DTSTAMP:20241023T141110Z +UID:60nobfcu0ct96jgsh5nhcia24b@google.com +CREATED:20241023T141019Z +DESCRIPTION:test for all day end viewing +LAST-MODIFIED:20241023T141019Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:simple all day event over many days (not repeating) +TRANSP:TRANSPARENT +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/germany_at_end_of_day_repeating.ics b/tests/mocks/germany_at_end_of_day_repeating.ics new file mode 100644 index 0000000000..9a72df0aed --- /dev/null +++ b/tests/mocks/germany_at_end_of_day_repeating.ics @@ -0,0 +1,15 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20241022T230000 +DTEND;TZID=Europe/Berlin:20241023T000000 +RRULE:FREQ=DAILY;WKST=MO;COUNT=4 +DTSTAMP:20241009T153220Z +UID:2m6mt1p89l2anl74915ur3hsgm@google.com +CREATED:20241009T153058Z +LAST-MODIFIED:20241009T153205Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:TestCal_AllDayRepeatingEvent +TRANSP:TRANSPARENT +END:VEVENT +END:VCALENDAR \ No newline at end of file diff --git a/tests/mocks/whole_day_moved_over_dst_change_berlin.ics b/tests/mocks/whole_day_moved_over_dst_change_berlin.ics new file mode 100644 index 0000000000..7335ccfdb4 --- /dev/null +++ b/tests/mocks/whole_day_moved_over_dst_change_berlin.ics @@ -0,0 +1,28 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;VALUE=DATE:20241027 +DTEND;VALUE=DATE:20241028 +RRULE:FREQ=DAILY;WKST=SU;COUNT=3 +DTSTAMP:20241020T152634Z +UID:14nv8jl8d6dvdbl477lod4fftf@google.com +CREATED:20241020T152434Z +LAST-MODIFIED:20241020T152536Z +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:test whole day moved +TRANSP:TRANSPARENT +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20241030 +DTEND;VALUE=DATE:20241031 +DTSTAMP:20241020T152634Z +UID:14nv8jl8d6dvdbl477lod4fftf@google.com +RECURRENCE-ID;VALUE=DATE:20241028 +CREATED:20241020T152434Z +LAST-MODIFIED:20241020T152536Z +SEQUENCE:2 +STATUS:CONFIRMED +SUMMARY:test whole day moved +TRANSP:TRANSPARENT +END:VEVENT +END:VCALENDAR From 5b7b76c877f75f9fe67cdfada720f472f34b6d2b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 7 Dec 2024 10:12:28 +0100 Subject: [PATCH 155/418] Add linting for markdown files (#3646) I also reworked the Linters section in `CONTRIBUTING.md` a bit and switched the `prettier` config to a flat config. Co-authored-by: Veeck --- .github/CONTRIBUTING.md | 16 +- .github/workflows/automated-tests.yaml | 1 + .markdownlint.json | 6 + .prettierrc.json | 3 - CHANGELOG.md | 9 +- Collaboration.md | 2 + README.md | 20 +-- cspell.config.json | 1 + package-lock.json | 200 +++++++++++++++++++++++++ package.json | 3 + prettier.config.mjs | 13 ++ 11 files changed, 252 insertions(+), 22 deletions(-) create mode 100644 .markdownlint.json delete mode 100644 .prettierrc.json create mode 100644 prettier.config.mjs diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 1166747bd5..1f897d047e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -6,22 +6,28 @@ We hold our code to standard, and these standards are documented below. ## Linters -We use prettier for automatic linting of all our files: `npm run lint:prettier`. +We use [prettier](https://prettier.io/) for automatic formatting a lot all our files. The configuration is in our `prettier.config.mjs` file. -### JavaScript: Run ESLint +To run prettier, use `npm run lint:prettier`. -We use [ESLint](https://eslint.org) on our JavaScript files. +### JavaScript: Run ESLint -The ESLint configuration is in our `eslint.config.mjs` file. +We use [ESLint](https://eslint.org) to lint our JavaScript files. The configuration is in our `eslint.config.mjs` file. To run ESLint, use `npm run lint:js`. ### CSS: Run StyleLint -We use [StyleLint](https://stylelint.io) to lint our CSS. Our configuration is in our `.stylelintrc` file. +We use [StyleLint](https://stylelint.io) to lint our CSS. The configuration is in our `.stylelintrc.json` file. To run StyleLint, use `npm run lint:css`. +### Markdown: Run markdownlint + +We use [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) to lint our markdown files. The configuration is in our `.markdownlint.json` file. + +To run markdownlint, use `npm run markdownlint:css`. + ## Testing We use [Jest](https://jestjs.io) for JavaScript testing. diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 1c64d3a727..cf083cbf46 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -39,4 +39,5 @@ jobs: npm run test:prettier npm run test:js npm run test:css + npm run test:markdown npm run test diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000000..f5202cdfe0 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,6 @@ +{ + "line_length": false, + "no-duplicate-heading": false, + "no-inline-html": false, + "no-trailing-punctuation": false +} diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 1518304d4c..0000000000 --- a/.prettierrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "trailingComma": "none" -} diff --git a/CHANGELOG.md b/CHANGELOG.md index e3cef7e281..af4a01a28f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,12 @@ _This release is scheduled to be released on 2025-01-01._ - [core] Add wayland and windows start options to `package.json` (#3594) - [docs] Add step for npm publishing in release process (#3595) - [core] Add GitHub workflow to run spellcheck a few days before each release (#3623) -- [core] Add intest flag to index.html to pass to module js for test mode detection (needed by #3630) -- [compliments] add support for refreshing remote compliments file, and testcases (#3630) +- [core] Add test flag to index.html to pass to module js for test mode detection (needed by #3630) +- [core] Add export on animation names (#3644) +- [compliments] add support for refreshing remote compliments file, and test cases (#3630) - [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) -- [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` -- [core] Add export on animation names +- [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643) +- [linter] Add linting for markdown files. - [calendar] - added ability to display end date for full date events, where end is not same day (showEnd=true) ### Removed diff --git a/Collaboration.md b/Collaboration.md index b61ca52826..52b4f80755 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -1,3 +1,5 @@ +# Collaboration + This document describes how collaborators of this repository should work together. ## Pull Requests diff --git a/README.md b/README.md index 751637ca8b..7bc585c9c4 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -![MagicMirror²: The open source modular smart mirror platform. ](.github/header.png) +# ![MagicMirror²: The open source modular smart mirror platform.](.github/header.png)

- License - - GitHub Actions - Build Status - - - + License + + GitHub Actions + Build Status + + GitHub Stars +

**MagicMirror²** is an open source modular smart mirror platform. With a growing list of installable modules, the **MagicMirror²** allows you to convert your hallway or bathroom mirror into your personal assistant. **MagicMirror²** is built by the creator of [the original MagicMirror](https://michaelteeuw.nl/tagged/magicmirror) with the incredible help of a [growing community of contributors](https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors). @@ -24,7 +24,7 @@ For the full documentation including **[installation instructions](https://docs. - Website: [https://magicmirror.builders](https://magicmirror.builders) - Documentation: [https://docs.magicmirror.builders](https://docs.magicmirror.builders) - Forum: [https://forum.magicmirror.builders](https://forum.magicmirror.builders) - - Technical discussions: https://forum.magicmirror.builders/category/11/core-system + - Technical discussions: - Discord: [https://discord.gg/J5BAtvx](https://discord.gg/J5BAtvx) - Blog: [https://michaelteeuw.nl/tagged/magicmirror](https://michaelteeuw.nl/tagged/magicmirror) - Donations: [https://magicmirror.builders/#donate](https://magicmirror.builders/#donate) @@ -49,5 +49,5 @@ If we receive enough donations we might even be able to free up some working hou To donate, please follow [this](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G5D8E9MR5DTD2&source=url) link.

- MagPi Top 50 + MagPi Top 50

diff --git a/cspell.config.json b/cspell.config.json index ba8aa98e14..5a27b4121a 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -198,6 +198,7 @@ "tada", "taglist", "Teeuw", + "TESTMODE", "thomasrockhu", "tomzt", "ukmetoffice", diff --git a/package-lock.json b/package-lock.json index 4c2a3adb81..312e72de94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", + "markdownlint-cli2": "^0.15.0", "playwright": "^1.48.2", "prettier": "^3.3.3", "sinon": "^19.0.2", @@ -2482,6 +2483,19 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", @@ -8499,6 +8513,13 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -8613,6 +8634,16 @@ "dev": true, "license": "MIT" }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/lint-staged": { "version": "15.2.10", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", @@ -8985,6 +9016,138 @@ "tmpl": "1.0.5" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdownlint": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.36.1.tgz", + "integrity": "sha512-s73fU2CQN7WCgjhaQUQ8wYESQNzGRNOKDd+3xgVqu8kuTEhmwepd/mxOv1LR2oV046ONrTLBFsM7IoKWNvmy5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "markdown-it": "14.1.0", + "markdownlint-micromark": "0.1.12" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-cli2": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.15.0.tgz", + "integrity": "sha512-4P/lnxQxU2R5lywRJs4b2ajm8z65CW8qqR1bTIcdQ5EG+nZpC6HJlJUnmIR5ee+uecUkoMroazxWcLB7etSmrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "14.0.2", + "js-yaml": "4.1.0", + "jsonc-parser": "3.3.1", + "markdownlint": "0.36.1", + "markdownlint-cli2-formatter-default": "0.0.5", + "micromatch": "4.0.8" + }, + "bin": { + "markdownlint-cli2": "markdownlint-cli2.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-cli2-formatter-default": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.5.tgz", + "integrity": "sha512-4XKTwQ5m1+Txo2kuQ3Jgpo/KmnG+X90dWt4acufg6HVGadTUG5hzHF/wssp9b5MBYOMCnZ9RMPaU//uHsszF8Q==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + }, + "peerDependencies": { + "markdownlint-cli2": ">=0.0.4" + } + }, + "node_modules/markdownlint-cli2/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdownlint-cli2/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdownlint-cli2/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdownlint-micromark": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.12.tgz", + "integrity": "sha512-RlB6EwMGgc0sxcIhOQ2+aq7Zw1V2fBnzbXKGgYK/mVWdT7cz34fteKSwfYeo4rL6+L/q2tyC9QtD/PgZbkdyJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -9016,6 +9179,13 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -10442,6 +10612,16 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -12512,6 +12692,13 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, "node_modules/uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", @@ -12546,6 +12733,19 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", diff --git a/package.json b/package.json index 8e6f4108a7..d2200a6149 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "install-vendor": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix", "lint:js": "eslint . --fix", + "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", "lint:staged": "lint-staged", "postinstall": "npm run install-vendor && npm run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"", @@ -51,6 +52,7 @@ "test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit", "test:electron": "NODE_ENV=test jest --selectProjects electron -i --forceExit", "test:js": "eslint .", + "test:markdown": "markdownlint-cli2 .", "test:prettier": "prettier . --check", "test:spelling": "cspell . --gitignore", "test:unit": "NODE_ENV=test jest --selectProjects unit" @@ -92,6 +94,7 @@ "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.2.10", + "markdownlint-cli2": "^0.15.0", "playwright": "^1.48.2", "prettier": "^3.3.3", "sinon": "^19.0.2", diff --git a/prettier.config.mjs b/prettier.config.mjs new file mode 100644 index 0000000000..7ec216b40b --- /dev/null +++ b/prettier.config.mjs @@ -0,0 +1,13 @@ +const config = { + overrides: [ + { + files: "*.md", + options: { + parser: "markdown" + } + } + ], + trailingComma: "none" +}; + +export default config; From 76fac78909b080ddf0c7d2e332e1a47880017df7 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 7 Dec 2024 18:29:49 +0100 Subject: [PATCH 156/418] Run code style checks in workflow only once (#3648) It's enough if the code style checks are successful once, it's not necessary to run them with every node version. Also, if there is an error, we can see more quickly whether it is a code style or a test-runner issue. --- .github/workflows/automated-tests.yaml | 24 ++++++++++++++++++++---- CHANGELOG.md | 12 ++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index cf083cbf46..8de8a641c7 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -13,6 +13,26 @@ permissions: contents: read jobs: + code-style-check: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: "Checkout code" + uses: actions/checkout@v4 + - name: "Use Node.js" + uses: actions/setup-node@v4 + with: + node-version: 23 + cache: "npm" + - name: "Install dependencies" + run: | + npm run install-mm:dev + - name: "Run linter tests" + run: | + npm run test:prettier + npm run test:js + npm run test:css + npm run test:markdown test: runs-on: ubuntu-latest timeout-minutes: 30 @@ -36,8 +56,4 @@ jobs: Xvfb :99 -screen 0 1024x768x16 & export DISPLAY=:99 touch css/custom.css - npm run test:prettier - npm run test:js - npm run test:css - npm run test:markdown npm run test diff --git a/CHANGELOG.md b/CHANGELOG.md index af4a01a28f..1c9481b479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,14 +16,18 @@ _This release is scheduled to be released on 2025-01-01._ - [core] Add wayland and windows start options to `package.json` (#3594) - [docs] Add step for npm publishing in release process (#3595) - [core] Add GitHub workflow to run spellcheck a few days before each release (#3623) -- [core] Add test flag to index.html to pass to module js for test mode detection (needed by #3630) +- [core] Add test flag to `index.html` to pass to module js for test mode detection (needed by #3630) - [core] Add export on animation names (#3644) -- [compliments] add support for refreshing remote compliments file, and test cases (#3630) +- [compliments] Add support for refreshing remote compliments file, and test cases (#3630) - [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643) -- [linter] Add linting for markdown files. +- [linter] Add linting for markdown files (#3646) - [calendar] - added ability to display end date for full date events, where end is not same day (showEnd=true) +### Changed + +- [core] Run code style checks in workflow only once. + ### Removed - [tests] Remove `node-pty` and `drivelist` from rebuilded test (#3575) @@ -31,7 +35,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated -- [repo] reactivated `stale.yaml` as github action to mark issues as stale after 60 days and close them 7 days later (if no activity) +- [repo] Reactivate `stale.yaml` as GitHub action to mark issues as stale after 60 days and close them 7 days later (if no activity) (#3577, #3580, #3581) - [core] Update electron dependency to v32 (test electron rebuild) and other dependencies too - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) - [core] Run and test with node 23 (#3588) From 39ab651319daadd72011ecc48cb2b8715e82b07e Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sun, 8 Dec 2024 09:24:39 -0600 Subject: [PATCH 157/418] Show animations, fix export only on server side (#3649) fix #3644 so only on server side --- CHANGELOG.md | 1 + js/animateCSS.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c9481b479..8634bbb06c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Changed - [core] Run code style checks in workflow only once. +- [core] fix animations export #3644 only on server side ### Removed diff --git a/js/animateCSS.js b/js/animateCSS.js index a503e1067b..c8f2924e8f 100644 --- a/js/animateCSS.js +++ b/js/animateCSS.js @@ -155,4 +155,4 @@ function removeAnimateCSS (element, animation) { node.classList.remove("animate__animated", animationName); node.style.removeProperty("--animate-duration"); } -module.exports = { AnimateCSSIn, AnimateCSSOut }; +if (typeof window === "undefined") module.exports = { AnimateCSSIn, AnimateCSSOut }; From 5232f46d4458d20ef09193ec2351e0ddb562fbf1 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sun, 8 Dec 2024 14:23:53 -0600 Subject: [PATCH 158/418] fix #3267 again this time, dropped from big cal update (#3650) this change was dropped from #3267 by mistake --- CHANGELOG.md | 1 + modules/default/calendar/calendar.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8634bbb06c..18e8f9ebd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ _This release is scheduled to be released on 2025-01-01._ - [calendar] - fix showEndsOnlyWithDuration not working, #3598, applies ONLY to full day events - [calendar] - fix showEnd for Full Day events #3602 - [tests] Suppress "module is not defined" in e2e tests +- [calendar] - fixes #3267 (styles array, really this time!) ## [2.29.0] - 2024-10-01 diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 6af652ba77..c97f353e32 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -907,9 +907,9 @@ Module.register("calendar", { let p = this.getCalendarProperty(url, property, defaultValue); if (property === "symbol" || property === "recurringSymbol" || property === "fullDaySymbol") { const className = this.getCalendarProperty(url, "symbolClassName", this.config.defaultSymbolClassName); - p = className + p; + if (p instanceof Array) p.push(className); + else p = className + p; } - if (!(p instanceof Array)) p = [p]; return p; }, From 5b3b40da661835c4c5ee4e8cbbd3121934827aab Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 18 Dec 2024 08:00:00 +0100 Subject: [PATCH 159/418] Use project URL in fallback config (#3656) --- CHANGELOG.md | 25 +++++++++++++------------ js/defaults.js | 2 +- tests/e2e/modules_empty_spec.js | 4 ++-- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e8f9ebd9..e9e3ce8d7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,12 +22,13 @@ _This release is scheduled to be released on 2025-01-01._ - [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643) - [linter] Add linting for markdown files (#3646) -- [calendar] - added ability to display end date for full date events, where end is not same day (showEnd=true) +- [calendar] Add ability to display end date for full date events, where end is not same day (showEnd=true) (#3650) ### Changed -- [core] Run code style checks in workflow only once. -- [core] fix animations export #3644 only on server side +- [core] Run code style checks in workflow only once (#3648) +- [core] Fix animations export #3644 only on server side (#3649) +- [core] Use project URL in fallback config. ### Removed @@ -45,18 +46,18 @@ _This release is scheduled to be released on 2025-01-01._ - [updatenotification] Fix pm2 using detection when pm2 script is inside or outside MagicMirror root folder (#3576) (#3605) (#3626) (#3628) - [core] Fix loading node_helper of modules: avoid black screen, display errors and continue loading with next module (#3578) -- [weather] changed default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) -- [tests] fix electron tests with mock dates, the mock on server side was missing (#3597) -- [tests] fix testcases with hard coded Date.now (#3597) +- [weather] Change default value for weatherEndpoint of provider openweathermap to "/onecall" (#3574) +- [tests] Fix electron tests with mock dates, the mock on server side was missing (#3597) +- [tests] Fix testcases with hard coded Date.now (#3597) - [core] Fix missing `basePath` where `location.host` is used (#3613) - [compliments] croner library changed filenames used in latest version (#3624) - [linter] Fix ESLint ignore pattern which caused that default modules not to be linted (#3632) -- [calendar] - update to resolve issues #3098 #3144 #3351 #3422 #3443 #3467 #3537 related to timezone changes -- [calendar] - fixes #3267 (styles array), also fixes event with both exdate AND recurrence(and testcase) -- [calendar] - fix showEndsOnlyWithDuration not working, #3598, applies ONLY to full day events -- [calendar] - fix showEnd for Full Day events #3602 -- [tests] Suppress "module is not defined" in e2e tests -- [calendar] - fixes #3267 (styles array, really this time!) +- [calendar] Update to resolve issues #3098 #3144 #3351 #3422 #3443 #3467 #3537 related to timezone changes +- [calendar] Fix #3267 (styles array), also fixes event with both exdate AND recurrence(and testcase) +- [calendar] Fix showEndsOnlyWithDuration not working, #3598, applies ONLY to full day events +- [calendar] Fix showEnd for Full Day events (#3602) +- [tests] Suppress "module is not defined" in e2e tests (#3647) +- [calendar] Fix #3267 (styles array, really this time!) ## [2.29.0] - 2024-10-01 diff --git a/js/defaults.js b/js/defaults.js index f3a894d6a9..ce16b1e95c 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -70,7 +70,7 @@ const defaults = { position: "bottom_bar", classes: "xsmall dimmed", config: { - text: "www.michaelteeuw.nl" + text: "https://magicmirror.builders/" } } ] diff --git a/tests/e2e/modules_empty_spec.js b/tests/e2e/modules_empty_spec.js index 535e3141c8..e5a4cd6670 100644 --- a/tests/e2e/modules_empty_spec.js +++ b/tests/e2e/modules_empty_spec.js @@ -15,9 +15,9 @@ describe("Check configuration without modules", () => { expect(elem.textContent).toContain("MagicMirror²"); }); - it("shows the url of michael's website", async () => { + it("shows the project URL", async () => { const elem = await helpers.waitForElement("#module_5_helloworld .module-content"); expect(elem).not.toBeNull(); - expect(elem.textContent).toContain("www.michaelteeuw.nl"); + expect(elem.textContent).toContain("https://magicmirror.builders/"); }); }); From 786eacf41ac68ee3e166400722ac1066e3fa83a0 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Wed, 18 Dec 2024 06:43:20 -0600 Subject: [PATCH 160/418] update config.js.sample about locale variable (#3655) add text to config.js.sample about usage of locale variable/property Co-authored-by: Veeck --- CHANGELOG.md | 1 + config/config.js.sample | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9e3ce8d7d..4bd35f0e34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ _This release is scheduled to be released on 2025-01-01._ - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643) - [linter] Add linting for markdown files (#3646) - [calendar] Add ability to display end date for full date events, where end is not same day (showEnd=true) (#3650) +- [core] Add text to the config.js.sample file about the locale variable (#3654) ### Changed diff --git a/config/config.js.sample b/config/config.js.sample index 56edb59df8..1526b0f60b 100644 --- a/config/config.js.sample +++ b/config/config.js.sample @@ -28,7 +28,11 @@ let config = { httpsCertificate: "", // HTTPS Certificate path, only require when useHttps is true language: "en", - locale: "en-US", + locale: "en-US", // this variable is provided as a consistent location + // it is currently only used by 3rd party modules. no MagicMirror code uses this value + // as we have no usage, we have no constraints on what this field holds + // see https://en.wikipedia.org/wiki/Locale_(computer_software) for the possibilities + logLevel: ["INFO", "LOG", "WARN", "ERROR"], // Add "DEBUG" for even more logging timeFormat: 24, units: "metric", From 24d9b70c4c5a511bea113fd6346dfe7a3e6df0d1 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Wed, 18 Dec 2024 10:37:51 -0600 Subject: [PATCH 161/418] fix access denied fault error writing js/positions.js (#3652) if the MagicMirror js folder is not writable (synology nas created by different user than docker container) there is an uncaught throw ``` [ERROR] EACCES: permission denied, open 'js/positions.js' ``` add try/catch, output new message, console.error ```text unable to write js/positions.js with the discovered module positions make the MagicMirror/js folder writeable by the user starting MagicMirror ``` MM will start, but no modules will show, as no positions were discovered this file is used to pass the list from the server side to the browser side fixes #3651 --- CHANGELOG.md | 1 + js/utils.js | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bd35f0e34..c19de0a317 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ _This release is scheduled to be released on 2025-01-01._ - [core] Run code style checks in workflow only once (#3648) - [core] Fix animations export #3644 only on server side (#3649) - [core] Use project URL in fallback config. +- [core] fix Access Denied crash writing js/positions.js (on synology nas) #3651. new message, MM starts, but no modules showing ### Removed diff --git a/js/utils.js b/js/utils.js index 9536a1b070..d4b90223ed 100644 --- a/js/utils.js +++ b/js/utils.js @@ -65,7 +65,12 @@ module.exports = { modulePositions.push(positionName); } }); - fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`); + try { + fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`); + } + catch (error) { + console.error("unable to write js/positions.js with the discovered module positions\nmake the MagicMirror/js folder writeable by the user starting MagicMirror"); + } } // return the list to the caller return modulePositions; From b910c60eb20bf1724b0fa93b88dba61a80c2b2c4 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 18 Dec 2024 22:04:16 +0100 Subject: [PATCH 162/418] update dependencies (#3657) --- CHANGELOG.md | 2 +- package-lock.json | 2664 ++++++++++++++++++++------------------ package.json | 34 +- vendor/package-lock.json | 9 +- vendor/package.json | 2 +- 5 files changed, 1440 insertions(+), 1271 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c19de0a317..9c895706c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated - [repo] Reactivate `stale.yaml` as GitHub action to mark issues as stale after 60 days and close them 7 days later (if no activity) (#3577, #3580, #3581) -- [core] Update electron dependency to v32 (test electron rebuild) and other dependencies too +- [core] Update electron dependency to v32 (test electron rebuild) and other dependencies - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) - [core] Run and test with node 23 (#3588) diff --git a/package-lock.json b/package-lock.json index 312e72de94..9cb5b683ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,11 +11,11 @@ "license": "MIT", "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.3.2", + "ansis": "^3.4.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.14.0", - "express": "^4.21.1", + "eslint": "^9.17.0", + "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^8.0.0", @@ -27,25 +27,25 @@ "pm2": "^5.4.2", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.5" + "systeminformation": "^5.23.14" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.10.1", - "cspell": "^8.15.7", + "@stylistic/eslint-plugin": "^2.12.1", + "cspell": "^8.17.1", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.4.3", - "eslint-plugin-package-json": "^0.17.0", + "eslint-plugin-jest": "^28.9.0", + "eslint-plugin-jsdoc": "^50.6.1", + "eslint-plugin-package-json": "^0.18.0", "express-basic-auth": "^1.2.1", - "husky": "^9.1.6", + "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^25.0.1", - "lint-staged": "^15.2.10", - "markdownlint-cli2": "^0.15.0", - "playwright": "^1.48.2", - "prettier": "^3.3.3", + "lint-staged": "^15.2.11", + "markdownlint-cli2": "^0.16.0", + "playwright": "^1.49.1", + "prettier": "^3.4.2", "sinon": "^19.0.2", - "stylelint": "^16.10.0", + "stylelint": "^16.12.0", "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.2" }, @@ -53,7 +53,7 @@ "node": ">=20.9.0 <21 || 22 || >=23" }, "optionalDependencies": { - "electron": "^32.2.2" + "electron": "^32.2.7" } }, "node_modules/@altano/repository-tools": { @@ -78,13 +78,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -92,9 +93,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", "dev": true, "license": "MIT", "engines": { @@ -102,22 +103,22 @@ } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -143,31 +144,32 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6", + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -186,30 +188,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -219,33 +220,19 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "license": "MIT", "engines": { @@ -253,9 +240,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "license": "MIT", "engines": { @@ -263,9 +250,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "license": "MIT", "engines": { @@ -273,121 +260,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.26.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -452,13 +345,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", - "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -494,13 +387,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -620,13 +513,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", - "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -636,32 +529,32 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -680,15 +573,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -702,9 +594,9 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.15.7.tgz", - "integrity": "sha512-lNbrlHhDnOWCJh/vNCliZJz4X1KMEZqWJZpTgmdPrEGS9ZyfEiCmZyoQzw+fauC5Xo7dwd2KdS9VMHftAJqMPQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.1.tgz", + "integrity": "sha512-HmkXS5uX4bk/XxsRS4Q+zRvhgRa81ddGiR2/Xfag9MIi5L5UnEJ4g21EpmIlXkMxYrTu2fp69SZFss5NfcFF9Q==", "dev": true, "license": "MIT", "dependencies": { @@ -712,8 +604,8 @@ "@cspell/dict-al": "^1.0.3", "@cspell/dict-aws": "^4.0.7", "@cspell/dict-bash": "^4.1.8", - "@cspell/dict-companies": "^3.1.7", - "@cspell/dict-cpp": "^6.0.0", + "@cspell/dict-companies": "^3.1.8", + "@cspell/dict-cpp": "^6.0.2", "@cspell/dict-cryptocurrencies": "^5.0.3", "@cspell/dict-csharp": "^4.0.5", "@cspell/dict-css": "^4.0.16", @@ -722,17 +614,17 @@ "@cspell/dict-docker": "^1.1.11", "@cspell/dict-dotnet": "^5.0.8", "@cspell/dict-elixir": "^4.0.6", - "@cspell/dict-en_us": "^4.3.26", + "@cspell/dict-en_us": "^4.3.28", "@cspell/dict-en-common-misspellings": "^2.0.7", "@cspell/dict-en-gb": "1.1.33", - "@cspell/dict-filetypes": "^3.0.8", + "@cspell/dict-filetypes": "^3.0.9", "@cspell/dict-flutter": "^1.0.3", "@cspell/dict-fonts": "^4.0.3", "@cspell/dict-fsharp": "^1.0.4", "@cspell/dict-fullstack": "^3.2.3", - "@cspell/dict-gaming-terms": "^1.0.8", + "@cspell/dict-gaming-terms": "^1.0.9", "@cspell/dict-git": "^3.0.3", - "@cspell/dict-golang": "^6.0.16", + "@cspell/dict-golang": "^6.0.17", "@cspell/dict-google": "^1.0.4", "@cspell/dict-haskell": "^4.0.4", "@cspell/dict-html": "^4.0.10", @@ -746,17 +638,17 @@ "@cspell/dict-makefile": "^1.0.3", "@cspell/dict-markdown": "^2.0.7", "@cspell/dict-monkeyc": "^1.0.9", - "@cspell/dict-node": "^5.0.4", - "@cspell/dict-npm": "^5.1.9", + "@cspell/dict-node": "^5.0.5", + "@cspell/dict-npm": "^5.1.17", "@cspell/dict-php": "^4.0.13", "@cspell/dict-powershell": "^5.0.13", "@cspell/dict-public-licenses": "^2.0.11", - "@cspell/dict-python": "^4.2.12", + "@cspell/dict-python": "^4.2.13", "@cspell/dict-r": "^2.0.4", "@cspell/dict-ruby": "^5.0.7", - "@cspell/dict-rust": "^4.0.9", + "@cspell/dict-rust": "^4.0.10", "@cspell/dict-scala": "^5.0.6", - "@cspell/dict-software-terms": "^4.1.12", + "@cspell/dict-software-terms": "^4.1.19", "@cspell/dict-sql": "^2.1.8", "@cspell/dict-svelte": "^1.0.5", "@cspell/dict-swift": "^2.0.4", @@ -769,22 +661,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.15.7.tgz", - "integrity": "sha512-kOcJaThztX1A8jkALBiAyp8dWrHPMuDOXki8Q5ZG1dL25wKsAnPyqflXhXg6Up4VGVIkkgy1S3T0Q/i+G5f12w==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.1.tgz", + "integrity": "sha512-EV9Xkh42Xw3aORvDZfxusICX91DDbqQpYdGKBdPGuhgxWOUYYZKpLXsHCmDkhruMPo2m5gDh++/OqjLRPZofKQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.15.7" + "@cspell/cspell-types": "8.17.1" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.15.7.tgz", - "integrity": "sha512-EyVSJPqJFrDA9Sj4Nzx13vytloMS0V3HaevhqMFLHJ53QNz/ZP7vuECbXApRAJwLonuToJBvY3b9xzB6eEhU/A==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.1.tgz", + "integrity": "sha512-uhC99Ox+OH3COSgShv4fpVHiotR70dNvAOSkzRvKVRzV6IGyFnxHjmyVVPEV0dsqzVLxltwYTqFhwI+UOwm45A==", "dev": true, "license": "MIT", "engines": { @@ -792,9 +684,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.15.7.tgz", - "integrity": "sha512-9RPZ5VwjYPYLTLWkoPGHqV3Kuai5QwTWgZJW3Yk2GgJkxss/LDsXME+9CalPcPBQpnCIBEOtE2DjDQbFjAiMnA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.1.tgz", + "integrity": "sha512-XEK2ymTdQNgsV3ny60VkKzWskbICl4zNXh/DbxsoRXHqIRg43MXFpTNkEJ7j873EqdX7BU4opQQ+5D4stWWuhQ==", "dev": true, "license": "MIT", "dependencies": { @@ -805,9 +697,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.15.7.tgz", - "integrity": "sha512-kL+1+K4VApdwZccGlg7Vjmh4CzzjoT+G556/gErdESQFPY0y9/4OPPVKLrFkbEDODtp9Py7aTRHdhl6w1xxCCw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.1.tgz", + "integrity": "sha512-2sFWQtMEWZ4tdz7bw0bAx4NaV1t0ynGfjpuKWdQppsJFKNb+ZPZZ6Ah1dC13AdRRMZaG194kDRFwzNvRaCgWkQ==", "dev": true, "license": "MIT", "engines": { @@ -815,9 +707,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.15.7.tgz", - "integrity": "sha512-QMbGJsUXTdV8/V9Gsc/kBgdkBwm4hvcChhQf6KE9yeg3CZlbd95NkFJuSiqp1phJOWMTzHCZ0Ro7v7P/LGKdVA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.1.tgz", + "integrity": "sha512-NJbov7Jp57fh8addoxesjb8atg/APQfssCH5Q9uZuHBN06wEJDgs7fhfE48bU+RBViC9gltblsYZzZZQKzHYKg==", "dev": true, "license": "MIT", "engines": { @@ -853,16 +745,16 @@ "license": "MIT" }, "node_modules/@cspell/dict-companies": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.7.tgz", - "integrity": "sha512-ncVs/efuAkP1/tLDhWbXukBjgZ5xOUfe03neHMWsE8zvXXc5+Lw6TX5jaJXZLOoES/f4j4AhRE20jsPCF5pm+A==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.9.tgz", + "integrity": "sha512-w7XEJ2B6x2jq9ws5XNyYgpYj2MxdZ3jW3PETLxjK7nc8pulCFmaGVgZ0JTnDWfJ3QMOczoagn5f9LM2PZ/CuJg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.0.tgz", - "integrity": "sha512-z9Mv3/Ool19aw/kl1C+NmLdHF5WN6XCDmP4UkM/sYIfBO4WMUmrhiKiqK/pzSih9jyC5C2AuxujtB/IdHmyfVg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.2.tgz", + "integrity": "sha512-yw5eejWvY4bAnc6LUA44m4WsFwlmgPt2uMSnO7QViGMBDuoeopMma4z9XYvs4lSjTi8fIJs/A1YDfM9AVzb8eg==", "dev": true, "license": "MIT" }, @@ -930,9 +822,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.26", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.26.tgz", - "integrity": "sha512-hDbHYJsi3UgU1J++B0WLiYhWQdsmve3CH53FIaMRAdhrWOHcuw7h1dYkQXHFEP5lOjaq53KUHp/oh5su6VkIZg==", + "version": "4.3.28", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.28.tgz", + "integrity": "sha512-BN1PME7cOl7DXRQJ92pEd1f0Xk5sqjcDfThDGkKcsgwbSOY7KnTc/czBW6Pr3WXIchIm6cT12KEfjNqx7U7Rrw==", "dev": true, "license": "MIT" }, @@ -951,9 +843,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.8.tgz", - "integrity": "sha512-D3N8sm/iptzfVwsib/jvpX+K/++rM8SRpLDFUaM4jxm8EyGmSIYRbKZvdIv5BkAWmMlTWoRqlLn7Yb1b11jKJg==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.9.tgz", + "integrity": "sha512-U7ycC1cE32A5aEgwzp/iE0TVabonUFnVt+Ygbf6NsIWqEuFWZgZChC7gfztA4T1fpuj602nFdp7eOnTWKORsnQ==", "dev": true, "license": "MIT" }, @@ -986,9 +878,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-gaming-terms": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.8.tgz", - "integrity": "sha512-7OL0zTl93WFWhhtpXFrtm9uZXItC3ncAs8d0iQDMMFVNU1rBr6raBNxJskxE5wx2Ant12fgI66ZGVagXfN+yfA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.9.tgz", + "integrity": "sha512-AVIrZt3YiUnxsUzzGYTZ1XqgtkgwGEO0LWIlEf+SiDUEVLtv4CYmmyXFQ+WXDN0pyJ0wOwDazWrP0Cu7avYQmQ==", "dev": true, "license": "MIT" }, @@ -1000,9 +892,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-golang": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.16.tgz", - "integrity": "sha512-hZOBlgcguv2Hdc93n2zjdAQm1j3grsN9T9WhPnQ1wh2vUDoCLEujg+6gWhjcLb8ECOcwZTWgNyQLWeOxEsAj/w==", + "version": "6.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.17.tgz", + "integrity": "sha512-uDDLEJ/cHdLiqPw4+5BnmIo2i/TSR+uDvYd6JlBjTmjBKpOCyvUgYRztH7nv5e7virsN5WDiUWah4/ATQGz4Pw==", "dev": true, "license": "MIT" }, @@ -1104,16 +996,16 @@ "license": "MIT" }, "node_modules/@cspell/dict-node": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.4.tgz", - "integrity": "sha512-Hz5hiuOvZTd7Cp1IBqUZ7/ChwJeQpD5BJuwCaDn4mPNq4iMcQ1iWBYMThvNVqCEDgKv63X52nT8RAWacss98qg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.5.tgz", + "integrity": "sha512-7NbCS2E8ZZRZwlLrh2sA0vAk9n1kcTUiRp/Nia8YvKaItGXLfxYqD2rMQ3HpB1kEutal6hQLVic3N2Yi1X7AaA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.9.tgz", - "integrity": "sha512-ZH10gepefFee03SYQXH4mMmYbI3iwwEg5+B0ujsUohGJR789SyieelY0xPiDeh1y9gcQAp62k1QxbUwpcCYe5A==", + "version": "5.1.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.18.tgz", + "integrity": "sha512-/Nukl+DSxtEWSlb8svWFSpJVctAsM9SP+f5Q1n+qdDcXNKMb1bUCo/d3QZPwyOhuMjDawnsGBUAfp+iq7Mw83Q==", "dev": true, "license": "MIT" }, @@ -1139,9 +1031,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.12.tgz", - "integrity": "sha512-U25eOFu+RE0aEcF2AsxZmq3Lic7y9zspJ9SzjrC0mfJz+yr3YmSCw4E0blMD3mZoNcf7H/vMshuKIY5AY36U+Q==", + "version": "4.2.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.13.tgz", + "integrity": "sha512-mZIcmo9qif8LkJ6N/lqTZawcOk2kVTcuWIUOSbMcjyomO0XZ7iWz15TfONyr03Ea/l7o5ULV+MZ4vx76bAUb7w==", "dev": true, "license": "MIT", "dependencies": { @@ -1163,9 +1055,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-rust": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.9.tgz", - "integrity": "sha512-Dhr6TIZsMV92xcikKIWei6p/qswS4M+gTkivpWwz4/1oaVk2nRrxJmCdRoVkJlZkkAc17rjxrS12mpnJZI0iWw==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.10.tgz", + "integrity": "sha512-6o5C8566VGTTctgcwfF3Iy7314W0oMlFFSQOadQ0OEdJ9Z9ERX/PDimrzP3LGuOrvhtEFoK8pj+BLnunNwRNrw==", "dev": true, "license": "MIT" }, @@ -1177,9 +1069,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.12.tgz", - "integrity": "sha512-MHDAK/WlEdMJiDQ6lJ3SF7VogdfJcRXGYWfO4v90rxW8HDVfKDXVk3zpJhjoZGq56ujR1qmeYkQsM6MlB69uJA==", + "version": "4.1.20", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.20.tgz", + "integrity": "sha512-ma51njqbk9ZKzZF9NpCZpZ+c50EwR5JTJ2LEXlX0tX+ExVbKpthhlDLhT2+mkUh5Zvj+CLf5F9z0qB4+X3re/w==", "dev": true, "license": "MIT" }, @@ -1226,12 +1118,13 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.15.7.tgz", - "integrity": "sha512-qFlVisdP2lvFcS4Kre4Dl+f4Y7U9w/Y7IQAS+XXl5KlInImMaYhNUDEru8DoUPQHYsXKAPJsu/Y2JloHNE502Q==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.1.tgz", + "integrity": "sha512-XQtr2olYOtqbg49E+8SISd6I5DzfxmsKINDn0ZgaTFeLalnNdF3ewDU4gOEbApIzGffRa1mW9t19MsiVrznSDw==", "dev": true, "license": "MIT", "dependencies": { + "@cspell/url": "8.17.1", "import-meta-resolve": "^4.1.0" }, "engines": { @@ -1239,9 +1132,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.15.7.tgz", - "integrity": "sha512-MeP6gh8Om9vHSxYoYey2BFCib4m+vEyMLQCSub1Gk+uXiJjj1l/S5MFWM9zHhjGBBNNdvuopuUKP6Gcgcw+3Cw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.1.tgz", + "integrity": "sha512-AxYw6j7EPYtDFAFjwybjFpMc9waXQzurfBXmEVfQ5RQRlbylujLZWwR6GnMqofeNg4oGDUpEjcAZFrgdkvMQlA==", "dev": true, "license": "MIT", "engines": { @@ -1249,9 +1142,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.15.7.tgz", - "integrity": "sha512-SGlkhRnHXoBzLY2SxVppMsREhyaDHpyXQrPDUfsCnyG5DC8UVmXnTVQp9c2kqhAZw6g6g6V7uoqTLqJQmrWOFQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.1.tgz", + "integrity": "sha512-8cY3vLAKdt5gQEMM3Gr57BuQ8sun2NjYNh9qTdrctC1S9gNC7XzFghTYAfHSWR4VrOUcMFLO/izMdsc1KFvFOA==", "dev": true, "license": "MIT", "engines": { @@ -1259,9 +1152,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.15.7.tgz", - "integrity": "sha512-IzBsrl54TyO5Ezbyr25ZOUZA3Sg2UbSWDZZar9jSRAsoikcsoy1ivgSumcYJYOH8HAtanfr8YGN0+8UF/kbYqg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.1.tgz", + "integrity": "sha512-LMvReIndW1ckvemElfDgTt282fb2C3C/ZXfsm0pJsTV5ZmtdelCHwzmgSBmY5fDr7D66XDp8EurotSE0K6BTvw==", "dev": true, "license": "MIT", "engines": { @@ -1427,16 +1320,19 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } @@ -1463,12 +1359,12 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -1499,18 +1395,21 @@ } }, "node_modules/@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -1575,27 +1474,27 @@ } }, "node_modules/@eslint/js": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", - "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", + "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", + "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" @@ -1653,9 +1552,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz", - "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -1845,29 +1744,6 @@ } } }, - "node_modules/@jest/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/@jest/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/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -1989,29 +1865,6 @@ } } }, - "node_modules/@jest/reporters/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/@jest/reporters/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/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2118,9 +1971,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "license": "MIT", "dependencies": { @@ -2261,6 +2114,23 @@ "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==", "license": "MIT" }, + "node_modules/@pm2/agent/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/@pm2/agent/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2343,6 +2213,23 @@ "lodash": "^4.17.14" } }, + "node_modules/@pm2/io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/@pm2/io/node_modules/eventemitter2": { "version": "6.4.9", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", @@ -2407,6 +2294,23 @@ "lodash": "^4.17.14" } }, + "node_modules/@pm2/js-api/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/@pm2/js-api/node_modules/eventemitter2": { "version": "6.4.9", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", @@ -2552,13 +2456,13 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.10.1.tgz", - "integrity": "sha512-U+4yzNXElTf9q0kEfnloI9XbOyD4cnEQCxjUI94q0+W++0GAEQvJ/slwEj9lwjDHfGADRSr+Tco/z0XJvmDfCQ==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.12.1.tgz", + "integrity": "sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.12.2", + "@typescript-eslint/utils": "^8.13.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "estraverse": "^5.3.0", @@ -2669,17 +2573,6 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -2747,17 +2640,10 @@ "@types/node": "*" } }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "20.17.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz", + "integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -2808,14 +2694,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", - "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz", + "integrity": "sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2" + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2826,9 +2712,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", - "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.1.tgz", + "integrity": "sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==", "dev": true, "license": "MIT", "engines": { @@ -2840,14 +2726,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", - "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz", + "integrity": "sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/visitor-keys": "8.12.2", + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/visitor-keys": "8.18.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2862,23 +2748,21 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", - "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.1.tgz", + "integrity": "sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.12.2", - "@typescript-eslint/types": "8.12.2", - "@typescript-eslint/typescript-estree": "8.12.2" + "@typescript-eslint/scope-manager": "8.18.1", + "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/typescript-estree": "8.18.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2888,18 +2772,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.12.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", - "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz", + "integrity": "sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.12.2", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.18.1", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2909,19 +2794,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2957,13 +2829,10 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } @@ -3025,16 +2894,13 @@ } }, "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "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": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=8" } }, "node_modules/ansi-styles": { @@ -3053,12 +2919,12 @@ } }, "node_modules/ansis": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.3.2.tgz", - "integrity": "sha512-cFthbBlt+Oi0i9Pv/j6YdVWJh54CtjGACaMPCIrEV4Ha7HWsIjXDwseYV79TIL0B4+KfSwD5S70PeQDkPUd1rA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.4.0.tgz", + "integrity": "sha512-zVESKSQhWaPhGaWiKj1k+UqvpC7vPBBgG3hjQEeIx2YGzylWt8qA3ziAzRuUtm0OnaGsZKjIvfl8D/sJTt/I0w==", "license": "ISC", "engines": { - "node": ">=15" + "node": ">=16" } }, "node_modules/anymatch": { @@ -3184,16 +3050,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3203,16 +3069,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3222,19 +3088,18 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -3256,9 +3121,9 @@ } }, "node_modules/ast-types/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/astral-regex": { @@ -3299,9 +3164,9 @@ } }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3570,6 +3435,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "license": "MIT", "optional": true }, @@ -3596,9 +3462,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", "dev": true, "funding": [ { @@ -3616,10 +3482,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -3693,16 +3559,44 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -3731,9 +3625,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001664", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", - "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", + "version": "1.0.30001689", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", + "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", "dev": true, "funding": [ { @@ -3784,9 +3678,9 @@ } }, "node_modules/chalk-template/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.0.tgz", + "integrity": "sha512-ZkD35Mx92acjB2yNJgziGqT9oKHEOxjTBTDRpOsRWtdecL/0jM3z5kM/CTzHWvHIen1GvkM85p6TuFfDGfc8/Q==", "dev": true, "license": "MIT", "engines": { @@ -3971,16 +3865,6 @@ "node": ">=12" } }, - "node_modules/cliui/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/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -4013,19 +3897,6 @@ "node": ">=8" } }, - "node_modules/cliui/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/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -4304,9 +4175,9 @@ "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -4318,25 +4189,25 @@ } }, "node_modules/cspell": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.15.7.tgz", - "integrity": "sha512-68Bs/brr31M0W6tljNCgHcz09xdfDnRobyyRQJ8z0ZrovfTHHj9gSQldJJt5Fq3AMlCeYbECnKPsY9DkzIP1sQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.1.tgz", + "integrity": "sha512-D0lw8XTXrTycNzOn5DkfPJNUT00X53OgvFDm+0SzhBr1r+na8LEh3CnQ6zKYVU0fL0x8vU82vs4jmGjDho9mPg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.15.7", - "@cspell/cspell-pipe": "8.15.7", - "@cspell/cspell-types": "8.15.7", - "@cspell/dynamic-import": "8.15.7", - "@cspell/url": "8.15.7", + "@cspell/cspell-json-reporter": "8.17.1", + "@cspell/cspell-pipe": "8.17.1", + "@cspell/cspell-types": "8.17.1", + "@cspell/dynamic-import": "8.17.1", + "@cspell/url": "8.17.1", "chalk": "^5.3.0", "chalk-template": "^1.1.0", "commander": "^12.1.0", - "cspell-dictionary": "8.15.7", - "cspell-gitignore": "8.15.7", - "cspell-glob": "8.15.7", - "cspell-io": "8.15.7", - "cspell-lib": "8.15.7", + "cspell-dictionary": "8.17.1", + "cspell-gitignore": "8.17.1", + "cspell-glob": "8.17.1", + "cspell-io": "8.17.1", + "cspell-lib": "8.17.1", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", @@ -4355,43 +4226,30 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.15.7.tgz", - "integrity": "sha512-orxPKLMLQjk+Px1wlZdMElsHlKFGiwlXhQcG/36hODFKsle9DnGqVefOjH6aWFO5DyDF+Z678leiO2F30wtXEQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.1.tgz", + "integrity": "sha512-x1S7QWprgUcwuwiJB1Ng0ZTBC4G50qP9qQyg/aroMkcdMsHfk26E8jUGRPNt4ftHFzS4YMhwtXuJQ9IgRUuNPA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.15.7", + "@cspell/cspell-types": "8.17.1", "comment-json": "^4.2.5", - "yaml": "^2.6.0" + "yaml": "^2.6.1" }, "engines": { "node": ">=18" } }, - "node_modules/cspell-config-lib/node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/cspell-dictionary": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.15.7.tgz", - "integrity": "sha512-jmOk9kJ/bsVFg0/ObnNMUHA3wPgHb4eGFx6yF+Lx28eYx9j2XkLZuXXicbNyOWqJ9AzP0CavPmHwAS6bJrxD3Q==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.1.tgz", + "integrity": "sha512-zSl9l3wii+x16yc2NVZl/+CMLeLBAiuEd5YoFkOYPcbTJnfPwdjMNcj71u7wBvNJ+qwbF+kGbutEt15yHW3NBw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.7", - "@cspell/cspell-types": "8.15.7", - "cspell-trie-lib": "8.15.7", + "@cspell/cspell-pipe": "8.17.1", + "@cspell/cspell-types": "8.17.1", + "cspell-trie-lib": "8.17.1", "fast-equals": "^5.0.1" }, "engines": { @@ -4399,15 +4257,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.15.7.tgz", - "integrity": "sha512-LxX/PS3z6UqXHUqw3wIB1OJwZrexxKn/EUertYcLce/K2M2wLsUA+uneU5EvUqzkM6vwMHvdv/hl/tROFQJIbw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.1.tgz", + "integrity": "sha512-bk727Zf4FBCjm9Mwvyreyhgjwe+YhPQEW7PldkHiinKd+Irfez4s8GXLQb1EgV0UpvViqaqBqLmngjZdS30BTA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.15.7", - "cspell-glob": "8.15.7", - "cspell-io": "8.15.7", + "@cspell/url": "8.17.1", + "cspell-glob": "8.17.1", + "cspell-io": "8.17.1", "find-up-simple": "^1.0.0" }, "bin": { @@ -4418,13 +4276,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.15.7.tgz", - "integrity": "sha512-BI0mF0IWqVxEGpRkH2kBgT9Ey7lAMlEhvY/zKCy3JQY5PSn/qI3RhlsXrsTDt2RJxhicuzJIe3KiNdUKXQM0Ig==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.1.tgz", + "integrity": "sha512-cUwM5auSt0RvLX7UkP2GEArJRWc85l51B1voArl+3ZIKeMZwcJpJgN3qvImtF8yRTZwYeYCs1sgsihb179q+mg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.15.7", + "@cspell/url": "8.17.1", "micromatch": "^4.0.8" }, "engines": { @@ -4432,14 +4290,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.15.7.tgz", - "integrity": "sha512-g7ocpFG9Gam4+b2bHrqhmXVaFNV4BjFjVnaEKS3RoqcMjJuQUa9wD5HWO6AvBJeJf/auvQS7CgmumQqSo9xxCw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.1.tgz", + "integrity": "sha512-H5tLcBuW7aUj9L0rR+FSbnWPEsWb8lWppHVidtqw9Ll1CUHWOZC9HTB2RdrhJZrsz/8DJbM2yNbok0Xt0VAfdw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.7", - "@cspell/cspell-types": "8.15.7" + "@cspell/cspell-pipe": "8.17.1", + "@cspell/cspell-types": "8.17.1" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4449,42 +4307,42 @@ } }, "node_modules/cspell-io": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.15.7.tgz", - "integrity": "sha512-GEnMPu+xyyHTal2QdCbuRrPUEpjCYo0mF/Tz/YkcZNJdn0sj6MylH2EA0A+d6WzheRpw9ijd1dRvq3h5jJgmuQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.1.tgz", + "integrity": "sha512-liIOsblt7oVItifzRAbuxiYrwlgw1VOqKppMxVKtYoAn2VUuuEpjCj6jLWpoTqSszR/38o7ChsHY1LHakhJZmw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.15.7", - "@cspell/url": "8.15.7" + "@cspell/cspell-service-bus": "8.17.1", + "@cspell/url": "8.17.1" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.15.7.tgz", - "integrity": "sha512-RxxPEymTENc76f8ny1LN+aPyR4Efwyah8m5c20xOwxD/lAhBrNs2PPE1taEMPkI7WTXWjKm4D0DJpZatD+W6pg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.1.tgz", + "integrity": "sha512-66n83Q7bK5tnvkDH7869/pBY/65AKmZVfCOAlsbhJn3YMDbNHFCHR0d1oNMlqG+n65Aco89VGwYfXxImZY+/mA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.15.7", - "@cspell/cspell-pipe": "8.15.7", - "@cspell/cspell-resolver": "8.15.7", - "@cspell/cspell-types": "8.15.7", - "@cspell/dynamic-import": "8.15.7", - "@cspell/filetypes": "8.15.7", - "@cspell/strong-weak-map": "8.15.7", - "@cspell/url": "8.15.7", + "@cspell/cspell-bundled-dicts": "8.17.1", + "@cspell/cspell-pipe": "8.17.1", + "@cspell/cspell-resolver": "8.17.1", + "@cspell/cspell-types": "8.17.1", + "@cspell/dynamic-import": "8.17.1", + "@cspell/filetypes": "8.17.1", + "@cspell/strong-weak-map": "8.17.1", + "@cspell/url": "8.17.1", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.15.7", - "cspell-dictionary": "8.15.7", - "cspell-glob": "8.15.7", - "cspell-grammar": "8.15.7", - "cspell-io": "8.15.7", - "cspell-trie-lib": "8.15.7", + "cspell-config-lib": "8.17.1", + "cspell-dictionary": "8.17.1", + "cspell-glob": "8.17.1", + "cspell-grammar": "8.17.1", + "cspell-io": "8.17.1", + "cspell-trie-lib": "8.17.1", "env-paths": "^3.0.0", "fast-equals": "^5.0.1", "gensequence": "^7.0.0", @@ -4499,14 +4357,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.15.7", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.15.7.tgz", - "integrity": "sha512-b8WWWOx5wfhT72K43fk3dMoE4H2c1UpbCEVB2JXJ5scub7mjqoT/CRiZlw1IDfQT6BmUtJuD7sZ8NRFanF9hQA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.1.tgz", + "integrity": "sha512-13WNa5s75VwOjlGzWprmfNbBFIfXyA7tYYrbV+LugKkznyNZJeJPojHouEudcLq3SYb2Q6tJ7qyWcuT5bR9qPA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.15.7", - "@cspell/cspell-types": "8.15.7", + "@cspell/cspell-pipe": "8.17.1", + "@cspell/cspell-types": "8.17.1", "gensequence": "^7.0.0" }, "engines": { @@ -4514,9 +4372,9 @@ } }, "node_modules/cspell/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.0.tgz", + "integrity": "sha512-ZkD35Mx92acjB2yNJgziGqT9oKHEOxjTBTDRpOsRWtdecL/0jM3z5kM/CTzHWvHIen1GvkM85p6TuFfDGfc8/Q==", "dev": true, "license": "MIT", "engines": { @@ -4537,13 +4395,13 @@ } }, "node_modules/css-tree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.0.1.tgz", - "integrity": "sha512-8Fxxv+tGhORlshCdCwnNJytvlvq46sOLSYEx2ZIGurahWvMucSRnyjPA3AmrMq4VPRYbHVpWj5VkiVasrM2H4Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", "dev": true, "license": "MIT", "dependencies": { - "mdn-data": "2.12.1", + "mdn-data": "2.12.2", "source-map-js": "^1.0.1" }, "engines": { @@ -4672,9 +4530,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -4899,6 +4757,16 @@ "node": ">=8" } }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -4967,6 +4835,20 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4974,9 +4856,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "32.2.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.2.tgz", - "integrity": "sha512-c7TRE42JcgEmJ4elJyCdKk/2os0UX7YMkRDeXBkxFEoM34iX1/2x+c5T9PgeroKz8FEG7omRU5TvjulqVtXvdw==", + "version": "32.2.7", + "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.7.tgz", + "integrity": "sha512-y8jbQRG3xogF70XPlk5c+dWe5iRfUBo28o2NMpKd/CcW7ENIaWtBlGima8/8nmRdAaYTy1+yIt6KB0Lon9H8cA==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4993,9 +4875,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.29", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", - "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==", + "version": "1.5.74", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", + "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", "dev": true, "license": "ISC" }, @@ -5077,6 +4959,23 @@ "node": ">= 0.6" } }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/engine.io/node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", @@ -5201,57 +5100,59 @@ } }, "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "version": "1.23.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.6.tgz", + "integrity": "sha512-Ifco6n3yj2tMZDWNLyloZrytt9lqqlwvS83P3HtaETR0NUOYnIULGGHpktqYGObGy+8wc1okO25p8TjemhImvA==", "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "data-view-buffer": "^1.0.1", "data-view-byte-length": "^1.0.1", "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.7", + "get-intrinsic": "^1.2.6", "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", + "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", + "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", + "is-regex": "^1.2.1", "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", + "is-string": "^1.1.1", "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.0.0", + "object-inspect": "^1.13.3", "object-keys": "^1.1.1", "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-regex-test": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", + "typed-array-byte-offset": "^1.0.3", + "typed-array-length": "^1.0.7", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -5261,13 +5162,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -5325,14 +5223,14 @@ } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -5398,26 +5296,26 @@ } }, "node_modules/eslint": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", - "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", + "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.14.0", - "@eslint/plugin-kit": "^0.2.0", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.17.0", + "@eslint/plugin-kit": "^0.2.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.0", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -5436,8 +5334,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -5586,9 +5483,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.8.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz", - "integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==", + "version": "28.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.9.0.tgz", + "integrity": "sha512-rLu1s1Wf96TgUUxSw6loVIkNtUjq1Re7A9QdCCHSohnvXEBAjuL420h0T/fMmkQlNsQP2GhQzEUpYHPfxBkvYQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5612,9 +5509,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.4.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.4.3.tgz", - "integrity": "sha512-uWtwFxGRv6B8sU63HZM5dAGDhgsatb+LONwmILZJhdRALLOkCX2HFZhdL/Kw2ls8SQMAVEfK+LmnEfxInRN8HA==", + "version": "50.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.1.tgz", + "integrity": "sha512-UWyaYi6iURdSfdVVqvfOs2vdCVz0J40O/z/HTsv2sFjdjmdlUI/qlKLOTmwbPQ2tAfQnE5F9vqx+B+poF71DBQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5638,9 +5535,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.17.0.tgz", - "integrity": "sha512-Yyf+hPjOhLGzr+m5ibw61yzvTQQMCCis06cTbnQuVQqblZqn5MLQHpRkKcdNzp28yxffLStKPPx9xvmVUdDBxQ==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.18.0.tgz", + "integrity": "sha512-ZyDaHm3c+vDMNoOVyO+KcJxlBnNNFeRML8Ui/WATrQ+F/dyAIR6aIyu50691gll3dCBT26llL2DXMre30x23ug==", "dev": true, "license": "MIT", "dependencies": { @@ -5650,7 +5547,7 @@ "package-json-validator": "^0.7.0", "semver": "^7.5.4", "sort-object-keys": "^1.1.3", - "sort-package-json": "^1.57.0", + "sort-package-json": "^2.12.0", "validate-npm-package-name": "^6.0.0" }, "engines": { @@ -5916,9 +5813,9 @@ } }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -5940,7 +5837,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -5955,6 +5852,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express-basic-auth": { @@ -6099,10 +6000,10 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", - "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", - "license": "MIT" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", @@ -6280,9 +6181,9 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "license": "ISC" }, "node_modules/follow-redirects": { @@ -6315,9 +6216,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -6392,15 +6293,16 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.7.tgz", + "integrity": "sha512-2g4x+HqTJKM9zcJqBSpjoRmdcPFtJM60J3xJisTQSXBWka5XqyBN/2tNUgma1mztTXyDuUsEtYe5qcs7xYzYQA==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -6449,9 +6351,9 @@ } }, "node_modules/get-east-asian-width": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", - "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", "dev": true, "license": "MIT", "engines": { @@ -6462,16 +6364,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", + "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -6520,14 +6427,14 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -6537,59 +6444,23 @@ } }, "node_modules/get-uri": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", - "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", "license": "MIT", "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4", - "fs-extra": "^11.2.0" + "debug": "^4.3.4" }, "engines": { "node": ">= 14" } }, - "node_modules/get-uri/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/get-uri/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/get-uri/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/git-hooks-list": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", - "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz", + "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", "dev": true, "license": "MIT", "funding": { @@ -6777,23 +6648,37 @@ } }, "node_modules/globby": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", - "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", "dev": true, "license": "MIT", "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globjoin": { @@ -6804,12 +6689,12 @@ "license": "MIT" }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6845,6 +6730,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "devOptional": true, "license": "ISC" }, "node_modules/handlebars": { @@ -6869,10 +6755,13 @@ } }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6909,10 +6798,13 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -6921,9 +6813,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -6963,6 +6855,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.0.0.tgz", "integrity": "sha512-VyusHLEIIO5mjQPUI1wpOAEu+wl6Q0998jzTxqUYGE45xCIcAxy3MsbEK/yyJUJ3ADeMoB6MornPH6GMWAf+Pw==", + "license": "MIT", "engines": { "node": ">=18.0.0" } @@ -7086,12 +6979,12 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "4" }, "engines": { @@ -7109,9 +7002,9 @@ } }, "node_modules/husky": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", - "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", "bin": { @@ -7251,14 +7144,14 @@ } }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7290,9 +7183,9 @@ "license": "BSD-3-Clause" }, "node_modules/ip6": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.2.10.tgz", - "integrity": "sha512-1LdpyKjhvepd6EbAU6rW4g14vuYtx5TnJX9TfZZBhsM6DsyPQLNzW12rtbUqXBMwqFrLVV/Gcxv0GNFvJp2cYA==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.2.11.tgz", + "integrity": "sha512-OmTP7FyIp+ZoNvZ7Xr97bWrCgypa3BeuYuRFNTOPT8Y11cxMW1pW1VC70kHZP1onSHHMotADcjdg5QyECiIMUw==", "license": "MIT", "bin": { "ip6": "ip6-cli.js" @@ -7308,13 +7201,14 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -7330,13 +7224,31 @@ "dev": true, "license": "MIT" }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7355,13 +7267,13 @@ } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7383,9 +7295,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.0.tgz", + "integrity": "sha512-urTSINYfAYgcbLb0yDQ6egFm6h3Mo1DcF9EkyXSRjjzdHbsulg01qhwWuXdOoUBuTkbQ80KDboXa0vFJ+BDH+g==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -7398,11 +7310,13 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -7413,12 +7327,13 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7436,6 +7351,21 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", @@ -7459,6 +7389,21 @@ "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7471,6 +7416,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -7493,12 +7450,13 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7508,13 +7466,16 @@ } }, "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-plain-object": { @@ -7535,14 +7496,28 @@ "license": "MIT" }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7551,12 +7526,12 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -7579,12 +7554,13 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7594,12 +7570,14 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7609,13 +7587,25 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7624,12 +7614,31 @@ } }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8403,16 +8412,16 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -8615,9 +8624,9 @@ } }, "node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, "license": "MIT", "engines": { @@ -8645,22 +8654,22 @@ } }, "node_modules/lint-staged": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", - "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "version": "15.2.11", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.11.tgz", + "integrity": "sha512-Ev6ivCTYRTGs9ychvpVw35m/bcNDuBN+mnTeObCL5h+boS5WzBEC6LHI4I9F/++sZm1m+J2LEiy0gxL/R9TBqQ==", "dev": true, "license": "MIT", "dependencies": { "chalk": "~5.3.0", "commander": "~12.1.0", - "debug": "~4.3.6", + "debug": "~4.4.0", "execa": "~8.0.1", - "lilconfig": "~3.1.2", - "listr2": "~8.2.4", + "lilconfig": "~3.1.3", + "listr2": "~8.2.5", "micromatch": "~4.0.8", "pidtree": "~0.6.0", "string-argv": "~0.3.2", - "yaml": "~2.5.0" + "yaml": "~2.6.1" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -8830,9 +8839,9 @@ } }, "node_modules/listr2": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", - "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8924,6 +8933,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/log-update/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", @@ -8970,6 +8992,22 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -9052,9 +9090,9 @@ } }, "node_modules/markdownlint-cli2": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.15.0.tgz", - "integrity": "sha512-4P/lnxQxU2R5lywRJs4b2ajm8z65CW8qqR1bTIcdQ5EG+nZpC6HJlJUnmIR5ee+uecUkoMroazxWcLB7etSmrg==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.16.0.tgz", + "integrity": "sha512-oy5dJdOxGMKSwrlouxdEGf6N4O2Iz8oJ4/HO2Ix67o4vTK1AQNGjZUNwTIzfa5x+XbJ++dfgR1gLfILajsW+1Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9088,53 +9126,6 @@ "markdownlint-cli2": ">=0.0.4" } }, - "node_modules/markdownlint-cli2/node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdownlint-cli2/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdownlint-cli2/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/markdownlint-micromark": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.12.tgz", @@ -9161,6 +9152,15 @@ "node": ">=10" } }, + "node_modules/math-intrinsics": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", + "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", @@ -9173,9 +9173,9 @@ } }, "node_modules/mdn-data": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.1.tgz", - "integrity": "sha512-rsfnCbOHjqrhWxwt5/wtSLzpoKTzW7OXdT5lLOIH1OTYhWu9rRJveGq0sKvDZODABH7RX+uoR+DYcpFnq4Tf6Q==", + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", "dev": true, "license": "CC0-1.0" }, @@ -9395,9 +9395,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.45", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", - "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "version": "0.5.46", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz", + "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -9419,9 +9419,9 @@ "license": "ISC" }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -9520,9 +9520,9 @@ } }, "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", - "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9543,6 +9543,7 @@ "version": "0.20.1", "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.20.1.tgz", "integrity": "sha512-NrXgzDJd6XcyX9kDMJVA3xYCZmntY7ghA2BOdBeYr3iu8tydHOAb+68jPQhF9V2CRQ0/386X05XhmLzQUN0+Hw==", + "license": "Apache-2.0", "dependencies": { "axios": "^1.7.7", "moment-timezone": "^0.5.45", @@ -9558,9 +9559,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, @@ -9619,9 +9620,9 @@ "license": "MIT" }, "node_modules/nwsapi": { - "version": "2.2.13", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", - "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", + "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", "dev": true, "license": "MIT" }, @@ -9635,9 +9636,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -9656,14 +9657,15 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.6.tgz", + "integrity": "sha512-yVh6qdqwYsX9rUYzK6VGV4QT16okE8zNvcX0uRPg9MmBNcvPdTJi7cErXnUw/IeQ7Cg4tYMM6BTL3JEcEA0YTQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -9831,19 +9833,19 @@ } }, "node_modules/pac-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", - "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", + "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", + "agent-base": "^7.1.2", "debug": "^4.3.4", "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.5", + "https-proxy-agent": "^7.0.6", "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.4" + "socks-proxy-agent": "^8.0.5" }, "engines": { "node": ">= 14" @@ -9863,14 +9865,17 @@ } }, "node_modules/package-json-validator": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.7.0.tgz", - "integrity": "sha512-ufEJ03cPLVxZCHuypSJjmUC2t0xDy0Eru4AfPFe2MfPw14BqedavayQqd49H2/VCrcWONmXsJ47Tp7kzaElX2w==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.7.1.tgz", + "integrity": "sha512-4LMljZxpshPCaeK4RxAgTe7bn6sGZl+K2+ehSRju/OdDkTrcBiggEtuLaistTRjqVZ4a/LB+ClbPUSZP7d3xew==", "dev": true, "license": "MIT", "dependencies": { "yargs": "~17.7.2" }, + "bin": { + "pjv": "bin/pjv" + }, "engines": { "node": ">=18" } @@ -9928,13 +9933,13 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -9997,19 +10002,22 @@ "license": "MIT" }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/peberminta": { @@ -10153,13 +10161,13 @@ } }, "node_modules/playwright": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", - "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", + "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.48.2" + "playwright-core": "1.49.1" }, "bin": { "playwright": "cli.js" @@ -10172,9 +10180,9 @@ } }, "node_modules/playwright-core": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", - "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "version": "1.49.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", + "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10200,9 +10208,9 @@ } }, "node_modules/pm2": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.2.tgz", - "integrity": "sha512-ynVpBwZampRH3YWLwRepZpQ7X3MvpwLIaqIdFEeBYEhaXbHmEx2KqOdxGV4T54wvKBhH3LixvU1j1bK4/sq7Tw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.3.tgz", + "integrity": "sha512-4/I1htIHzZk1Y67UgOCo4F1cJtas1kSds31N8zN0PybO230id1nigyjGuGFzUnGmUFPmrJ0On22fO1ChFlp7VQ==", "license": "AGPL-3.0", "dependencies": { "@pm2/agent": "~2.0.0", @@ -10456,9 +10464,9 @@ } }, "node_modules/prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", - "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, "license": "MIT", "bin": { @@ -10780,16 +10788,38 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", + "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "dunder-proto": "^1.0.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -10851,12 +10881,12 @@ } }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.9", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.9.tgz", + "integrity": "sha512-QxrmX1DzraFIi9PxdG5VkRfRwIgjwyud+z/iBwfRRrVmHc+P9Q7u2lSSpQ6bjr2gy5lrqIiU9vb6iAeGf2400A==", "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -10898,9 +10928,9 @@ } }, "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, "license": "MIT", "engines": { @@ -11012,9 +11042,9 @@ } }, "node_modules/rrule/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/rrweb-cssom": { @@ -11069,14 +11099,15 @@ "license": "MIT" }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -11107,14 +11138,14 @@ "license": "MIT" }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -11337,15 +11368,16 @@ "license": "BSD-2-Clause" }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11354,22 +11386,75 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/sinon": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", - "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", - "dev": true, - "license": "BSD-3-Clause", + "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==", + "license": "MIT", "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.2", - "@sinonjs/samsam": "^8.0.1", + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/sinon": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", + "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.2", + "@sinonjs/samsam": "^8.0.1", "diff": "^7.0.0", "nise": "^6.1.1", "supports-color": "^7.2.0" @@ -11380,9 +11465,9 @@ } }, "node_modules/sinon/node_modules/@sinonjs/fake-timers": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz", - "integrity": "sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA==", + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -11491,6 +11576,23 @@ "ws": "~8.17.1" } }, + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/socket.io-adapter/node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", @@ -11525,6 +11627,40 @@ "node": ">=10.0.0" } }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/socks": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", @@ -11540,12 +11676,12 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "license": "MIT", "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -11561,23 +11697,48 @@ "license": "MIT" }, "node_modules/sort-package-json": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.57.0.tgz", - "integrity": "sha512-FYsjYn2dHTRb41wqnv+uEqCUvBpK3jZcTp9rbz2qDTmel7Pmdtf+i2rLaaPMRZeSVM60V3Se31GyWFpmKs4Q5Q==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.12.0.tgz", + "integrity": "sha512-/HrPQAeeLaa+vbAH/znjuhwUluuiM/zL5XX9kop8UpDgjtyWKt43hGDk2vd/TBdDpzIyzIHVUgmYofzYrAQjew==", "dev": true, "license": "MIT", "dependencies": { - "detect-indent": "^6.0.0", - "detect-newline": "3.1.0", - "git-hooks-list": "1.0.3", - "globby": "10.0.0", - "is-plain-obj": "2.1.0", - "sort-object-keys": "^1.1.3" + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", + "git-hooks-list": "^3.0.0", + "is-plain-obj": "^4.1.0", + "semver": "^7.6.0", + "sort-object-keys": "^1.1.3", + "tinyglobby": "^0.2.9" }, "bin": { "sort-package-json": "cli.js" } }, + "node_modules/sort-package-json/node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/sort-package-json/node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -11695,45 +11856,51 @@ "node": ">=10" } }, - "node_modules/string-length/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==", + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-length/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==", + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/string.prototype.matchall": { @@ -11763,15 +11930,18 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11781,15 +11951,19 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11812,19 +11986,16 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "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": "^6.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/strip-bom": { @@ -11860,9 +12031,9 @@ } }, "node_modules/stylelint": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.11.0.tgz", - "integrity": "sha512-zrl4IrKmjJQ+h9FoMp69UMCq5SxeHk0URhxUBj4d3ISzo/DplOFBJZc7t7Dr6otB+1bfbbKNLOmCDpzKSlW+Nw==", + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.12.0.tgz", + "integrity": "sha512-F8zZ3L/rBpuoBZRvI4JVT20ZanPLXfQLzMOZg1tzPflRVh9mKpOZ8qcSIhh1my3FjAjZWG4T2POwGnmn6a6hbg==", "dev": true, "funding": [ { @@ -11912,7 +12083,7 @@ "string-width": "^4.2.3", "supports-hyperlinks": "^3.1.0", "svg-tags": "^1.0.0", - "table": "^6.8.2", + "table": "^6.9.0", "write-file-atomic": "^5.0.1" }, "bin": { @@ -11988,16 +12159,6 @@ "stylelint": ">=16.0.0" } }, - "node_modules/stylelint/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/stylelint/node_modules/balanced-match": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", @@ -12091,19 +12252,6 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/string-width/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/stylelint/node_modules/write-file-atomic": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", @@ -12191,9 +12339,9 @@ "license": "MIT" }, "node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, "license": "MIT", "dependencies": { @@ -12208,16 +12356,16 @@ } }, "node_modules/synckit/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, "node_modules/systeminformation": { - "version": "5.23.5", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.5.tgz", - "integrity": "sha512-PEpJwhRYxZgBCAlWZhWIgfMTjXLqfcaZ1pJsJn9snWNfBW/Z1YQg1mbIUSWrEV3ErAHF7l/OoVLQeaZDlPzkpA==", + "version": "5.23.14", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.14.tgz", + "integrity": "sha512-mUHEuDQJJOpphvjcIrTY0iwLnoNo/qotr6SuN7v0ANOO0L3j89mfCrEuIVheS/9S9KGRt4Osqxh9GoF7BX49UA==", "license": "MIT", "os": [ "darwin", @@ -12241,9 +12389,9 @@ } }, "node_modules/table": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", - "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -12257,16 +12405,6 @@ "node": ">=10.0.0" } }, - "node_modules/table/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/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -12317,19 +12455,6 @@ "node": ">=8" } }, - "node_modules/table/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/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -12369,12 +12494,6 @@ "node": "*" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "license": "MIT" - }, "node_modules/tinyglobby": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", @@ -12390,22 +12509,22 @@ } }, "node_modules/tldts": { - "version": "6.1.48", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.48.tgz", - "integrity": "sha512-SPbnh1zaSzi/OsmHb1vrPNnYuwJbdWjwo5TbBYYMlTtH3/1DSb41t8bcSxkwDmmbG2q6VLPVvQc7Yf23T+1EEw==", + "version": "6.1.68", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.68.tgz", + "integrity": "sha512-JKF17jROiYkjJPT73hUTEiTp2OBCf+kAlB+1novk8i6Q6dWjHsgEjw9VLiipV4KTJavazXhY1QUXyQFSem2T7w==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.48" + "tldts-core": "^6.1.68" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.48", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.48.tgz", - "integrity": "sha512-3gD9iKn/n2UuFH1uilBviK9gvTNT6iYwdqrj1Vr5mh8FuelvpRNaYVH4pNYqUgOGU4aAdL9X35eLuuj0gRsx+A==", + "version": "6.1.68", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.68.tgz", + "integrity": "sha512-85TdlS/DLW/gVdf2oyyzqp3ocS30WxjaL4la85EArl9cHUR/nizifKAJPziWewSZjDZS71U517/i6ciUeqtB5Q==", "dev": true, "license": "MIT" }, @@ -12416,16 +12535,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -12474,9 +12583,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", - "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, "license": "MIT", "engines": { @@ -12605,30 +12714,30 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -12638,9 +12747,9 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", + "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", @@ -12648,7 +12757,8 @@ "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.13", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -12658,17 +12768,17 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -12678,9 +12788,9 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -12713,15 +12823,18 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12969,9 +13082,9 @@ } }, "node_modules/whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", "dev": true, "license": "MIT", "dependencies": { @@ -12998,31 +13111,80 @@ } }, "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "for-each": "^0.3.3", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -13065,6 +13227,19 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", @@ -13078,6 +13253,22 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -13169,9 +13360,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, "license": "ISC", "bin": { @@ -13210,16 +13401,6 @@ "node": ">=12" } }, - "node_modules/yargs/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/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -13252,19 +13433,6 @@ "node": ">=8" } }, - "node_modules/yargs/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/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index d2200a6149..7552489172 100644 --- a/package.json +++ b/package.json @@ -64,11 +64,11 @@ }, "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.3.2", + "ansis": "^3.4.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.14.0", - "express": "^4.21.1", + "eslint": "^9.17.0", + "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^8.0.0", @@ -80,33 +80,33 @@ "pm2": "^5.4.2", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.5" + "systeminformation": "^5.23.14" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.10.1", - "cspell": "^8.15.7", + "@stylistic/eslint-plugin": "^2.12.1", + "cspell": "^8.17.1", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^28.8.3", - "eslint-plugin-jsdoc": "^50.4.3", - "eslint-plugin-package-json": "^0.17.0", + "eslint-plugin-jest": "^28.9.0", + "eslint-plugin-jsdoc": "^50.6.1", + "eslint-plugin-package-json": "^0.18.0", "express-basic-auth": "^1.2.1", - "husky": "^9.1.6", + "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^25.0.1", - "lint-staged": "^15.2.10", - "markdownlint-cli2": "^0.15.0", - "playwright": "^1.48.2", - "prettier": "^3.3.3", + "lint-staged": "^15.2.11", + "markdownlint-cli2": "^0.16.0", + "playwright": "^1.49.1", + "prettier": "^3.4.2", "sinon": "^19.0.2", - "stylelint": "^16.10.0", + "stylelint": "^16.12.0", "stylelint-config-standard": "^36.0.1", "stylelint-prettier": "^5.0.2" }, "optionalDependencies": { - "electron": "^32.2.2" + "electron": "^32.2.7" }, "engines": { - "node": ">=20.9.0 <21 || 22 || >=23" + "node": ">=20.9.0 <21 || >=22" }, "_moduleAliases": { "node_helper": "js/node_helper.js", diff --git a/vendor/package-lock.json b/vendor/package-lock.json index 6edb0dd58d..fa4bf8a861 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-free": "^6.7.1", + "@fortawesome/fontawesome-free": "^6.7.2", "animate.css": "^4.1.1", "croner": "^9.0.0", "moment": "^2.30.1", @@ -20,9 +20,9 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.1.tgz", - "integrity": "sha512-ALIk/MOh5gYe1TG/ieS5mVUsk7VUIJTJKPMK9rFFqOgfp0Q3d5QiBXbcOMwUvs37fyZVCz46YjOE6IFeOAXCHA==", + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz", + "integrity": "sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==", "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", "engines": { "node": ">=6" @@ -59,6 +59,7 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/croner/-/croner-9.0.0.tgz", "integrity": "sha512-onMB0OkDjkXunhdW9htFjEhqrD54+M94i6ackoUkjHKbRnXdyEyKRelp4nJ1kAz32+s27jP1FsebpJCVl0BsvA==", + "license": "MIT", "engines": { "node": ">=18.0" } diff --git a/vendor/package.json b/vendor/package.json index 34b3593898..e4afe0bc09 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-free": "^6.7.1", + "@fortawesome/fontawesome-free": "^6.7.2", "animate.css": "^4.1.1", "croner": "^9.0.0", "moment": "^2.30.1", From c485ff670d03b26d652a7d74ef49158433bd9041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Wed, 18 Dec 2024 22:07:09 +0100 Subject: [PATCH 163/418] path resolve and sub/sub folder module (#3653) Fix: - use `path.resolve` for `moduleFolder` and `defaultModuleFolder` path - Fix module path in case of sub/sub folder is used (sample `module/test/test`) --- case of module installation on `module/test/test`: config will be: ```js { module: "test/test", ... } ``` module core will be: ```js Module.register("test", { ... ``` `test.js` is used for module core (no change) --- case of module installation on `module/test` (no change): config will be: ```js { module: "test", ... } ``` module core will be: ```js Module.register("test", { ... ``` so `test.js` is used for module core --- In reality, with this patch, `module` config feature have 2 functionalites: - determinate module path with more precision - allow to use sub/sub folder in modules folder --------- Co-authored-by: Veeck --- CHANGELOG.md | 1 + js/app.js | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c895706c3..1d71ff63b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ _This release is scheduled to be released on 2025-01-01._ - [core] Fix missing `basePath` where `location.host` is used (#3613) - [compliments] croner library changed filenames used in latest version (#3624) - [linter] Fix ESLint ignore pattern which caused that default modules not to be linted (#3632) +- [core] Fix module path in case of sub/sub folder is used and use path.resolve for resolve `moduleFolder` and `defaultModuleFolder` in app.js (#3653) - [calendar] Update to resolve issues #3098 #3144 #3351 #3422 #3443 #3467 #3537 related to timezone changes - [calendar] Fix #3267 (styles array), also fixes event with both exdate AND recurrence(and testcase) - [calendar] Fix showEndsOnlyWithDuration not working, #3598, applies ONLY to full day events diff --git a/js/app.js b/js/app.js index 9d111c7eb9..0c2586af18 100644 --- a/js/app.js +++ b/js/app.js @@ -164,10 +164,10 @@ function App () { const elements = module.split("/"); const moduleName = elements[elements.length - 1]; const env = getEnvVarsAsObj(); - let moduleFolder = `${__dirname}/../${env.modulesDir}/${module}`; + let moduleFolder = path.resolve(`${__dirname}/../${env.modulesDir}`, module); if (defaultModules.includes(moduleName)) { - const defaultModuleFolder = `${__dirname}/../modules/default/${module}`; + const defaultModuleFolder = path.resolve(`${__dirname}/../modules/default/`, module); if (process.env.JEST_WORKER_ID === undefined) { moduleFolder = defaultModuleFolder; } else { @@ -178,7 +178,7 @@ function App () { } } - const moduleFile = `${moduleFolder}/${module}.js`; + const moduleFile = `${moduleFolder}/${moduleName}.js`; try { fs.accessSync(moduleFile, fs.R_OK); From 0b3a04c5201a9ef530c927a5186852e06716eee0 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 22 Dec 2024 07:26:01 +0100 Subject: [PATCH 164/418] Switch to 'npx' for lint-staged in pre-commit hook (#3658) This way we get rid of the script entry in the `package.json` and the whole thing becomes a little less complex. --- .husky/pre-commit | 4 ++-- CHANGELOG.md | 9 +++++---- package.json | 1 - 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index d949a3eb50..37b0600fe4 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,5 @@ #!/bin/sh -if command -v npm &> /dev/null; then - npm run lint:staged +if command -v npx &> /dev/null; then + npx lint-staged fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d71ff63b0..f6edcfb4de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,14 +23,15 @@ _This release is scheduled to be released on 2025-01-01._ - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643) - [linter] Add linting for markdown files (#3646) - [calendar] Add ability to display end date for full date events, where end is not same day (showEnd=true) (#3650) -- [core] Add text to the config.js.sample file about the locale variable (#3654) +- [core] Add text to the config.js.sample file about the locale variable (#3654, #3655) ### Changed - [core] Run code style checks in workflow only once (#3648) - [core] Fix animations export #3644 only on server side (#3649) -- [core] Use project URL in fallback config. -- [core] fix Access Denied crash writing js/positions.js (on synology nas) #3651. new message, MM starts, but no modules showing +- [core] Use project URL in fallback config (#3656) +- [core] Fix Access Denied crash writing js/positions.js (on synology nas) #3651. new message, MM starts, but no modules showing (#3652) +- [linter] Switch to 'npx' for lint-staged in pre-commit hook ### Removed @@ -40,7 +41,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated - [repo] Reactivate `stale.yaml` as GitHub action to mark issues as stale after 60 days and close them 7 days later (if no activity) (#3577, #3580, #3581) -- [core] Update electron dependency to v32 (test electron rebuild) and other dependencies +- [core] Update electron dependency to v32 (test electron rebuild) and other dependencies (#3657) - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) - [core] Run and test with node 23 (#3588) diff --git a/package.json b/package.json index 7552489172..de2e76bbd8 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "lint:js": "eslint . --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", - "lint:staged": "lint-staged", "postinstall": "npm run install-vendor && npm run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"", "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.", "server": "node ./serveronly", From 2fb51436a523cbf79654a3523f85ff6f40edc9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Tue, 24 Dec 2024 15:20:29 +0100 Subject: [PATCH 165/418] delete exception `allow-ghsas: GHSA-8hc4-vh64-cxmj` in `dep-review.yaml` (#3659) node needed with new version of `node-ical` --- .github/workflows/dep-review.yaml | 2 -- CHANGELOG.md | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dep-review.yaml b/.github/workflows/dep-review.yaml index 838f157ecb..141e821b9c 100644 --- a/.github/workflows/dep-review.yaml +++ b/.github/workflows/dep-review.yaml @@ -16,5 +16,3 @@ jobs: uses: actions/checkout@v4 - name: "Dependency Review" uses: actions/dependency-review-action@v4 - with: - allow-ghsas: GHSA-8hc4-vh64-cxmj diff --git a/CHANGELOG.md b/CHANGELOG.md index f6edcfb4de..20772b7a9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ _This release is scheduled to be released on 2025-01-01._ - [core] Fix animations export #3644 only on server side (#3649) - [core] Use project URL in fallback config (#3656) - [core] Fix Access Denied crash writing js/positions.js (on synology nas) #3651. new message, MM starts, but no modules showing (#3652) -- [linter] Switch to 'npx' for lint-staged in pre-commit hook +- [linter] Switch to 'npx' for lint-staged in pre-commit hook (#3658) ### Removed @@ -44,6 +44,7 @@ _This release is scheduled to be released on 2025-01-01._ - [core] Update electron dependency to v32 (test electron rebuild) and other dependencies (#3657) - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) - [core] Run and test with node 23 (#3588) +- [workflow] delete exception `allow-ghsas: GHSA-8hc4-vh64-cxmj` in `dep-review.yaml` (#3659) ### Fixed From 6a09bc4ec4f6faf81bea422ff2af16ce2bb0cdc2 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Wed, 25 Dec 2024 17:28:16 -0600 Subject: [PATCH 166/418] add support for fetch timeout control for node_helpers, fix timeouts on armv6l (#3660) user reporting slow/no connection/timeout errors on armv6l for calendar, and newsfeed we can increase the timeout by adding calls to the undici lib, but it requires node 20.18.1 or above. this adds the support for timeout (also environment variable to override if needed,, mmFetchTimeout (default 30 seconds) and updates the base node version --- .github/workflows/automated-tests.yaml | 2 +- .github/workflows/electron-rebuild.yaml | 2 +- CHANGELOG.md | 1 + js/app.js | 7 + package-lock.json | 320 ++++++++++++------------ package.json | 5 +- 6 files changed, 175 insertions(+), 162 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 8de8a641c7..f6dc940b08 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -38,7 +38,7 @@ jobs: timeout-minutes: 30 strategy: matrix: - node-version: [20.9.0, 20.x, 22.x, 23.x] + node-version: [20.18.1, 20.x, 22.x, 23.x] steps: - name: "Checkout code" uses: actions/checkout@v4 diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index 5c5e9b5a3f..5d310e1cfb 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.9.0, 20.x, 22.x, 23.x] + node-version: [20.18.1, 20.x, 22.x, 23.x] steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 20772b7a9f..4d4754faca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ _This release is scheduled to be released on 2025-01-01._ - [linter] Add linting for markdown files (#3646) - [calendar] Add ability to display end date for full date events, where end is not same day (showEnd=true) (#3650) - [core] Add text to the config.js.sample file about the locale variable (#3654, #3655) +- [core] Add fetch timeout for all node_helpers (thru undici, forces node 20.18.1 minimum) to help on slower systems. ### Changed diff --git a/js/app.js b/js/app.js index 0c2586af18..bfd249c23a 100644 --- a/js/app.js +++ b/js/app.js @@ -11,6 +11,11 @@ const Utils = require(`${__dirname}/utils`); const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`); const { getEnvVarsAsObj } = require(`${__dirname}/server_functions`); +// used to control fetch timeout for node_helpers +const { setGlobalDispatcher, Agent } = require("undici"); +// common timeout value, provide environment override in case +const fetch_timeout = process.env.mmFetchTimeout !== undefined ? process.env.mmFetchTimeout : 30000; + // Get version number. global.version = require(`${__dirname}/../package.json`).version; global.mmTestMode = process.env.mmTestMode === "true" ? true : false; @@ -295,6 +300,8 @@ function App () { } } + setGlobalDispatcher(new Agent({ connect: { timeout: fetch_timeout } })); + await loadModules(modules); httpServer = new Server(config); diff --git a/package-lock.json b/package-lock.json index 9cb5b683ac..f3750f0d89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,8 @@ "pm2": "^5.4.2", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.14" + "systeminformation": "^5.23.14", + "undici": "^7.2.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^2.12.1", @@ -50,7 +51,7 @@ "stylelint-prettier": "^5.0.2" }, "engines": { - "node": ">=20.9.0 <21 || 22 || >=23" + "node": ">=20.18.1 <21 || 22 || >=23" }, "optionalDependencies": { "electron": "^32.2.7" @@ -745,9 +746,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-companies": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.9.tgz", - "integrity": "sha512-w7XEJ2B6x2jq9ws5XNyYgpYj2MxdZ3jW3PETLxjK7nc8pulCFmaGVgZ0JTnDWfJ3QMOczoagn5f9LM2PZ/CuJg==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.10.tgz", + "integrity": "sha512-KpRLiVDCpTkF+IjWnuYc31B0gyHVh0TSf/MDrWPobl9oYNQRWFUMACAJO9FP+kHI0jzLjTyLC1KpKwqte/88iA==", "dev": true, "license": "MIT" }, @@ -1003,9 +1004,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.18", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.18.tgz", - "integrity": "sha512-/Nukl+DSxtEWSlb8svWFSpJVctAsM9SP+f5Q1n+qdDcXNKMb1bUCo/d3QZPwyOhuMjDawnsGBUAfp+iq7Mw83Q==", + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.20.tgz", + "integrity": "sha512-vE9pFIifCDChsVhhUDuVtnwxygOdtHNluDm+8FkgC84M6LwiUVJr/CuSOI/SCR0oI9iiFp0VvMz194B6XwMv3g==", "dev": true, "license": "MIT" }, @@ -1069,9 +1070,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.1.20", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.1.20.tgz", - "integrity": "sha512-ma51njqbk9ZKzZF9NpCZpZ+c50EwR5JTJ2LEXlX0tX+ExVbKpthhlDLhT2+mkUh5Zvj+CLf5F9z0qB4+X3re/w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.0.tgz", + "integrity": "sha512-cTLTNdP9RM6nruZ01FThEFKRi7C4TPN8ndc+FpvCqis9J8iSg4Cr4YQemT/DxXoXz0527NbBPCARunxA0qIgTA==", "dev": true, "license": "MIT" }, @@ -1097,9 +1098,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-terraform": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.6.tgz", - "integrity": "sha512-Sqm5vGbXuI9hCFcr4w6xWf4Y25J9SdleE/IqfM6RySPnk8lISEmVdax4k6+Kinv9qaxyvnIbUUN4WFLWcBPQAg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.7.tgz", + "integrity": "sha512-Ip7tOlAt/qUVdWYyDMA7DlKMpQ6sjtrsXk4vcpqXoYpoJlzMoDce7pw+fPhHshtNOFBAZ4nOrszlLu6APuy+HQ==", "dev": true, "license": "MIT" }, @@ -2694,14 +2695,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz", - "integrity": "sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz", + "integrity": "sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1" + "@typescript-eslint/types": "8.18.2", + "@typescript-eslint/visitor-keys": "8.18.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2712,9 +2713,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.1.tgz", - "integrity": "sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.2.tgz", + "integrity": "sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==", "dev": true, "license": "MIT", "engines": { @@ -2726,14 +2727,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz", - "integrity": "sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz", + "integrity": "sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1", + "@typescript-eslint/types": "8.18.2", + "@typescript-eslint/visitor-keys": "8.18.2", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2753,16 +2754,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.1.tgz", - "integrity": "sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.2.tgz", + "integrity": "sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.18.1", - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/typescript-estree": "8.18.1" + "@typescript-eslint/scope-manager": "8.18.2", + "@typescript-eslint/types": "8.18.2", + "@typescript-eslint/typescript-estree": "8.18.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2777,13 +2778,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz", - "integrity": "sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz", + "integrity": "sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/types": "8.18.2", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2969,13 +2970,13 @@ "license": "Python-2.0" }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -3625,9 +3626,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001689", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", - "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", + "version": "1.0.30001690", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", + "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", "dev": true, "funding": [ { @@ -3678,9 +3679,9 @@ } }, "node_modules/chalk-template/node_modules/chalk": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.0.tgz", - "integrity": "sha512-ZkD35Mx92acjB2yNJgziGqT9oKHEOxjTBTDRpOsRWtdecL/0jM3z5kM/CTzHWvHIen1GvkM85p6TuFfDGfc8/Q==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", "engines": { @@ -4372,9 +4373,9 @@ } }, "node_modules/cspell/node_modules/chalk": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.0.tgz", - "integrity": "sha512-ZkD35Mx92acjB2yNJgziGqT9oKHEOxjTBTDRpOsRWtdecL/0jM3z5kM/CTzHWvHIen1GvkM85p6TuFfDGfc8/Q==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", "engines": { @@ -4464,14 +4465,14 @@ } }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4481,29 +4482,29 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -4822,9 +4823,9 @@ } }, "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", + "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", @@ -4875,9 +4876,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.74", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", - "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", + "version": "1.5.76", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", + "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", "dev": true, "license": "ISC" }, @@ -5100,27 +5101,27 @@ } }, "node_modules/es-abstract": { - "version": "1.23.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.6.tgz", - "integrity": "sha512-Ifco6n3yj2tMZDWNLyloZrytt9lqqlwvS83P3HtaETR0NUOYnIULGGHpktqYGObGy+8wc1okO25p8TjemhImvA==", + "version": "1.23.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.7.tgz", + "integrity": "sha512-OygGC8kIcDhXX+6yAZRGLqwi2CmEXCbLQixeGUgYeR+Qwlppqmo7DIDr8XibtEBZp+fJcoYpoatp5qwLMEdcqQ==", "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", + "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.3", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.7", + "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.2.6", - "get-symbol-description": "^1.0.2", + "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", @@ -5128,31 +5129,30 @@ "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.4", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.3", + "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", - "is-typed-array": "^1.1.13", + "is-typed-array": "^1.1.15", "is-weakref": "^1.1.0", - "math-intrinsics": "^1.0.0", + "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", + "object.assign": "^4.1.7", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.3", "safe-regex-test": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.3", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.16" + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" }, "engines": { "node": ">= 0.4" @@ -5483,9 +5483,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.9.0.tgz", - "integrity": "sha512-rLu1s1Wf96TgUUxSw6loVIkNtUjq1Re7A9QdCCHSohnvXEBAjuL420h0T/fMmkQlNsQP2GhQzEUpYHPfxBkvYQ==", + "version": "28.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.10.0.tgz", + "integrity": "sha512-hyMWUxkBH99HpXT3p8hc7REbEZK3D+nk8vHXGgpB+XXsi0gO4PxMSP+pjfUzb67GnV9yawV9a53eUmcde1CCZA==", "dev": true, "license": "MIT", "dependencies": { @@ -6016,9 +6016,9 @@ } }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "dev": true, "license": "ISC", "dependencies": { @@ -6293,12 +6293,13 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.7.tgz", - "integrity": "sha512-2g4x+HqTJKM9zcJqBSpjoRmdcPFtJM60J3xJisTQSXBWka5XqyBN/2tNUgma1mztTXyDuUsEtYe5qcs7xYzYQA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "license": "MIT", "dependencies": { "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", @@ -7295,9 +7296,9 @@ } }, "node_modules/is-core-module": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.0.tgz", - "integrity": "sha512-urTSINYfAYgcbLb0yDQ6egFm6h3Mo1DcF9EkyXSRjjzdHbsulg01qhwWuXdOoUBuTkbQ80KDboXa0vFJ+BDH+g==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -7428,18 +7429,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -9153,9 +9142,9 @@ } }, "node_modules/math-intrinsics": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", - "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -9657,14 +9646,15 @@ } }, "node_modules/object.assign": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.6.tgz", - "integrity": "sha512-yVh6qdqwYsX9rUYzK6VGV4QT16okE8zNvcX0uRPg9MmBNcvPdTJi7cErXnUw/IeQ7Cg4tYMM6BTL3JEcEA0YTQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, @@ -9710,13 +9700,14 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -10881,9 +10872,9 @@ } }, "node_modules/resolve": { - "version": "1.22.9", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.9.tgz", - "integrity": "sha512-QxrmX1DzraFIi9PxdG5VkRfRwIgjwyud+z/iBwfRRrVmHc+P9Q7u2lSSpQ6bjr2gy5lrqIiU9vb6iAeGf2400A==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -10893,6 +10884,9 @@ "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11904,23 +11898,24 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -12363,9 +12358,9 @@ "license": "0BSD" }, "node_modules/systeminformation": { - "version": "5.23.14", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.14.tgz", - "integrity": "sha512-mUHEuDQJJOpphvjcIrTY0iwLnoNo/qotr6SuN7v0ANOO0L3j89mfCrEuIVheS/9S9KGRt4Osqxh9GoF7BX49UA==", + "version": "5.23.21", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.21.tgz", + "integrity": "sha512-7cXg7L3Hkdy7L0iOdsFDoclDQpE/dMTi5UDgdYpihBsqy+3yhr/bIlfJedy7+LM65Xugk5MIxJ0OMtS5ZncjkA==", "license": "MIT", "os": [ "darwin", @@ -12509,22 +12504,22 @@ } }, "node_modules/tldts": { - "version": "6.1.68", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.68.tgz", - "integrity": "sha512-JKF17jROiYkjJPT73hUTEiTp2OBCf+kAlB+1novk8i6Q6dWjHsgEjw9VLiipV4KTJavazXhY1QUXyQFSem2T7w==", + "version": "6.1.69", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.69.tgz", + "integrity": "sha512-Oh/CqRQ1NXNY7cy9NkTPUauOWiTro0jEYZTioGbOmcQh6EC45oribyIMJp0OJO3677r13tO6SKdWoGZUx2BDFw==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.68" + "tldts-core": "^6.1.69" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.68", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.68.tgz", - "integrity": "sha512-85TdlS/DLW/gVdf2oyyzqp3ocS30WxjaL4la85EArl9cHUR/nizifKAJPziWewSZjDZS71U517/i6ciUeqtB5Q==", + "version": "6.1.69", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.69.tgz", + "integrity": "sha512-nygxy9n2PBUFQUtAXAc122gGo+04/j5qr5TGQFZTHafTKYvmARVXt2cA5rgero2/dnXUfkdPtiJoKmrd3T+wdA==", "dev": true, "license": "MIT" }, @@ -12747,18 +12742,18 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", - "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "reflect.getprototypeof": "^1.0.6" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -12840,6 +12835,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.2.0.tgz", + "integrity": "sha512-klt+0S55GBViA9nsq48/NSCo4YX5mjydjypxD7UmHh/brMu8h/Mhd/F7qAeoH2NOO8SDTk6kjnTFc4WpzmfYpQ==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", diff --git a/package.json b/package.json index de2e76bbd8..da72a07fc6 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,8 @@ "pm2": "^5.4.2", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.14" + "systeminformation": "^5.23.14", + "undici": "^7.2.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^2.12.1", @@ -105,7 +106,7 @@ "electron": "^32.2.7" }, "engines": { - "node": ">=20.9.0 <21 || >=22" + "node": ">=20.18.1 <21 || >=22" }, "_moduleAliases": { "node_helper": "js/node_helper.js", From 9d0501f24055e6d05efe2a7b337f1a7ed71ec315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Fri, 27 Dec 2024 14:20:24 +0100 Subject: [PATCH 167/418] Fix: package-lock.json after PR #3660 (#3661) continue from #3660 Fix: package-lock.json (check node engine) --- CHANGELOG.md | 2 +- package-lock.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d4754faca..efc0119460 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ _This release is scheduled to be released on 2025-01-01._ - [linter] Add linting for markdown files (#3646) - [calendar] Add ability to display end date for full date events, where end is not same day (showEnd=true) (#3650) - [core] Add text to the config.js.sample file about the locale variable (#3654, #3655) -- [core] Add fetch timeout for all node_helpers (thru undici, forces node 20.18.1 minimum) to help on slower systems. +- [core] Add fetch timeout for all node_helpers (thru undici, forces node 20.18.1 minimum) to help on slower systems. (#3660) (3661) ### Changed diff --git a/package-lock.json b/package-lock.json index f3750f0d89..c1e9c24b8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,7 +51,7 @@ "stylelint-prettier": "^5.0.2" }, "engines": { - "node": ">=20.18.1 <21 || 22 || >=23" + "node": ">=20.18.1 <21 || >=22" }, "optionalDependencies": { "electron": "^32.2.7" From 93a0c24c22ddbefb91afa48d129dee41e7597e28 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sat, 28 Dec 2024 11:57:39 -0600 Subject: [PATCH 168/418] fix #3662 line parse on windows with linux line ends (#3663) line parse used os.EOL, which failed with linux line ends in index.html, change to '\n' --- CHANGELOG.md | 1 + js/utils.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efc0119460..5375ff6539 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ _This release is scheduled to be released on 2025-01-01._ - [calendar] Fix showEnd for Full Day events (#3602) - [tests] Suppress "module is not defined" in e2e tests (#3647) - [calendar] Fix #3267 (styles array, really this time!) +- [core] Fix #3662 js/positions.js created incorrectly ## [2.29.0] - 2024-10-01 diff --git a/js/utils.js b/js/utils.js index d4b90223ed..da953fec71 100644 --- a/js/utils.js +++ b/js/utils.js @@ -52,7 +52,7 @@ module.exports = { // if not already discovered if (modulePositions.length === 0) { // get the lines of the index.html - const lines = fs.readFileSync(indexFileName).toString().split(os.EOL); + const lines = fs.readFileSync(indexFileName).toString().split("\n"); // loop thru the lines lines.forEach((line) => { // run the regex on each line From d41ce81469bb4765859099e868e1a3a547c7ccdb Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 28 Dec 2024 20:18:45 +0100 Subject: [PATCH 169/418] update dependencies, fix typo in Collaboration.md (#3664) last dependency update before release --- CHANGELOG.md | 2 +- Collaboration.md | 2 +- package-lock.json | 844 ++++++++++++++++++++++++++++++++++++++++++---- package.json | 10 +- 4 files changed, 792 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5375ff6539..95e847c82d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated - [repo] Reactivate `stale.yaml` as GitHub action to mark issues as stale after 60 days and close them 7 days later (if no activity) (#3577, #3580, #3581) -- [core] Update electron dependency to v32 (test electron rebuild) and other dependencies (#3657) +- [core] Update electron dependency to v32 (test electron rebuild) and other dependencies too (#3657) - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) - [core] Run and test with node 23 (#3588) - [workflow] delete exception `allow-ghsas: GHSA-8hc4-vh64-cxmj` in `dep-review.yaml` (#3659) diff --git a/Collaboration.md b/Collaboration.md index 52b4f80755..d2adfc9050 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -45,7 +45,7 @@ Are done by - [ ] create new release with - [ ] corresponding version tag `v2.xx.0` - [ ] a release name: `...` - - [ ] description of the PR is the section of the `CHANGELOG.md` + - [ ] description of the release is the section of the `CHANGELOG.md` ### Draft new development release diff --git a/package-lock.json b/package-lock.json index c1e9c24b8a..347393abd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.4.0", + "ansis": "^3.5.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^9.17.0", @@ -27,22 +27,22 @@ "pm2": "^5.4.2", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.14", + "systeminformation": "^5.23.23", "undici": "^7.2.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^2.12.1", "cspell": "^8.17.1", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^28.9.0", + "eslint-plugin-jest": "^28.10.0", "eslint-plugin-jsdoc": "^50.6.1", "eslint-plugin-package-json": "^0.18.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^25.0.1", - "lint-staged": "^15.2.11", - "markdownlint-cli2": "^0.16.0", + "lint-staged": "^15.3.0", + "markdownlint-cli2": "^0.17.0", "playwright": "^1.49.1", "prettier": "^3.4.2", "sinon": "^19.0.2", @@ -746,9 +746,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-companies": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.10.tgz", - "integrity": "sha512-KpRLiVDCpTkF+IjWnuYc31B0gyHVh0TSf/MDrWPobl9oYNQRWFUMACAJO9FP+kHI0jzLjTyLC1KpKwqte/88iA==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.11.tgz", + "integrity": "sha512-1gbPfN4fk6Cmg8DbCc+3nFxnHJNNGN1R5T/VzGEp8UpVBcW3OFET2xXFKcJiKSh+DyXB+M2tAx3so6WBEwOK1Q==", "dev": true, "license": "MIT" }, @@ -893,9 +893,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-golang": { - "version": "6.0.17", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.17.tgz", - "integrity": "sha512-uDDLEJ/cHdLiqPw4+5BnmIo2i/TSR+uDvYd6JlBjTmjBKpOCyvUgYRztH7nv5e7virsN5WDiUWah4/ATQGz4Pw==", + "version": "6.0.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.18.tgz", + "integrity": "sha512-Mt+7NwfodDwUk7423DdaQa0YaA+4UoV3XSxQwZioqjpFBCuxfvvv4l80MxCTAAbK6duGj0uHbGTwpv8fyKYPKg==", "dev": true, "license": "MIT" }, @@ -1070,9 +1070,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.0.tgz", - "integrity": "sha512-cTLTNdP9RM6nruZ01FThEFKRi7C4TPN8ndc+FpvCqis9J8iSg4Cr4YQemT/DxXoXz0527NbBPCARunxA0qIgTA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.1.tgz", + "integrity": "sha512-8FiZHeeTqBdjsw4uBsZ9GIV9zEUbr49bBeEyVGFmUMZYwhAzC9riGqbTWco277X5Mabe8OjbYxqiP2/snC6w5w==", "dev": true, "license": "MIT" }, @@ -2568,6 +2568,16 @@ "@types/node": "*" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -2631,6 +2641,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -2641,6 +2658,13 @@ "@types/node": "*" } }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "20.17.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz", @@ -2667,6 +2691,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -2920,9 +2951,9 @@ } }, "node_modules/ansis": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.4.0.tgz", - "integrity": "sha512-zVESKSQhWaPhGaWiKj1k+UqvpC7vPBBgG3hjQEeIx2YGzylWt8qA3ziAzRuUtm0OnaGsZKjIvfl8D/sJTt/I0w==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.5.2.tgz", + "integrity": "sha512-5uGcUZRbORJeEppVdWfZOSybTMz+Ou+84HepgK081Yk5+pPMMzWf/XGxiAT6bfBqCghRB4MwBtYn0CHqINRVag==", "license": "ISC", "engines": { "node": ">=16" @@ -3701,6 +3732,39 @@ "node": ">=10" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/charm": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", @@ -4554,6 +4618,20 @@ "dev": true, "license": "MIT" }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -4689,6 +4767,16 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -4726,6 +4814,20 @@ "license": "MIT", "optional": true }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -5180,9 +5282,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", "dev": true, "license": "MIT" }, @@ -7201,6 +7303,32 @@ "node": ">= 0.10" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -7343,6 +7471,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -7417,6 +7556,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -8535,6 +8685,33 @@ "dev": true, "license": "MIT" }, + "node_modules/katex": { + "version": "0.16.18", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.18.tgz", + "integrity": "sha512-LRuk0rPdXrecAFwQucYjMiIs0JFefk6N1q/04mlw14aVIVgxq1FO0MA9RiIIGVaKOB5GIP5GH4aBBNraZERmaQ==", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -8643,13 +8820,13 @@ } }, "node_modules/lint-staged": { - "version": "15.2.11", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.11.tgz", - "integrity": "sha512-Ev6ivCTYRTGs9ychvpVw35m/bcNDuBN+mnTeObCL5h+boS5WzBEC6LHI4I9F/++sZm1m+J2LEiy0gxL/R9TBqQ==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.3.0.tgz", + "integrity": "sha512-vHFahytLoF2enJklgtOtCtIjZrKD/LoxlaUusd5nh7dWv/dkKQJY74ndFSzxCdv7g0ueGg1ORgTSt4Y9LPZn9A==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "~5.3.0", + "chalk": "~5.4.1", "commander": "~12.1.0", "debug": "~4.4.0", "execa": "~8.0.1", @@ -8671,9 +8848,9 @@ } }, "node_modules/lint-staged/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", "engines": { @@ -9062,14 +9239,20 @@ } }, "node_modules/markdownlint": { - "version": "0.36.1", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.36.1.tgz", - "integrity": "sha512-s73fU2CQN7WCgjhaQUQ8wYESQNzGRNOKDd+3xgVqu8kuTEhmwepd/mxOv1LR2oV046ONrTLBFsM7IoKWNvmy5g==", + "version": "0.37.2", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.37.2.tgz", + "integrity": "sha512-m8QhYnRA1ptbhIjhVVBUkKQcUelVxuyO/yXyLewnc1+xs4eXhST/+hIy29goO+EYVLmWtknH4SmYQ4s0caoKqw==", "dev": true, "license": "MIT", "dependencies": { "markdown-it": "14.1.0", - "markdownlint-micromark": "0.1.12" + "micromark": "4.0.1", + "micromark-extension-directive": "3.0.2", + "micromark-extension-gfm-autolink-literal": "2.1.0", + "micromark-extension-gfm-footnote": "2.1.0", + "micromark-extension-gfm-table": "2.1.0", + "micromark-extension-math": "3.1.0", + "micromark-util-types": "2.0.1" }, "engines": { "node": ">=18" @@ -9079,21 +9262,21 @@ } }, "node_modules/markdownlint-cli2": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.16.0.tgz", - "integrity": "sha512-oy5dJdOxGMKSwrlouxdEGf6N4O2Iz8oJ4/HO2Ix67o4vTK1AQNGjZUNwTIzfa5x+XbJ++dfgR1gLfILajsW+1Q==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.17.0.tgz", + "integrity": "sha512-8Xz7wkkkV4wJTf+pvryU3J/fT3BZWD3ZykcjYBR0GuH0GHvrCbswaCdurbuUuAPDGFZy4cxBGYCJSAOW8jM4aQ==", "dev": true, "license": "MIT", "dependencies": { "globby": "14.0.2", "js-yaml": "4.1.0", "jsonc-parser": "3.3.1", - "markdownlint": "0.36.1", + "markdownlint": "0.37.2", "markdownlint-cli2-formatter-default": "0.0.5", "micromatch": "4.0.8" }, "bin": { - "markdownlint-cli2": "markdownlint-cli2.js" + "markdownlint-cli2": "markdownlint-cli2-bin.mjs" }, "engines": { "node": ">=18" @@ -9115,19 +9298,6 @@ "markdownlint-cli2": ">=0.0.4" } }, - "node_modules/markdownlint-micromark": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.12.tgz", - "integrity": "sha512-RlB6EwMGgc0sxcIhOQ2+aq7Zw1V2fBnzbXKGgYK/mVWdT7cz34fteKSwfYeo4rL6+L/q2tyC9QtD/PgZbkdyJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/DavidAnson" - } - }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -9232,6 +9402,542 @@ "node": ">= 0.6" } }, + "node_modules/micromark": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.1.tgz", + "integrity": "sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.2.tgz", + "integrity": "sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", + "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.3.tgz", + "integrity": "sha512-VXJJuNxYWSoYL6AJ6OQECCFGhIU2GGHMw8tahogePBrjkG8aCCas3ibkp7RnVOSTClg2is05/R7maAhF1XyQMg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.1.tgz", + "integrity": "sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -9890,6 +10596,26 @@ "node": ">=8" } }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/parse-imports": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", @@ -12358,9 +13084,9 @@ "license": "0BSD" }, "node_modules/systeminformation": { - "version": "5.23.21", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.21.tgz", - "integrity": "sha512-7cXg7L3Hkdy7L0iOdsFDoclDQpE/dMTi5UDgdYpihBsqy+3yhr/bIlfJedy7+LM65Xugk5MIxJ0OMtS5ZncjkA==", + "version": "5.23.23", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.23.tgz", + "integrity": "sha512-QhEWrMFZnzWjFZ7J65gikIXTrB8U6b7VTQ8pLaF/GUgJaJoUoSuucqalIVj91D/grhRUtXplL6qYwTn1A4FfhQ==", "license": "MIT", "os": [ "darwin", @@ -12504,22 +13230,22 @@ } }, "node_modules/tldts": { - "version": "6.1.69", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.69.tgz", - "integrity": "sha512-Oh/CqRQ1NXNY7cy9NkTPUauOWiTro0jEYZTioGbOmcQh6EC45oribyIMJp0OJO3677r13tO6SKdWoGZUx2BDFw==", + "version": "6.1.70", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.70.tgz", + "integrity": "sha512-/W1YVgYVJd9ZDjey5NXadNh0mJXkiUMUue9Zebd0vpdo1sU+H4zFFTaJ1RKD4N6KFoHfcXy6l+Vu7bh+bdWCzA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.69" + "tldts-core": "^6.1.70" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.69", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.69.tgz", - "integrity": "sha512-nygxy9n2PBUFQUtAXAc122gGo+04/j5qr5TGQFZTHafTKYvmARVXt2cA5rgero2/dnXUfkdPtiJoKmrd3T+wdA==", + "version": "6.1.70", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.70.tgz", + "integrity": "sha512-RNnIXDB1FD4T9cpQRErEqw6ZpjLlGdMOitdV+0xtbsnwr4YFka1zpc7D4KD+aAn8oSG5JyFrdasZTE04qDE9Yg==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index da72a07fc6..1102d14ad6 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ }, "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.4.0", + "ansis": "^3.5.2", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^9.17.0", @@ -79,22 +79,22 @@ "pm2": "^5.4.2", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.14", + "systeminformation": "^5.23.23", "undici": "^7.2.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^2.12.1", "cspell": "^8.17.1", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^28.9.0", + "eslint-plugin-jest": "^28.10.0", "eslint-plugin-jsdoc": "^50.6.1", "eslint-plugin-package-json": "^0.18.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^25.0.1", - "lint-staged": "^15.2.11", - "markdownlint-cli2": "^0.16.0", + "lint-staged": "^15.3.0", + "markdownlint-cli2": "^0.17.0", "playwright": "^1.49.1", "prettier": "^3.4.2", "sinon": "^19.0.2", From 143dfd6b672fd4ed962185b40bf0fd3f3f9a31b0 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 30 Dec 2024 12:24:51 +0100 Subject: [PATCH 170/418] Add some ESLint rules + minor changes (#3665) Main point was to enable ESLint `dot-notation` and `no-unneeded-ternary` rules for more code consistency. I took the occasion to add two minor commits: - Fix a problem found by running `test:spelling - Minor dependency update It wouldn't be a problem if the PR didn't arrive in the next release, the changes are cosmetic. --- CHANGELOG.md | 1 + clientonly/index.js | 2 +- cspell.config.json | 1 + eslint.config.mjs | 7 +++++-- js/app.js | 2 +- js/electron.js | 6 +++--- js/utils.js | 6 +++--- modules/default/weather/providers/openmeteo.js | 10 +++++----- modules/default/weather/providers/openweathermap.js | 8 ++++---- package-lock.json | 10 +++++----- package.json | 4 ++-- 11 files changed, 31 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95e847c82d..658955b269 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ _This release is scheduled to be released on 2025-01-01._ - [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643) - [linter] Add linting for markdown files (#3646) +- [linter] Add some handy ESLint rules. - [calendar] Add ability to display end date for full date events, where end is not same day (showEnd=true) (#3650) - [core] Add text to the config.js.sample file about the locale variable (#3654, #3655) - [core] Add fetch timeout for all node_helpers (thru undici, forces node 20.18.1 minimum) to help on slower systems. (#3660) (3661) diff --git a/clientonly/index.js b/clientonly/index.js index b9a354832b..674355f810 100644 --- a/clientonly/index.js +++ b/clientonly/index.js @@ -28,7 +28,7 @@ }); // determine if "--use-tls"-flag was provided - config["tls"] = process.argv.indexOf("--use-tls") > 0; + config.tls = process.argv.indexOf("--use-tls") > 0; } /** diff --git a/cspell.config.json b/cspell.config.json index 5a27b4121a..1faa7e6502 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -152,6 +152,7 @@ "newsitems", "nfogal", "njwilliams", + "nonrepeating", "Norsk", "nunjuck", "odroid", diff --git a/eslint.config.mjs b/eslint.config.mjs index e8800a5144..c6bd2be9c1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -55,11 +55,12 @@ const config = [ "@stylistic/semi": ["error", "always"], "@stylistic/space-before-function-paren": ["error", "always"], "@stylistic/spaced-comment": "off", + "dot-notation": "error", eqeqeq: "error", "id-length": "off", - "import/order": "error", "import/extensions": "error", "import/newline-after-import": "error", + "import/order": "error", "init-declarations": "off", "jest/consistent-test-it": "warn", "jest/no-done-callback": "warn", @@ -78,6 +79,7 @@ const config = [ "no-ternary": "off", "no-throw-literal": "error", "no-undefined": "off", + "no-unneeded-ternary": "error", "no-unused-vars": "off", "no-useless-return": "error", "no-warning-comments": "off", @@ -112,7 +114,8 @@ const config = [ "max-lines-per-function": ["error", 100], "no-magic-numbers": "off", "one-var": "off", - "prefer-destructuring": "off" + "prefer-destructuring": "off", + "sort-keys": "error" } }, { diff --git a/js/app.js b/js/app.js index bfd249c23a..020139439a 100644 --- a/js/app.js +++ b/js/app.js @@ -18,7 +18,7 @@ const fetch_timeout = process.env.mmFetchTimeout !== undefined ? process.env.mmF // Get version number. global.version = require(`${__dirname}/../package.json`).version; -global.mmTestMode = process.env.mmTestMode === "true" ? true : false; +global.mmTestMode = process.env.mmTestMode === "true"; Log.log(`Starting MagicMirror: v${global.version}`); // Log system information. diff --git a/js/electron.js b/js/electron.js index b0224149a7..8bf8e15ba5 100644 --- a/js/electron.js +++ b/js/electron.js @@ -102,7 +102,7 @@ function createWindow () { */ let prefix; - if ((config["tls"] !== null && config["tls"]) || config.useHttps) { + if ((config.tls !== null && config.tls) || config.useHttps) { prefix = "https://"; } else { prefix = "http://"; @@ -151,11 +151,11 @@ function createWindow () { //remove response headers that prevent sites of being embedded into iframes if configured mainWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => { let curHeaders = details.responseHeaders; - if (config["ignoreXOriginHeader"] || false) { + if (config.ignoreXOriginHeader || false) { curHeaders = Object.fromEntries(Object.entries(curHeaders).filter((header) => !(/x-frame-options/i).test(header[0]))); } - if (config["ignoreContentSecurityPolicy"] || false) { + if (config.ignoreContentSecurityPolicy || false) { curHeaders = Object.fromEntries(Object.entries(curHeaders).filter((header) => !(/content-security-policy/i).test(header[0]))); } diff --git a/js/utils.js b/js/utils.js index da953fec71..2900317e97 100644 --- a/js/utils.js +++ b/js/utils.js @@ -24,9 +24,9 @@ module.exports = { versions: "kernel, node, npm, pm2" }); let systemDataString = "System information:"; - systemDataString += `\n### SYSTEM: manufacturer: ${staticData["system"]["manufacturer"]}; model: ${staticData["system"]["model"]}; virtual: ${staticData["system"]["virtual"]}`; - systemDataString += `\n### OS: platform: ${staticData["osInfo"]["platform"]}; distro: ${staticData["osInfo"]["distro"]}; release: ${staticData["osInfo"]["release"]}; arch: ${staticData["osInfo"]["arch"]}; kernel: ${staticData["versions"]["kernel"]}`; - systemDataString += `\n### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData["versions"]["node"]}; installed node: ${installedNodeVersion}; npm: ${staticData["versions"]["npm"]}; pm2: ${staticData["versions"]["pm2"]}`; + systemDataString += `\n### SYSTEM: manufacturer: ${staticData.system.manufacturer}; model: ${staticData.system.model}; virtual: ${staticData.system.virtual}`; + systemDataString += `\n### OS: platform: ${staticData.osInfo.platform}; distro: ${staticData.osInfo.distro}; release: ${staticData.osInfo.release}; arch: ${staticData.osInfo.arch}; kernel: ${staticData.versions.kernel}`; + systemDataString += `\n### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData.versions.node}; installed node: ${installedNodeVersion}; npm: ${staticData.versions.npm}; pm2: ${staticData.versions.pm2}`; systemDataString += `\n### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}`; Log.info(systemDataString); diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index 07f17e935c..b89510c000 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -244,17 +244,17 @@ WeatherProvider.register("openmeteo", { .add(Math.max(0, Math.min(7, this.config.maxNumberOfDays)), "days") .endOf("day"); - params["start_date"] = startDate.format("YYYY-MM-DD"); + params.start_date = startDate.format("YYYY-MM-DD"); switch (this.config.type) { case "hourly": case "daily": case "forecast": - params["end_date"] = endDate.format("YYYY-MM-DD"); + params.end_date = endDate.format("YYYY-MM-DD"); break; case "current": - params["current_weather"] = true; - params["end_date"] = params["start_date"]; + params.current_weather = true; + params.end_date = params.start_date; break; default: // Failsafe @@ -262,7 +262,7 @@ WeatherProvider.register("openmeteo", { } return Object.keys(params) - .filter((key) => (params[key] ? true : false)) + .filter((key) => (!!params[key])) .map((key) => { switch (key) { case "hourly": diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index dc902705ce..832d390dee 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -285,12 +285,12 @@ WeatherProvider.register("openweathermap", { current.weatherType = this.convertWeatherType(data.current.weather[0].icon); current.humidity = data.current.humidity; current.uv_index = data.current.uvi; - if (data.current.hasOwnProperty("rain") && !isNaN(data.current["rain"]["1h"])) { - current.rain = data.current["rain"]["1h"]; + if (data.current.hasOwnProperty("rain") && !isNaN(data.current.rain["1h"])) { + current.rain = data.current.rain["1h"]; precip = true; } - if (data.current.hasOwnProperty("snow") && !isNaN(data.current["snow"]["1h"])) { - current.snow = data.current["snow"]["1h"]; + if (data.current.hasOwnProperty("snow") && !isNaN(data.current.snow["1h"])) { + current.snow = data.current.snow["1h"]; precip = true; } if (precip) { diff --git a/package-lock.json b/package-lock.json index 347393abd6..3d5d094534 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,10 +24,10 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.20.1", - "pm2": "^5.4.2", + "pm2": "^5.4.3", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.23", + "systeminformation": "^5.23.24", "undici": "^7.2.0" }, "devDependencies": { @@ -13084,9 +13084,9 @@ "license": "0BSD" }, "node_modules/systeminformation": { - "version": "5.23.23", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.23.tgz", - "integrity": "sha512-QhEWrMFZnzWjFZ7J65gikIXTrB8U6b7VTQ8pLaF/GUgJaJoUoSuucqalIVj91D/grhRUtXplL6qYwTn1A4FfhQ==", + "version": "5.23.24", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.24.tgz", + "integrity": "sha512-dPEaqxCaOQMp+5/zCSjuGWbYW2NNBHUZZgI8SNs8xZbLSML2gXvf8OUiqr7Ea1zLkEuH3Tu58DLiNe4kwftPxw==", "license": "MIT", "os": [ "darwin", diff --git a/package.json b/package.json index 1102d14ad6..508b359718 100644 --- a/package.json +++ b/package.json @@ -76,10 +76,10 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.20.1", - "pm2": "^5.4.2", + "pm2": "^5.4.3", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.23", + "systeminformation": "^5.23.24", "undici": "^7.2.0" }, "devDependencies": { From c92fbb8a7e30e83923fe8d2c353eb8588ad2cc0d Mon Sep 17 00:00:00 2001 From: Veeck Date: Wed, 1 Jan 2025 14:30:18 +0100 Subject: [PATCH 171/418] Final dependency updates for v2.30 (#3671) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: veeck --- CHANGELOG.md | 8 +-- fonts/package-lock.json | 18 +++---- fonts/package.json | 4 +- package-lock.json | 108 +++++++++++----------------------------- package.json | 6 +-- 5 files changed, 46 insertions(+), 98 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 658955b269..2674249c12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,7 +43,7 @@ _This release is scheduled to be released on 2025-01-01._ ### Updated - [repo] Reactivate `stale.yaml` as GitHub action to mark issues as stale after 60 days and close them 7 days later (if no activity) (#3577, #3580, #3581) -- [core] Update electron dependency to v32 (test electron rebuild) and other dependencies too (#3657) +- [core] Update electron dependency to v32 (test electron rebuild) and all other dependencies too (#3657) - [tests] All test configs have been updated to allow full external access, allowing for easier debugging (especially when running as a container) - [core] Run and test with node 23 (#3588) - [workflow] delete exception `allow-ghsas: GHSA-8hc4-vh64-cxmj` in `dep-review.yaml` (#3659) @@ -107,7 +107,7 @@ Thanks to: @bugsounet, @dkallen78, @jargordon, @khassel, @KristjanESPERANTO, @Ma - [docs] Fixed `checks` badge in README.md - [weather] Fixed issue with the UK Met Office provider following a change in their API paths and header info. -- [core] add check for node_helper loading for multiple instances of same module (#3502) +- [core] Add check for node_helper loading for multiple instances of same module (#3502) - [weather] Fixed issue for respecting unit config on broadcasted notifications - [tests] Fixes calendar test by moving it from e2e to electron with fixed date (#3532) - [calendar] fixed sliceMultiDayEvents getting wrong count and displaying incorrect entries, Europe/Berlin (#3542) @@ -179,7 +179,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T ### Fixed -- Correct apiBase of weathergov weatherProvider to match documentation (#2926) +- [weather] Correct apiBase of weathergov weatherProvider to match documentation (#2926) - Worked around several issues in the RRULE library that were causing deleted calender events to still show, some initial and recurring events to not show, and some event times to be off an hour. (#3291) - Skip changelog requirement when running tests for dependency updates (#3320) @@ -331,7 +331,7 @@ Special thanks to @khassel, @rejas and @sdetweil for taking over most (if not al ### Updated -- Added support for precipitation probability with openmeteo weather-provider +- [weather] Added support for precipitation probability with openmeteo weather-provider - Update electron to v25.2 and other dependencies - Use node v20 in github workflow (replacing v14) - Refactor formatTime into common util function for default modules diff --git a/fonts/package-lock.json b/fonts/package-lock.json index 3acdd8c0a7..96614a92b2 100644 --- a/fonts/package-lock.json +++ b/fonts/package-lock.json @@ -9,21 +9,19 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.1.0", - "@fontsource/roboto-condensed": "^5.1.0" + "@fontsource/roboto": "^5.1.1", + "@fontsource/roboto-condensed": "^5.1.1" } }, "node_modules/@fontsource/roboto": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.1.0.tgz", - "integrity": "sha512-cFRRC1s6RqPygeZ8Uw/acwVHqih8Czjt6Q0MwoUoDe9U3m4dH1HmNDRBZyqlMSFwgNAUKgFImncKdmDHyKpwdg==", - "license": "Apache-2.0" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.1.1.tgz", + "integrity": "sha512-XwVVXtERDQIM7HPUIbyDe0FP4SRovpjF7zMI8M7pbqFp3ahLJsJTd18h+E6pkar6UbV3btbwkKjYARr5M+SQow==" }, "node_modules/@fontsource/roboto-condensed": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.1.0.tgz", - "integrity": "sha512-cTS62X9bgR6H+3qRtaDwt0I+3ocitMPalyr2OrzJtilIcuEo4my8UA4VVhOgr0OI2Sk9JNrNYcSxkv0k4XuKtQ==", - "license": "OFL-1.1" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.1.1.tgz", + "integrity": "sha512-0SYkGnWPsvyCI3TAqBYAglfVUqVu/fsdgsyl5u396oK8ZgyamWHdQMFHDqCWrb4H4hNiewJT1l2ShDCA/cu6Ug==" } } } diff --git a/fonts/package.json b/fonts/package.json index 0b6576f2f6..f10f3088bb 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.1.0", - "@fontsource/roboto-condensed": "^5.1.0" + "@fontsource/roboto": "^5.1.1", + "@fontsource/roboto-condensed": "^5.1.1" } } diff --git a/package-lock.json b/package-lock.json index 3d5d094534..2fa45747f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "pm2": "^5.4.3", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.24", + "systeminformation": "^5.24.3", "undici": "^7.2.0" }, "devDependencies": { @@ -36,13 +36,13 @@ "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.10.0", "eslint-plugin-jsdoc": "^50.6.1", - "eslint-plugin-package-json": "^0.18.0", + "eslint-plugin-package-json": "^0.19.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.3.0", - "markdownlint-cli2": "^0.17.0", + "markdownlint-cli2": "^0.17.1", "playwright": "^1.49.1", "prettier": "^3.4.2", "sinon": "^19.0.2", @@ -2573,7 +2573,6 @@ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/ms": "*" } @@ -2645,8 +2644,7 @@ "version": "0.16.7", "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/keyv": { "version": "3.1.4", @@ -2662,8 +2660,7 @@ "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/node": { "version": "20.17.10", @@ -2695,8 +2692,7 @@ "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/yargs": { "version": "17.0.33", @@ -3737,7 +3733,6 @@ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "dev": true, - "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -3748,7 +3743,6 @@ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", "dev": true, - "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -3759,7 +3753,6 @@ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", "dev": true, - "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -4623,7 +4616,6 @@ "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", "dev": true, - "license": "MIT", "dependencies": { "character-entities": "^2.0.0" }, @@ -4772,7 +4764,6 @@ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -4819,7 +4810,6 @@ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "dev": true, - "license": "MIT", "dependencies": { "dequal": "^2.0.0" }, @@ -5637,11 +5627,10 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.18.0.tgz", - "integrity": "sha512-ZyDaHm3c+vDMNoOVyO+KcJxlBnNNFeRML8Ui/WATrQ+F/dyAIR6aIyu50691gll3dCBT26llL2DXMre30x23ug==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.19.0.tgz", + "integrity": "sha512-L1RCeuEcZHrOC2KJqRctgHrndLufICo4VSHNZEnGEF7PkZXWZrxUBc17I5Cdolarlk+5kIW9IJ+zettXUuELHg==", "dev": true, - "license": "MIT", "dependencies": { "@altano/repository-tools": "^0.1.1", "detect-indent": "6.1.0", @@ -7308,7 +7297,6 @@ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", "dev": true, - "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -7319,7 +7307,6 @@ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", "dev": true, - "license": "MIT", "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" @@ -7476,7 +7463,6 @@ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "dev": true, - "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -7561,7 +7547,6 @@ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "dev": true, - "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -8686,15 +8671,14 @@ "license": "MIT" }, "node_modules/katex": { - "version": "0.16.18", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.18.tgz", - "integrity": "sha512-LRuk0rPdXrecAFwQucYjMiIs0JFefk6N1q/04mlw14aVIVgxq1FO0MA9RiIIGVaKOB5GIP5GH4aBBNraZERmaQ==", + "version": "0.16.19", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.19.tgz", + "integrity": "sha512-3IA6DYVhxhBabjSLTNO9S4+OliA3Qvb8pBQXMfC4WxXJgLwZgnfDl0BmB4z6nBMdznBsZ+CGM8DrGZ5hcguDZg==", "dev": true, "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" ], - "license": "MIT", "dependencies": { "commander": "^8.3.0" }, @@ -8707,7 +8691,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, - "license": "MIT", "engines": { "node": ">= 12" } @@ -8814,7 +8797,6 @@ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, - "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" } @@ -9225,7 +9207,6 @@ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -9239,14 +9220,14 @@ } }, "node_modules/markdownlint": { - "version": "0.37.2", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.37.2.tgz", - "integrity": "sha512-m8QhYnRA1ptbhIjhVVBUkKQcUelVxuyO/yXyLewnc1+xs4eXhST/+hIy29goO+EYVLmWtknH4SmYQ4s0caoKqw==", + "version": "0.37.3", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.37.3.tgz", + "integrity": "sha512-eoQqH0291YCCjd+Pe1PUQ9AmWthlVmS0XWgcionkZ8q34ceZyRI+pYvsWksXJJL8OBkWCPwp1h/pnXxrPFC4oA==", "dev": true, - "license": "MIT", "dependencies": { "markdown-it": "14.1.0", "micromark": "4.0.1", + "micromark-core-commonmark": "2.0.2", "micromark-extension-directive": "3.0.2", "micromark-extension-gfm-autolink-literal": "2.1.0", "micromark-extension-gfm-footnote": "2.1.0", @@ -9262,16 +9243,15 @@ } }, "node_modules/markdownlint-cli2": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.17.0.tgz", - "integrity": "sha512-8Xz7wkkkV4wJTf+pvryU3J/fT3BZWD3ZykcjYBR0GuH0GHvrCbswaCdurbuUuAPDGFZy4cxBGYCJSAOW8jM4aQ==", + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.17.1.tgz", + "integrity": "sha512-n1Im9lhKJJE12/u2N0GWBwPqeb0HGdylN8XpSFg9hbj35+QalY9Vi6mxwUQdG6wlSrrIq9ZDQ0Q85AQG9V2WOg==", "dev": true, - "license": "MIT", "dependencies": { "globby": "14.0.2", "js-yaml": "4.1.0", "jsonc-parser": "3.3.1", - "markdownlint": "0.37.2", + "markdownlint": "0.37.3", "markdownlint-cli2-formatter-default": "0.0.5", "micromatch": "4.0.8" }, @@ -9342,8 +9322,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/media-typer": { "version": "0.3.0", @@ -9417,7 +9396,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", @@ -9453,7 +9431,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", @@ -9478,7 +9455,6 @@ "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", "dev": true, - "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", @@ -9498,7 +9474,6 @@ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", "dev": true, - "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", @@ -9515,7 +9490,6 @@ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", "dev": true, - "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", @@ -9536,7 +9510,6 @@ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", "dev": true, - "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", @@ -9554,7 +9527,6 @@ "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", "dev": true, - "license": "MIT", "dependencies": { "@types/katex": "^0.16.0", "devlop": "^1.0.0", @@ -9584,7 +9556,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", @@ -9606,7 +9577,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", @@ -9629,7 +9599,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" @@ -9650,7 +9619,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", @@ -9673,7 +9641,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", @@ -9696,7 +9663,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" @@ -9717,7 +9683,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0" } @@ -9737,7 +9702,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", @@ -9759,7 +9723,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" @@ -9780,7 +9743,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0" } @@ -9799,8 +9761,7 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ], - "license": "MIT" + ] }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", @@ -9816,8 +9777,7 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ], - "license": "MIT" + ] }, "node_modules/micromark-util-normalize-identifier": { "version": "2.0.1", @@ -9834,7 +9794,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0" } @@ -9854,7 +9813,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-types": "^2.0.0" } @@ -9874,7 +9832,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", @@ -9896,7 +9853,6 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", @@ -9918,8 +9874,7 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ], - "license": "MIT" + ] }, "node_modules/micromark-util-types": { "version": "2.0.1", @@ -9935,8 +9890,7 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ], - "license": "MIT" + ] }, "node_modules/micromatch": { "version": "4.0.8", @@ -10601,7 +10555,6 @@ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", "dev": true, - "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", @@ -11342,7 +11295,6 @@ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -13084,10 +13036,9 @@ "license": "0BSD" }, "node_modules/systeminformation": { - "version": "5.23.24", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.24.tgz", - "integrity": "sha512-dPEaqxCaOQMp+5/zCSjuGWbYW2NNBHUZZgI8SNs8xZbLSML2gXvf8OUiqr7Ea1zLkEuH3Tu58DLiNe4kwftPxw==", - "license": "MIT", + "version": "5.24.3", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.24.3.tgz", + "integrity": "sha512-f7uvLgsQIj9/gNcbNZWgw27sNJO5tQvi2tCo4/eVlynxS5slaa7EAN2vSD5jh0YljyjE8qQZ3qtAr7EkDCRyMw==", "os": [ "darwin", "linux", @@ -13527,8 +13478,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/uglify-js": { "version": "3.19.3", diff --git a/package.json b/package.json index 508b359718..0618f529c1 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "pm2": "^5.4.3", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.23.24", + "systeminformation": "^5.24.3", "undici": "^7.2.0" }, "devDependencies": { @@ -88,13 +88,13 @@ "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.10.0", "eslint-plugin-jsdoc": "^50.6.1", - "eslint-plugin-package-json": "^0.18.0", + "eslint-plugin-package-json": "^0.19.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^25.0.1", "lint-staged": "^15.3.0", - "markdownlint-cli2": "^0.17.0", + "markdownlint-cli2": "^0.17.1", "playwright": "^1.49.1", "prettier": "^3.4.2", "sinon": "^19.0.2", From 9be625c72b994ab14f819a4815855ed07b6e902b Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Wed, 1 Jan 2025 08:18:25 -0600 Subject: [PATCH 172/418] ready for release 2.30.0 (#3672) Update files impacted for release --- CHANGELOG.md | 6 ++++-- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2674249c12..0f3af9014b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². -## [2.30.0] - Unreleased (`develop` branch) +## [2.30.0] - 2025-01-01 -_This release is scheduled to be released on 2025-01-01._ +Thanks to: @xsorifc28, @HeikoGr, @bugsounet, @khassel, @KristjanESPERANTO, @rejas, @sdetweil. + +> ⚠️ This release needs nodejs version `v20` or `v22 or higher`, minimum version is `v20.18.1` ### Added diff --git a/package-lock.json b/package-lock.json index 2fa45747f1..31dea2bc8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.30.0-develop", + "version": "2.30.0", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index 0618f529c1..366d4b242d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.30.0-develop", + "version": "2.30.0", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From 6f50a7b3bdce951a0d06b21eeb9de1db9ed435d2 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Wed, 1 Jan 2025 10:33:17 -0600 Subject: [PATCH 173/418] Release 2.31.0 (#3674) begin next release --- CHANGELOG.md | 16 ++++++++++++++++ Collaboration.md | 1 + package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f3af9014b..2b58882f6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². +## [2.31.0-develop] - unreleased + +planned for 2025-04-01 + +> ⚠️ This release needs nodejs version `v20` or `v22 or higher`, minimum version is `v20.18.1` + +### Added + +### Changed + +### Removed + +### Updated + +### Fixed + ## [2.30.0] - 2025-01-01 Thanks to: @xsorifc28, @HeikoGr, @bugsounet, @khassel, @KristjanESPERANTO, @rejas, @sdetweil. diff --git a/Collaboration.md b/Collaboration.md index d2adfc9050..bfcfc0061e 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -37,6 +37,7 @@ Are done by - [ ] add min. node version: > ⚠️ This release needs nodejs version `v20` or `v22`, minimum version is `v20.9.0` - [ ] check release link at the bottom of the file - [ ] commit and push all changes +- [ ] after successful test run via github actions: merge pull request to `develop` - [ ] after successful test run via github actions: create pull request from `develop` to `master` branch - [ ] add label `mastermerge` - [ ] title of the PR is `Release 2.xx.0` diff --git a/package-lock.json b/package-lock.json index 31dea2bc8b..4a204a1ea8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.30.0", + "version": "2.31.0-develop", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.30.0-develop", + "version": "2.31.0-develop", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 366d4b242d..90016705be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.30.0", + "version": "2.31.0-develop", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From 75dbe671677565505b1e261d295dd7c87bdf566f Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Fri, 3 Jan 2025 12:10:29 -0600 Subject: [PATCH 174/418] Fix calendar clipping before broadcast (#3679) -fixes #3678 --- CHANGELOG.md | 2 ++ modules/default/calendar/calendar.js | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b58882f6d..b2410a560c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ planned for 2025-04-01 ### Fixed +- [calendar] fix clipping events being broadcast (#3678) + ## [2.30.0] - 2025-01-01 Thanks to: @xsorifc28, @HeikoGr, @bugsounet, @khassel, @KristjanESPERANTO, @rejas, @sdetweil. diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index c97f353e32..2610b23939 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -692,9 +692,13 @@ Module.register("calendar", { by_url_calevents.sort(function (a, b) { return a.startDate - b.startDate; }); - Log.debug(`pushing ${by_url_calevents.length} events to total with room for ${remainingEntries}`); - events = events.concat(by_url_calevents.slice(0, remainingEntries)); - Log.debug(`events for calendar=${events.length}`); + if (limitNumberOfEntries) { + Log.debug(`pushing ${by_url_calevents.length} events to total with room for ${remainingEntries}`); + events = events.concat(by_url_calevents.slice(0, remainingEntries)); + Log.debug(`events for calendar=${events.length}`); + } else { + events = events.concat(by_url_calevents); + } } Log.info(`sorting events count=${events.length}`); events.sort(function (a, b) { From 0f6efac8e6ef90e1d90c8f64414da1ff8f372ab9 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 3 Jan 2025 21:52:10 +0100 Subject: [PATCH 175/418] clientonly and wayland, hotfix electron tests (#3677) clientonly: - did work only with xserver and `DISPLAY` env var - now checks for `WAYLAND_DISPLAY` or `DISPLAY` env var before running - if `WAYLAND_DISPLAY` is set now starts with wayland parameters electron tests see #3676 --- .github/workflows/automated-tests.yaml | 2 +- CHANGELOG.md | 2 ++ clientonly/index.js | 13 ++++++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index f6dc940b08..f75e17b3d0 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -34,7 +34,7 @@ jobs: npm run test:css npm run test:markdown test: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 30 strategy: matrix: diff --git a/CHANGELOG.md b/CHANGELOG.md index b2410a560c..ddba26071d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ planned for 2025-04-01 ### Changed +- [core] starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) + ### Removed ### Updated diff --git a/clientonly/index.js b/clientonly/index.js index 674355f810..4fe4758263 100644 --- a/clientonly/index.js +++ b/clientonly/index.js @@ -83,6 +83,17 @@ if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].indexOf(config.address) === -1) { getServerConfig(`${prefix}${config.address}:${config.port}/config/`) .then(function (configReturn) { + // check environment for DISPLAY or WAYLAND_DISPLAY + const elecParams = ["js/electron.js"]; + if (process.env.WAYLAND_DISPLAY !== "") { + console.log(`Client: Using WAYLAND_DISPLAY=${process.env.WAYLAND_DISPLAY}`); + elecParams.push("--enable-features=UseOzonePlatform"); + elecParams.push("--ozone-platform=wayland"); + } else if (process.env.DISPLAY !== "") { + console.log(`Client: Using DISPLAY=${process.env.DISPLAY}`); + } else { + fail("Error: Requires environment variable WAYLAND_DISPLAY or DISPLAY, none is provided."); + } // Pass along the server config via an environment variable const env = Object.create(process.env); env.clientonly = true; // set to pass to electron.js @@ -94,7 +105,7 @@ // Spawn electron application const electron = require("electron"); - const child = require("node:child_process").spawn(electron, ["js/electron.js"], options); + const child = require("node:child_process").spawn(electron, elecParams, options); // Pipe all child process output to current stdout child.stdout.on("data", function (buf) { From 8fdd865cb1a205d8a03f11e6fb5a407c7d5531fb Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 5 Jan 2025 11:07:34 +0100 Subject: [PATCH 176/418] electron tests: fixes for running under new github image ubuntu-24.04 (#3680) and replace xserver with labwc, fixes #3676 --- .github/workflows/automated-tests.yaml | 14 ++++++++++---- CHANGELOG.md | 3 ++- tests/electron/env_spec.js | 2 +- tests/electron/helpers/global-setup.js | 4 +++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index f75e17b3d0..b6ab34a6ad 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -34,12 +34,14 @@ jobs: npm run test:css npm run test:markdown test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 30 strategy: matrix: node-version: [20.18.1, 20.x, 22.x, 23.x] steps: + - name: Install electron dependencies and labwc + run: sudo apt-get install -y libnss3 libasound2t64 labwc - name: "Checkout code" uses: actions/checkout@v4 - name: "Use Node.js ${{ matrix.node-version }}" @@ -48,12 +50,16 @@ jobs: node-version: ${{ matrix.node-version }} check-latest: true cache: "npm" - - name: "Install dependencies" + - name: "Install MagicMirror²" run: | npm run install-mm:dev - name: "Run tests" run: | - Xvfb :99 -screen 0 1024x768x16 & - export DISPLAY=:99 + # Fix chrome-sandbox permissions: + sudo chown root:root ./node_modules/electron/dist/chrome-sandbox + sudo chmod 4755 ./node_modules/electron/dist/chrome-sandbox + # Start labwc + WLR_BACKENDS=headless WLR_LIBINPUT_NO_DEVICES=1 WLR_RENDERER=pixman labwc & + export WAYLAND_DISPLAY=wayland-0 touch css/custom.css npm run test diff --git a/CHANGELOG.md b/CHANGELOG.md index ddba26071d..fc5627a88f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,8 @@ planned for 2025-04-01 ### Fixed -- [calendar] fix clipping events being broadcast (#3678) +- [calendar] Fix clipping events being broadcast (#3678) +- [tests] Electron tests: Fixes for running under new github image ubuntu-24.04, replace xserver with labwc (#3676) ## [2.30.0] - 2025-01-01 diff --git a/tests/electron/env_spec.js b/tests/electron/env_spec.js index b0e28789a6..b0f07c1853 100644 --- a/tests/electron/env_spec.js +++ b/tests/electron/env_spec.js @@ -19,7 +19,7 @@ describe("Electron app environment", () => { describe("Development console tests", () => { beforeEach(async () => { - await helpers.startApplication("tests/configs/modules/display.js", null, ["js/electron.js", "dev"]); + await helpers.startApplication("tests/configs/modules/display.js", null, ["dev"]); }); afterEach(async () => { diff --git a/tests/electron/helpers/global-setup.js b/tests/electron/helpers/global-setup.js index 505cb5e3c0..7561e5ecea 100644 --- a/tests/electron/helpers/global-setup.js +++ b/tests/electron/helpers/global-setup.js @@ -3,7 +3,7 @@ // https://www.anycodings.com/1questions/958135/can-i-set-the-date-for-playwright-browser const { _electron: electron } = require("playwright"); -exports.startApplication = async (configFilename, systemDate = null, electronParams = ["js/electron.js"], timezone = "GMT") => { +exports.startApplication = async (configFilename, systemDate = null, electronParams = [], timezone = "GMT") => { global.electronApp = null; global.page = null; process.env.MM_CONFIG_FILE = configFilename; @@ -13,6 +13,8 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar } process.env.mmTestMode = "true"; + electronParams.unshift("js/electron.js", "--enable-features=UseOzonePlatform", "--ozone-platform=wayland"); + global.electronApp = await electron.launch({ args: electronParams }); await global.electronApp.firstWindow(); From 5e337f8b5fc07ce1348416d6e93adf5ebdda6216 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sun, 5 Jan 2025 15:25:32 -0600 Subject: [PATCH 177/418] fix #3267, CORRECTLY, add testcase, add testcase for #3279 (#3681) fixes #3267 AGAIN, correctly, add testcase add testcase for #3679 , broadcast clipping incorrectly I added a test module (tests/testNotification) to catch the notification and check the count. (one way to configure) i put this module in the tests folder, and added /tests to the server paths. (can't have a module in a nested folder, like tests/modules/xxx) but I have a problem. i can run the test config (MM_CONFIG_FILE), and the two modules work correctly, but in the spec runner, the calendar module times out on the broadcast test.. there is only local ics file access, no outside hosts I forced my system date to 1/1/24 (same as runner) and again the manual testcase works fine I added two test config.js,(configs/calendar) one works great (symbols) , one fails (broadcast test) I added additional delay in the calendarspec runner to try to debug the module, but it still not long enough.. no messages of trouble when I get into the browser.. BUT, this may be because of the log being turned off... (just thought of this) I created a special ICS (in mocks) that has 12 events, 1 for each month.. (so I can check clipping and broadcast) the US holidays one is sensitive to the current date, and I couldn't get it to work on 1/1/2024.. also, in general, is there a mechanism to run test:just_one_runner? waiting thru the electron test to get to one testcase.. ugh.. --- CHANGELOG.md | 3 +- js/app.js | 2 +- modules/default/calendar/calendar.js | 13 +- .../modules/calendar/countCalendarEvents.js | 39 +++++ tests/configs/modules/calendar/symboltest.js | 28 +++ tests/electron/modules/calendar_spec.js | 25 ++- tests/mocks/12_events.ics | 164 ++++++++++++++++++ .../testNotification/testNotification.js | 59 +++++++ 8 files changed, 323 insertions(+), 10 deletions(-) create mode 100644 tests/configs/modules/calendar/countCalendarEvents.js create mode 100644 tests/configs/modules/calendar/symboltest.js create mode 100644 tests/mocks/12_events.ics create mode 100644 tests/mocks/testNotification/testNotification.js diff --git a/CHANGELOG.md b/CHANGELOG.md index fc5627a88f..7d95e1c565 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,8 +25,9 @@ planned for 2025-04-01 ### Fixed -- [calendar] Fix clipping events being broadcast (#3678) +- [calendar] fix clipping events being broadcast (#3678) - [tests] Electron tests: Fixes for running under new github image ubuntu-24.04, replace xserver with labwc (#3676) +- [calendar] fix arrayed symbols, #3267, again, add testcase, add testcase for #3678 ## [2.30.0] - 2025-01-01 diff --git a/js/app.js b/js/app.js index 020139439a..ffe3616df8 100644 --- a/js/app.js +++ b/js/app.js @@ -177,7 +177,7 @@ function App () { moduleFolder = defaultModuleFolder; } else { // running in Jest, allow defaultModules placed under moduleDir for testing - if (env.modulesDir === "modules") { + if (env.modulesDir === "modules" || env.modulesDir === "tests/mocks") { moduleFolder = defaultModuleFolder; } } diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 2610b23939..e2f921db28 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -689,10 +689,11 @@ Module.register("calendar", { by_url_calevents.push(event); } } - by_url_calevents.sort(function (a, b) { - return a.startDate - b.startDate; - }); if (limitNumberOfEntries) { + // sort entries before clipping + by_url_calevents.sort(function (a, b) { + return a.startDate - b.startDate; + }); Log.debug(`pushing ${by_url_calevents.length} events to total with room for ${remainingEntries}`); events = events.concat(by_url_calevents.slice(0, remainingEntries)); Log.debug(`events for calendar=${events.length}`); @@ -911,7 +912,11 @@ Module.register("calendar", { let p = this.getCalendarProperty(url, property, defaultValue); if (property === "symbol" || property === "recurringSymbol" || property === "fullDaySymbol") { const className = this.getCalendarProperty(url, "symbolClassName", this.config.defaultSymbolClassName); - if (p instanceof Array) p.push(className); + if (p instanceof Array) { + let t = []; + p.forEach((n) => { t.push(className + n); }); + p = t; + } else p = className + p; } if (!(p instanceof Array)) p = [p]; diff --git a/tests/configs/modules/calendar/countCalendarEvents.js b/tests/configs/modules/calendar/countCalendarEvents.js new file mode 100644 index 0000000000..ea3244b96d --- /dev/null +++ b/tests/configs/modules/calendar/countCalendarEvents.js @@ -0,0 +1,39 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 12, + foreignModulesDir: "tests/mocks", + modules: [ + { + module: "calendar", + position: "bottom_bar", + + config: { + maximumEntries: 1, + calendars: [ + { + fetchInterval: 10000, //7 * 24 * 60 * 60 * 1000, + symbol: ["calendar-check", "google"], + url: "http://localhost:8080/tests/mocks/12_events.ics" + } + ] + } + }, + { + module: "testNotification", + position: "bottom_bar", + config: { + debug: true, + match: { + matchtype: "count", + notificationID: "CALENDAR_EVENTS" + } + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/calendar/symboltest.js b/tests/configs/modules/calendar/symboltest.js new file mode 100644 index 0000000000..f31c54d84b --- /dev/null +++ b/tests/configs/modules/calendar/symboltest.js @@ -0,0 +1,28 @@ + +let config = { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + maximumEntries: 1, + calendars: [ + { + fetchInterval: 7 * 24 * 60 * 60 * 1000, + symbol: ["calendar-check", "google"], + url: "https://ics.calendarlabs.com/76/mm3137/US_Holidays.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index f73d673489..0cf9bec5a9 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -13,9 +13,9 @@ describe("Calendar module", () => { return true; }; - const doTestCount = async () => { + const doTestCount = async (locator = ".calendar .event") => { expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); + const loc = await global.page.locator(locator); const elem = loc.first(); await elem.waitFor(); expect(elem).not.toBeNull(); @@ -32,8 +32,8 @@ describe("Calendar module", () => { // uses playwright nth locator syntax const doTestTableContent = async (table_row, table_column, content, row = first) => { const elem = await global.page.locator(table_row); - const date = await global.page.locator(table_column).locator(`nth=${row}`); - await expect(date.textContent()).resolves.toContain(content); + const column = await elem.locator(table_column).locator(`nth=${row}`); + await expect(column.textContent()).resolves.toContain(content); return true; }; @@ -279,4 +279,21 @@ describe("Calendar module", () => { }); }); + describe("count and check symbols", () => { + it("in array", async () => { + await helpers.startApplication("tests/configs/modules/calendar/symboltest.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + // just + await expect(doTestCount(".calendar .event .symbol .fa-fw")).resolves.toBe(2); + await expect(doTestCount(".calendar .event .symbol .fa-calendar-check")).resolves.toBe(1); + await expect(doTestCount(".calendar .event .symbol .fa-google")).resolves.toBe(1); + + }); + }); + + describe("count events broadcast", () => { + it("get 12 with maxentries set to 1", async () => { + await helpers.startApplication("tests/configs/modules/calendar/countCalendarEvents.js", "01 Jan 2024 12:30:00 GMT-076:00", ["js/electron.js"], "America/Chicago"); + await expect(doTestTableContent(".testNotification", ".elementCount", "12", first)).resolves.toBe(true); + }); + }); }); diff --git a/tests/mocks/12_events.ics b/tests/mocks/12_events.ics new file mode 100644 index 0000000000..f89c938129 --- /dev/null +++ b/tests/mocks/12_events.ics @@ -0,0 +1,164 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//Calendar Labs//Calendar 1.0//EN +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:US Holidays +X-WR-TIMEZONE:Etc/GMT +BEGIN:VEVENT +SUMMARY:Start of Month 1 +DTSTART:20190101 +DTEND:20190101 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e52949sada28d231582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 2 +DTSTART:20190201 +DTEND:20190201 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e52949a2wds8d231582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 3 +DTSTART:20190301 +DTEND:20190301 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e52949a2SDD8d231582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 4 +DTSTART:20190401 +DTEND:20190401 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e52949a2SDD8d231582FDSFD470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 5 +DTSTART:20190501 +DTEND:20190501 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e52949a2SDD8d2DD315824702598@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 6 +DTSTART:20190601 +DTEND:20190601 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e52949a2SDD8d2DD31582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 7 +DTSTART:20190701 +DTEND:20190701 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e52942SDD8d2DD31582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 8 +DTSTART:20190801 +DTEND:20190801 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e52949a2SDD8d2DDt31582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 9 +DTSTART:20190901 +DTEND:20190901 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e529449a2SDD8d2DDt315824702798@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 10 +DTSTART:20191001 +DTEND:20191001 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e529449a2SDD8d2DDt31582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 11 +DTSTART:20191101 +DTEND:20191101 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e5294449a2SDD8d2DDt31582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +BEGIN:VEVENT +SUMMARY:Start of Month 12 +DTSTART:20191201 +DTEND:20191201 +RRULE:FREQ=YEARLY;WKST=SU;INTERVAL=1 +LOCATION:United States +DESCRIPTION:Visit https://calendarlabs.com/holidays/us/new-years-day.php to know more about New Year's Day. \n\n Like us on Facebook: http://fb.com/calendarlabs to get updates +UID:5e5294a2SDD8d2DDt31582470298@calendarlabs.com +DTSTAMP:20200223T150458Z +STATUS:CONFIRMED +TRANSP:TRANSPARENT +SEQUENCE:0 +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/testNotification/testNotification.js b/tests/mocks/testNotification/testNotification.js new file mode 100644 index 0000000000..735af025a3 --- /dev/null +++ b/tests/mocks/testNotification/testNotification.js @@ -0,0 +1,59 @@ +Module.register("testNotification", { + defaults: { + debug: false, + match: { + notificationID: "", + matchtype: "count" + //or + // type: 'contents' // look for item in field of content + } + }, + count: 0, + table: null, + notificationReceived (notification, payload) { + if (notification === this.config.match.notificationID) { + if (this.config.match.matchtype === "count") { + this.count = payload.length; + if (this.count) { + this.table = document.createElement("table"); + this.addTableRow(this.table, null, `${this.count}:elementCount`); + if (this.config.debug) { + payload.forEach((e, i) => { + this.addTableRow(this.table, i, e.title); + }); + } + } + + this.updateDom(); + } + } + }, + maketd (row, info) { + let td = document.createElement("td"); + row.appendChild(td); + if (info !== null) { + let colinfo = info.toString().split(":"); + if (colinfo.length === 2) td.className = colinfo[1]; + td.innerText = colinfo[0]; + } + return td; + }, + addTableRow (table, col1 = null, col2 = null, col3 = null) { + 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); + + return tableRow; + }, + getDom () { + let wrapper = document.createElement("div"); + if (this.table) { + wrapper.appendChild(this.table); + } + return wrapper; + } + +}); From b1bc5547290474399f7f0e08a2924215016bded4 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 6 Jan 2025 21:20:19 +0100 Subject: [PATCH 178/418] Update year (#3686) I also added a few new words to the cspell dictionary that were added in the changelog. I have not made an extra entry in the changelog for these tiny things. --- CHANGELOG.md | 2 +- Collaboration.md | 1 + LICENSE.md | 2 +- cspell.config.json | 7 +++++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d95e1c565..80380e1cbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,7 @@ Thanks to: @xsorifc28, @HeikoGr, @bugsounet, @khassel, @KristjanESPERANTO, @reja - [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586) - [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643) - [linter] Add linting for markdown files (#3646) -- [linter] Add some handy ESLint rules. +- [linter] Add some handy ESLint rules (#3665) - [calendar] Add ability to display end date for full date events, where end is not same day (showEnd=true) (#3650) - [core] Add text to the config.js.sample file about the locale variable (#3654, #3655) - [core] Add fetch timeout for all node_helpers (thru undici, forces node 20.18.1 minimum) to help on slower systems. (#3660) (3661) diff --git a/Collaboration.md b/Collaboration.md index bfcfc0061e..ddf18ef723 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -55,6 +55,7 @@ Are done by - [ ] draft new section in `CHANGELOG.md` - [ ] create new release link at the bottom of the file - [ ] commit and publish `develop` branch +- [ ] if new release will be in January, update the year in LICENSE.md ### After release diff --git a/LICENSE.md b/LICENSE.md index 506207e0c4..646b0598d2 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ # The MIT License (MIT) -Copyright © 2016-2024 Michael Teeuw +Copyright © 2016-2025 Michael Teeuw Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/cspell.config.json b/cspell.config.json index 1faa7e6502..a4ecc259fd 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -58,6 +58,7 @@ "eddiehung", "Edgardos", "Ekristoffe", + "elec", "envcanada", "envsub", "envsubst", @@ -85,6 +86,7 @@ "GHSA", "ghsas", "grenagit", + "Heiko", "Hirschberger", "hourlyweather", "Hwind", @@ -117,6 +119,7 @@ "krekos", "Kristjan", "krukle", + "labwc", "Landis", "larryare", "letsencrypt", @@ -132,6 +135,8 @@ "martingron", "marvai", "mastermerge", + "matchtype", + "maxentries", "Meteo", "michaelteeuw", "michmich", @@ -195,6 +200,7 @@ "sunaction", "suncalc", "suntimes", + "symboltest", "systeminformation", "tada", "taglist", @@ -228,6 +234,7 @@ "xlarge", "xrandr", "xsmall", + "xsorifc", "xwindows", "xxxe", "Ybbet", From 553d2d4a2145a9b4fa1b47035879e9edc6a92a83 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 8 Jan 2025 11:46:42 +0100 Subject: [PATCH 179/418] electron tests (#3684) - fix setup to run with xserver and labwc - remove electronParams from calendar_spec.js (forgotten in https://github.com/MagicMirrorOrg/MagicMirror/pull/3680) fixes [running tests locally without labwc installed](https://github.com/MagicMirrorOrg/MagicMirror/pull/3681#issuecomment-2571736233) follow up to https://github.com/MagicMirrorOrg/MagicMirror/pull/3680 --- CHANGELOG.md | 2 +- clientonly/index.js | 4 +- tests/electron/helpers/global-setup.js | 7 +++- tests/electron/modules/calendar_spec.js | 50 ++++++++++++------------- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80380e1cbb..df0789e079 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ planned for 2025-04-01 ### Fixed - [calendar] fix clipping events being broadcast (#3678) -- [tests] Electron tests: Fixes for running under new github image ubuntu-24.04, replace xserver with labwc (#3676) +- [tests] Electron tests: Fixes for running under new github image ubuntu-24.04, replace xserver with labwc, running under xserver and labwc depending on env variable WAYLAND_DISPLAY is set (#3676) - [calendar] fix arrayed symbols, #3267, again, add testcase, add testcase for #3678 ## [2.30.0] - 2025-01-01 diff --git a/clientonly/index.js b/clientonly/index.js index 4fe4758263..e1ad59c5de 100644 --- a/clientonly/index.js +++ b/clientonly/index.js @@ -85,11 +85,11 @@ .then(function (configReturn) { // check environment for DISPLAY or WAYLAND_DISPLAY const elecParams = ["js/electron.js"]; - if (process.env.WAYLAND_DISPLAY !== "") { + if (process.env.WAYLAND_DISPLAY) { console.log(`Client: Using WAYLAND_DISPLAY=${process.env.WAYLAND_DISPLAY}`); elecParams.push("--enable-features=UseOzonePlatform"); elecParams.push("--ozone-platform=wayland"); - } else if (process.env.DISPLAY !== "") { + } else if (process.env.DISPLAY) { console.log(`Client: Using DISPLAY=${process.env.DISPLAY}`); } else { fail("Error: Requires environment variable WAYLAND_DISPLAY or DISPLAY, none is provided."); diff --git a/tests/electron/helpers/global-setup.js b/tests/electron/helpers/global-setup.js index 7561e5ecea..b95ad5217d 100644 --- a/tests/electron/helpers/global-setup.js +++ b/tests/electron/helpers/global-setup.js @@ -13,7 +13,12 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar } process.env.mmTestMode = "true"; - electronParams.unshift("js/electron.js", "--enable-features=UseOzonePlatform", "--ozone-platform=wayland"); + // check environment for DISPLAY or WAYLAND_DISPLAY + if (process.env.WAYLAND_DISPLAY) { + electronParams.unshift("js/electron.js", "--enable-features=UseOzonePlatform", "--ozone-platform=wayland"); + } else { + electronParams.unshift("js/electron.js"); + } global.electronApp = await electron.launch({ args: electronParams }); diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 0cf9bec5a9..6143d29a36 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -81,7 +81,7 @@ describe("Calendar module", () => { */ describe("rrule", () => { it("Issue #3393 recurrence dates past rrule until date", async () => { - await helpers.startApplication("tests/configs/modules/calendar/rrule_until.js", "07 Mar 2024 10:38:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + await helpers.startApplication("tests/configs/modules/calendar/rrule_until.js", "07 Mar 2024 10:38:00 GMT-07:00", [], "America/Los_Angeles"); await expect(doTestCount()).resolves.toBe(1); }); }); @@ -98,20 +98,20 @@ describe("Calendar module", () => { */ describe("Exdate: LA crossover DST before midnight GMT", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { - await helpers.startApplication("tests/configs/modules/calendar/exdate_la_before_midnight.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + await helpers.startApplication("tests/configs/modules/calendar/exdate_la_before_midnight.js", "19 Oct 2023 12:30:00 GMT-07:00", [], "America/Los_Angeles"); await expect(doTestCount()).resolves.toBe(2); }); }); describe("Exdate: LA crossover DST at midnight GMT local STD", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { - await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_std.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_std.js", "19 Oct 2023 12:30:00 GMT-07:00", [], "America/Los_Angeles"); await expect(doTestCount()).resolves.toBe(2); }); }); describe("Exdate: LA crossover DST at midnight GMT local DST", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { - await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_dst.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_dst.js", "19 Oct 2023 12:30:00 GMT-07:00", [], "America/Los_Angeles"); await expect(doTestCount()).resolves.toBe(2); }); }); @@ -128,19 +128,19 @@ describe("Calendar module", () => { */ describe("Exdate: SYD crossover DST before midnight GMT", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { - await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_before_midnight.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); + await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_before_midnight.js", "14 Sep 2023 12:30:00 GMT+10:00", [], "Australia/Sydney"); await expect(doTestCount()).resolves.toBe(2); }); }); describe("Exdate: SYD crossover DST at midnight GMT local STD", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { - await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_std.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); + await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_std.js", "14 Sep 2023 12:30:00 GMT+10:00", [], "Australia/Sydney"); await expect(doTestCount()).resolves.toBe(2); }); }); describe("Exdate: SYD crossover DST at midnight GMT local DST", () => { it("SYD crossover DST at midnight GMT local DST should have 2 events", async () => { - await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney"); + await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js", "14 Sep 2023 12:30:00 GMT+10:00", [], "Australia/Sydney"); await expect(doTestCount()).resolves.toBe(2); }); }); @@ -151,7 +151,7 @@ describe("Calendar module", () => { */ describe("sliceMultiDayEvents", () => { it("Issue #3452 split multiday in Europe", async () => { - await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", [], "Europe/Berlin"); expect(global.page).not.toBeNull(); const loc = await global.page.locator(".calendar .event"); const elem = loc.first(); @@ -164,56 +164,56 @@ describe("Calendar module", () => { describe("sliceMultiDayEvents direct count", () => { it("Issue #3452 split multiday in Europe", async () => { - await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", [], "Europe/Berlin"); await expect(doTestCount()).resolves.toBe(6); }); }); describe("germany timezone", () => { it("Issue #unknown fullday timezone East of UTC edge", async () => { - await helpers.startApplication("tests/configs/modules/calendar/germany_at_end_of_day_repeating.js", "01 Oct 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await helpers.startApplication("tests/configs/modules/calendar/germany_at_end_of_day_repeating.js", "01 Oct 2024 10:38:00 GMT+02:00", [], "Europe/Berlin"); await expect(doTestTableContent(".calendar .event", ".time", "Oct 22nd, 23:00", first)).resolves.toBe(true); }); }); describe("germany all day repeating moved (recurrence and exdate)", () => { it("Issue #unknown fullday timezone East of UTC event moved", async () => { - await helpers.startApplication("tests/configs/modules/calendar/3_move_first_allday_repeating_event.js", "01 Oct 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await helpers.startApplication("tests/configs/modules/calendar/3_move_first_allday_repeating_event.js", "01 Oct 2024 10:38:00 GMT+02:00", [], "Europe/Berlin"); await expect(doTestTableContent(".calendar .event", ".time", "12th.Oct")).resolves.toBe(true); }); }); describe("chicago late in timezone", () => { it("Issue #unknown rrule US close to timezone edge", async () => { - await helpers.startApplication("tests/configs/modules/calendar/chicago_late_in_timezone.js", "01 Sept 2024 10:38:00 GMT-5:00", ["js/electron.js"], "America/Chicago"); + await helpers.startApplication("tests/configs/modules/calendar/chicago_late_in_timezone.js", "01 Sept 2024 10:38:00 GMT-5:00", [], "America/Chicago"); await expect(doTestTableContent(".calendar .event", ".time", "10th.Sep, 20:15")).resolves.toBe(true); }); }); describe("berlin late in day event moved, viewed from berlin", () => { it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { - await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "Europe/Berlin"); await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 23:00-00:00", last)).resolves.toBe(true); }); }); describe("berlin late in day event moved, viewed from sydney", () => { it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { - await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Australia/Sydney"); + await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "Australia/Sydney"); await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 01:00-02:00", last)).resolves.toBe(true); }); }); describe("berlin late in day event moved, viewed from chicago", () => { it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { - await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "America/Chicago"); + await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "America/Chicago"); await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 16:00-17:00", last)).resolves.toBe(true); }); }); describe("berlin multi-events inside offset", () => { it("some events before DST. some after midnight", async () => { - await helpers.startApplication("tests/configs/modules/calendar/berlin_multi.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await helpers.startApplication("tests/configs/modules/calendar/berlin_multi.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "Europe/Berlin"); await expect(doTestTableContent(".calendar .event", ".time", "30th.Oct, 00:00-01:00", last)).resolves.toBe(true); await expect(doTestTableContent(".calendar .event", ".time", "21st.Oct, 00:00-01:00", first)).resolves.toBe(true); }); @@ -221,7 +221,7 @@ describe("Calendar module", () => { describe("berlin whole day repeating, start moved after end", () => { it("some events before DST. some after", async () => { - await helpers.startApplication("tests/configs/modules/calendar/berlin_whole_day_event_moved_over_dst_change.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await helpers.startApplication("tests/configs/modules/calendar/berlin_whole_day_event_moved_over_dst_change.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "Europe/Berlin"); await expect(doTestTableContent(".calendar .event", ".time", "30th.Oct", last)).resolves.toBe(true); await expect(doTestTableContent(".calendar .event", ".time", "27th.Oct", first)).resolves.toBe(true); }); @@ -229,7 +229,7 @@ describe("Calendar module", () => { describe("berlin 11pm-midnight", () => { it("right inside the offset, before midnight", async () => { - await helpers.startApplication("tests/configs/modules/calendar/berlin_end_of_day_repeating.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin"); + await helpers.startApplication("tests/configs/modules/calendar/berlin_end_of_day_repeating.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "Europe/Berlin"); await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 23:00-00:00", last)).resolves.toBe(true); await expect(doTestTableContent(".calendar .event", ".time", "22nd.Oct, 23:00-00:00", first)).resolves.toBe(true); }); @@ -237,7 +237,7 @@ describe("Calendar module", () => { describe("both moved and delete events in recurring list", () => { it("with moved before and after original", async () => { - await helpers.startApplication("tests/configs/modules/calendar/exdate_and_recurrence_together.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); + await helpers.startApplication("tests/configs/modules/calendar/exdate_and_recurrence_together.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Los_Angeles"); // moved after end at oct 26 await expect(doTestTableContent(".calendar .event", ".time", "27th.Oct, 14:30-15:30", last)).resolves.toBe(true); // moved before start at oct 23 @@ -249,7 +249,7 @@ describe("Calendar module", () => { describe("one event diff tz", () => { it("start/end in diff timezones", async () => { - await helpers.startApplication("tests/configs/modules/calendar/diff_tz_start_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + await helpers.startApplication("tests/configs/modules/calendar/diff_tz_start_end.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Chicago"); // just await expect(doTestTableContent(".calendar .event", ".time", "29th.Oct, 05:00-30th.Oct, 18:00", first)).resolves.toBe(true); }); @@ -257,7 +257,7 @@ describe("Calendar module", () => { describe("one event non repeating", () => { it("fullday non-repeating", async () => { - await helpers.startApplication("tests/configs/modules/calendar/fullday_event_over_multiple_days_nonrepeating.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + await helpers.startApplication("tests/configs/modules/calendar/fullday_event_over_multiple_days_nonrepeating.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Chicago"); // just await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct-30th.Oct", first)).resolves.toBe(true); }); @@ -265,7 +265,7 @@ describe("Calendar module", () => { describe("one event no end display", () => { it("don't display end", async () => { - await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Chicago"); // just await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 20:00", first)).resolves.toBe(true); }); @@ -273,7 +273,7 @@ describe("Calendar module", () => { describe("display end display end", () => { it("display end", async () => { - await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Chicago"); // just await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 20:00-26th.Oct, 06:00", first)).resolves.toBe(true); }); @@ -281,7 +281,7 @@ describe("Calendar module", () => { describe("count and check symbols", () => { it("in array", async () => { - await helpers.startApplication("tests/configs/modules/calendar/symboltest.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago"); + await helpers.startApplication("tests/configs/modules/calendar/symboltest.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Chicago"); // just await expect(doTestCount(".calendar .event .symbol .fa-fw")).resolves.toBe(2); await expect(doTestCount(".calendar .event .symbol .fa-calendar-check")).resolves.toBe(1); @@ -292,7 +292,7 @@ describe("Calendar module", () => { describe("count events broadcast", () => { it("get 12 with maxentries set to 1", async () => { - await helpers.startApplication("tests/configs/modules/calendar/countCalendarEvents.js", "01 Jan 2024 12:30:00 GMT-076:00", ["js/electron.js"], "America/Chicago"); + await helpers.startApplication("tests/configs/modules/calendar/countCalendarEvents.js", "01 Jan 2024 12:30:00 GMT-076:00", [], "America/Chicago"); await expect(doTestTableContent(".testNotification", ".elementCount", "12", first)).resolves.toBe(true); }); }); From a7f814d76b74c08c34c630a926e25d5ce1a0efd3 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 12 Jan 2025 23:27:31 +0100 Subject: [PATCH 180/418] Optimize systeminformation calls and output string (#3689) Since we don't use the `raspberry` information, calling it in `si.get` is useless. I also made the string construction in the code a bit more readable. The output remains the same. --- CHANGELOG.md | 3 ++- js/utils.js | 13 +++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df0789e079..167a8ae749 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ planned for 2025-04-01 ### Changed -- [core] starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) +- [core] starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) (#3677) +- [core] Optimize systeminformation calls and output ### Removed diff --git a/js/utils.js b/js/utils.js index 2900317e97..de3032a420 100644 --- a/js/utils.js +++ b/js/utils.js @@ -19,15 +19,16 @@ module.exports = { let installedNodeVersion = execSync("node -v", { encoding: "utf-8" }).replace("v", "").replace(/(?:\r\n|\r|\n)/g, ""); const staticData = await si.get({ - system: "manufacturer, model, raspberry, virtual", + system: "manufacturer, model, virtual", osInfo: "platform, distro, release, arch", versions: "kernel, node, npm, pm2" }); - let systemDataString = "System information:"; - systemDataString += `\n### SYSTEM: manufacturer: ${staticData.system.manufacturer}; model: ${staticData.system.model}; virtual: ${staticData.system.virtual}`; - systemDataString += `\n### OS: platform: ${staticData.osInfo.platform}; distro: ${staticData.osInfo.distro}; release: ${staticData.osInfo.release}; arch: ${staticData.osInfo.arch}; kernel: ${staticData.versions.kernel}`; - systemDataString += `\n### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData.versions.node}; installed node: ${installedNodeVersion}; npm: ${staticData.versions.npm}; pm2: ${staticData.versions.pm2}`; - systemDataString += `\n### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}`; + let systemDataString = `System information: + ### SYSTEM: manufacturer: ${staticData.system.manufacturer}; model: ${staticData.system.model}; virtual: ${staticData.system.virtual} + ### OS: platform: ${staticData.osInfo.platform}; distro: ${staticData.osInfo.distro}; release: ${staticData.osInfo.release}; arch: ${staticData.osInfo.arch}; kernel: ${staticData.versions.kernel} + ### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData.versions.node}; installed node: ${installedNodeVersion}; npm: ${staticData.versions.npm}; pm2: ${staticData.versions.pm2} + ### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}` + .replace(/\t/g, ""); Log.info(systemDataString); // Return is currently only for jest From 99dda821d3ec423465557ddca67fa2336492b4db Mon Sep 17 00:00:00 2001 From: Veeck Date: Mon, 13 Jan 2025 20:09:33 +0100 Subject: [PATCH 181/418] Fix unknown (n/a) icon in openmeteo provider (#3691) Due to a typo the icon displayed in the openmeteo provider was "N/A" for a certain weather condition Bildschirmfoto 2025-01-13 um 16 35 40 --------- Co-authored-by: veeck --- CHANGELOG.md | 5 +++-- modules/default/weather/providers/openmeteo.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 167a8ae749..be656bb621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,9 +26,10 @@ planned for 2025-04-01 ### Fixed -- [calendar] fix clipping events being broadcast (#3678) +- [calendar] Fix clipping events being broadcast (#3678) - [tests] Electron tests: Fixes for running under new github image ubuntu-24.04, replace xserver with labwc, running under xserver and labwc depending on env variable WAYLAND_DISPLAY is set (#3676) -- [calendar] fix arrayed symbols, #3267, again, add testcase, add testcase for #3678 +- [calendar] Fix arrayed symbols, #3267, again, add testcase, add testcase for #3678 +- [weather] Fix wrong weatherCondition name in openmeteo provider which lead to n/a icon ## [2.30.0] - 2025-01-01 diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index b89510c000..0d1fec4366 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -470,7 +470,7 @@ WeatherProvider.register("openmeteo", { 61: "rain-slight-intensity", 63: "rain-moderate-intensity", 65: "rain-heavy-intensity", - 66: "freezing-rain-light-heavy-intensity", + 66: "freezing-rain-light-intensity", 67: "freezing-rain-heavy-intensity", 71: "snow-fall-slight-intensity", 73: "snow-fall-moderate-intensity", From 2400e2045fb4ce54ea2a83055073f6027ede4f9d Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 13 Jan 2025 21:36:44 +0100 Subject: [PATCH 182/418] update dependencies and formatting (#3693) after updating deps 2 files needed formatting updates --- CHANGELOG.md | 2 + modules/default/clock/clock.js | 8 +- modules/default/weather/weatherutils.js | 16 +- package-lock.json | 1498 ++++++++++++++--------- package.json | 20 +- 5 files changed, 974 insertions(+), 570 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be656bb621..782ecb47e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ planned for 2025-04-01 ### Updated +- [core] Update dependencies and formatting + ### Fixed - [calendar] Fix clipping events being broadcast (#3678) diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 42b066ab58..5d2a17c87d 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -181,8 +181,8 @@ Module.register("clock", { const untilNextEventString = `${untilNextEvent.hours()}h ${untilNextEvent.minutes()}m`; sunWrapper.innerHTML = ` ${untilNextEventString}` - + ` ${formatTime(this.config, sunTimes.sunrise)}` - + ` ${formatTime(this.config, sunTimes.sunset)}`; + + ` ${formatTime(this.config, sunTimes.sunrise)}` + + ` ${formatTime(this.config, sunTimes.sunset)}`; digitalWrapper.appendChild(sunWrapper); } @@ -208,8 +208,8 @@ Module.register("clock", { moonWrapper.innerHTML = `${image} ${showFraction ? illuminatedFractionString : ""}` - + ` ${moonRise ? formatTime(this.config, moonRise) : "..."}` - + ` ${moonSet ? formatTime(this.config, moonSet) : "..."}`; + + ` ${moonRise ? formatTime(this.config, moonRise) : "..."}` + + ` ${moonSet ? formatTime(this.config, moonSet) : "..."}`; digitalWrapper.appendChild(moonWrapper); } diff --git a/modules/default/weather/weatherutils.js b/modules/default/weather/weatherutils.js index 4d6ce45bf9..75414143f1 100644 --- a/modules/default/weather/weatherutils.js +++ b/modules/default/weather/weatherutils.js @@ -128,14 +128,14 @@ const WeatherUtils = { } else if (tempInF > 80 && humidity > 40) { feelsLike = -42.379 - + 2.04901523 * tempInF - + 10.14333127 * humidity - - 0.22475541 * tempInF * humidity - - 6.83783 * Math.pow(10, -3) * tempInF * tempInF - - 5.481717 * Math.pow(10, -2) * humidity * humidity - + 1.22874 * Math.pow(10, -3) * tempInF * tempInF * humidity - + 8.5282 * Math.pow(10, -4) * tempInF * humidity * humidity - - 1.99 * Math.pow(10, -6) * tempInF * tempInF * humidity * humidity; + + 2.04901523 * tempInF + + 10.14333127 * humidity + - 0.22475541 * tempInF * humidity + - 6.83783 * Math.pow(10, -3) * tempInF * tempInF + - 5.481717 * Math.pow(10, -2) * humidity * humidity + + 1.22874 * Math.pow(10, -3) * tempInF * tempInF * humidity + + 8.5282 * Math.pow(10, -4) * tempInF * humidity * humidity + - 1.99 * Math.pow(10, -6) * tempInF * tempInF * humidity * humidity; } return ((feelsLike - 32) * 5) / 9; diff --git a/package-lock.json b/package-lock.json index 4a204a1ea8..23a62b010d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,10 @@ "license": "MIT", "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.5.2", + "ansis": "^3.9.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.17.0", + "eslint": "^9.18.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -27,12 +27,12 @@ "pm2": "^5.4.3", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.24.3", - "undici": "^7.2.0" + "systeminformation": "^5.25.11", + "undici": "^7.2.1" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.12.1", - "cspell": "^8.17.1", + "@stylistic/eslint-plugin": "^2.13.0", + "cspell": "^8.17.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.10.0", "eslint-plugin-jsdoc": "^50.6.1", @@ -40,21 +40,21 @@ "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", - "jsdom": "^25.0.1", + "jsdom": "^26.0.0", "lint-staged": "^15.3.0", "markdownlint-cli2": "^0.17.1", "playwright": "^1.49.1", "prettier": "^3.4.2", "sinon": "^19.0.2", - "stylelint": "^16.12.0", - "stylelint-config-standard": "^36.0.1", + "stylelint": "^16.13.1", + "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.2" }, "engines": { "node": ">=20.18.1 <21 || >=22" }, "optionalDependencies": { - "electron": "^32.2.7" + "electron": "^32.2.8" } }, "node_modules/@altano/repository-tools": { @@ -78,6 +78,30 @@ "node": ">=6.0.0" } }, + "node_modules/@asamuzakjp/css-color": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.2.tgz", + "integrity": "sha512-RtWv9jFN2/bLExuZgFFZ0I3pWWeezAHGgrmjqGGWclATl1aDe3yhCUaI0Ilkp6OCk9zX7+FjvDasEX8Q9Rxc5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.1", + "@csstools/css-color-parser": "^3.0.7", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^11.0.2" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -94,9 +118,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", - "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", "dev": true, "license": "MIT", "engines": { @@ -145,14 +169,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -162,13 +186,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.9", + "@babel/compat-data": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -221,9 +245,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, "license": "MIT", "engines": { @@ -275,13 +299,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", + "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.3" + "@babel/types": "^7.26.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -545,17 +569,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.26.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", - "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", + "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.3", - "@babel/parser": "^7.26.3", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.5", "@babel/template": "^7.25.9", - "@babel/types": "^7.26.3", + "@babel/types": "^7.26.5", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -574,9 +598,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", "dev": true, "license": "MIT", "dependencies": { @@ -595,89 +619,92 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.1.tgz", - "integrity": "sha512-HmkXS5uX4bk/XxsRS4Q+zRvhgRa81ddGiR2/Xfag9MIi5L5UnEJ4g21EpmIlXkMxYrTu2fp69SZFss5NfcFF9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/dict-ada": "^4.0.5", - "@cspell/dict-al": "^1.0.3", - "@cspell/dict-aws": "^4.0.7", - "@cspell/dict-bash": "^4.1.8", - "@cspell/dict-companies": "^3.1.8", - "@cspell/dict-cpp": "^6.0.2", - "@cspell/dict-cryptocurrencies": "^5.0.3", - "@cspell/dict-csharp": "^4.0.5", - "@cspell/dict-css": "^4.0.16", - "@cspell/dict-dart": "^2.2.4", - "@cspell/dict-django": "^4.1.3", - "@cspell/dict-docker": "^1.1.11", - "@cspell/dict-dotnet": "^5.0.8", - "@cspell/dict-elixir": "^4.0.6", - "@cspell/dict-en_us": "^4.3.28", - "@cspell/dict-en-common-misspellings": "^2.0.7", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.2.tgz", + "integrity": "sha512-t+DQtruJF2cYfXF5GC4F0O/PQR04hL5WH55R9oOaor5i7K8ejbw6+jex2LB0XbZFf3qBhXNSnMPuM3b/113LnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-ada": "^4.1.0", + "@cspell/dict-al": "^1.1.0", + "@cspell/dict-aws": "^4.0.9", + "@cspell/dict-bash": "^4.2.0", + "@cspell/dict-companies": "^3.1.12", + "@cspell/dict-cpp": "^6.0.3", + "@cspell/dict-cryptocurrencies": "^5.0.4", + "@cspell/dict-csharp": "^4.0.6", + "@cspell/dict-css": "^4.0.17", + "@cspell/dict-dart": "^2.3.0", + "@cspell/dict-data-science": "^2.0.6", + "@cspell/dict-django": "^4.1.4", + "@cspell/dict-docker": "^1.1.12", + "@cspell/dict-dotnet": "^5.0.9", + "@cspell/dict-elixir": "^4.0.7", + "@cspell/dict-en_us": "^4.3.29", + "@cspell/dict-en-common-misspellings": "^2.0.8", "@cspell/dict-en-gb": "1.1.33", - "@cspell/dict-filetypes": "^3.0.9", - "@cspell/dict-flutter": "^1.0.3", - "@cspell/dict-fonts": "^4.0.3", - "@cspell/dict-fsharp": "^1.0.4", + "@cspell/dict-filetypes": "^3.0.10", + "@cspell/dict-flutter": "^1.1.0", + "@cspell/dict-fonts": "^4.0.4", + "@cspell/dict-fsharp": "^1.1.0", "@cspell/dict-fullstack": "^3.2.3", - "@cspell/dict-gaming-terms": "^1.0.9", - "@cspell/dict-git": "^3.0.3", - "@cspell/dict-golang": "^6.0.17", - "@cspell/dict-google": "^1.0.4", - "@cspell/dict-haskell": "^4.0.4", - "@cspell/dict-html": "^4.0.10", + "@cspell/dict-gaming-terms": "^1.1.0", + "@cspell/dict-git": "^3.0.4", + "@cspell/dict-golang": "^6.0.18", + "@cspell/dict-google": "^1.0.5", + "@cspell/dict-haskell": "^4.0.5", + "@cspell/dict-html": "^4.0.11", "@cspell/dict-html-symbol-entities": "^4.0.3", - "@cspell/dict-java": "^5.0.10", - "@cspell/dict-julia": "^1.0.4", - "@cspell/dict-k8s": "^1.0.9", + "@cspell/dict-java": "^5.0.11", + "@cspell/dict-julia": "^1.1.0", + "@cspell/dict-k8s": "^1.0.10", + "@cspell/dict-kotlin": "^1.1.0", "@cspell/dict-latex": "^4.0.3", - "@cspell/dict-lorem-ipsum": "^4.0.3", - "@cspell/dict-lua": "^4.0.6", - "@cspell/dict-makefile": "^1.0.3", - "@cspell/dict-markdown": "^2.0.7", - "@cspell/dict-monkeyc": "^1.0.9", - "@cspell/dict-node": "^5.0.5", - "@cspell/dict-npm": "^5.1.17", - "@cspell/dict-php": "^4.0.13", - "@cspell/dict-powershell": "^5.0.13", - "@cspell/dict-public-licenses": "^2.0.11", - "@cspell/dict-python": "^4.2.13", - "@cspell/dict-r": "^2.0.4", + "@cspell/dict-lorem-ipsum": "^4.0.4", + "@cspell/dict-lua": "^4.0.7", + "@cspell/dict-makefile": "^1.0.4", + "@cspell/dict-markdown": "^2.0.9", + "@cspell/dict-monkeyc": "^1.0.10", + "@cspell/dict-node": "^5.0.6", + "@cspell/dict-npm": "^5.1.22", + "@cspell/dict-php": "^4.0.14", + "@cspell/dict-powershell": "^5.0.14", + "@cspell/dict-public-licenses": "^2.0.12", + "@cspell/dict-python": "^4.2.14", + "@cspell/dict-r": "^2.1.0", "@cspell/dict-ruby": "^5.0.7", - "@cspell/dict-rust": "^4.0.10", - "@cspell/dict-scala": "^5.0.6", - "@cspell/dict-software-terms": "^4.1.19", - "@cspell/dict-sql": "^2.1.8", - "@cspell/dict-svelte": "^1.0.5", - "@cspell/dict-swift": "^2.0.4", - "@cspell/dict-terraform": "^1.0.6", - "@cspell/dict-typescript": "^3.1.11", - "@cspell/dict-vue": "^3.0.3" + "@cspell/dict-rust": "^4.0.11", + "@cspell/dict-scala": "^5.0.7", + "@cspell/dict-shell": "^1.1.0", + "@cspell/dict-software-terms": "^4.2.2", + "@cspell/dict-sql": "^2.2.0", + "@cspell/dict-svelte": "^1.0.6", + "@cspell/dict-swift": "^2.0.5", + "@cspell/dict-terraform": "^1.1.0", + "@cspell/dict-typescript": "^3.2.0", + "@cspell/dict-vue": "^3.0.4" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.1.tgz", - "integrity": "sha512-EV9Xkh42Xw3aORvDZfxusICX91DDbqQpYdGKBdPGuhgxWOUYYZKpLXsHCmDkhruMPo2m5gDh++/OqjLRPZofKQ==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.2.tgz", + "integrity": "sha512-9QFzuSApaK7SYB50iCTRIUDjFZf6DXTFj8+qTR2cky+/YmEcHDpJieJVCd3STONO4m2JyqIsV7faEuA6M0YcHg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.17.1" + "@cspell/cspell-types": "8.17.2" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.1.tgz", - "integrity": "sha512-uhC99Ox+OH3COSgShv4fpVHiotR70dNvAOSkzRvKVRzV6IGyFnxHjmyVVPEV0dsqzVLxltwYTqFhwI+UOwm45A==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.2.tgz", + "integrity": "sha512-LOTKK+hZSUc7vaN8SBEOcv+9dMYbo84awbsjjdI+HkKVBfTt3Lzlu6IJImw39L6pTDAJ1ZxOUdWO89jcxpyihg==", "dev": true, "license": "MIT", "engines": { @@ -685,9 +712,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.1.tgz", - "integrity": "sha512-XEK2ymTdQNgsV3ny60VkKzWskbICl4zNXh/DbxsoRXHqIRg43MXFpTNkEJ7j873EqdX7BU4opQQ+5D4stWWuhQ==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.2.tgz", + "integrity": "sha512-Z2ndlzVIiXOCBnQby9q+OXcxeddiuCi//pnhO9Jf6Ixgthn+Yg7bwzAnHu+CM1SJaQnZCntGyimdxfojm+WDdA==", "dev": true, "license": "MIT", "dependencies": { @@ -698,9 +725,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.1.tgz", - "integrity": "sha512-2sFWQtMEWZ4tdz7bw0bAx4NaV1t0ynGfjpuKWdQppsJFKNb+ZPZZ6Ah1dC13AdRRMZaG194kDRFwzNvRaCgWkQ==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.2.tgz", + "integrity": "sha512-Cp4kVxJRyyDRd5RVTASlu+ygWG+dgy6GyH7lzb6P8SOXt1mxzCBK6Q5Dc1XHAsvhRaLrnMziCO/5Pj9/0DKs6w==", "dev": true, "license": "MIT", "engines": { @@ -708,9 +735,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.1.tgz", - "integrity": "sha512-NJbov7Jp57fh8addoxesjb8atg/APQfssCH5Q9uZuHBN06wEJDgs7fhfE48bU+RBViC9gltblsYZzZZQKzHYKg==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.2.tgz", + "integrity": "sha512-4kMBhX92p0pchEzYTpyLCoe/bUJ29YYvMINTeHTd//hLQh0ZAyMGY1opDm1tqaXX0qpYmWG60KcvN4fCR0i6lw==", "dev": true, "license": "MIT", "engines": { @@ -718,121 +745,124 @@ } }, "node_modules/@cspell/dict-ada": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.5.tgz", - "integrity": "sha512-6/RtZ/a+lhFVmrx/B7bfP7rzC4yjEYe8o74EybXcvu4Oue6J4Ey2WSYj96iuodloj1LWrkNCQyX5h4Pmcj0Iag==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.1.0.tgz", + "integrity": "sha512-7SvmhmX170gyPd+uHXrfmqJBY5qLcCX8kTGURPVeGxmt8XNXT75uu9rnZO+jwrfuU2EimNoArdVy5GZRGljGNg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-al": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.0.3.tgz", - "integrity": "sha512-V1HClwlfU/qwSq2Kt+MkqRAsonNu3mxjSCDyGRecdLGIHmh7yeEeaxqRiO/VZ4KP+eVSiSIlbwrb5YNFfxYZbw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.1.0.tgz", + "integrity": "sha512-PtNI1KLmYkELYltbzuoztBxfi11jcE9HXBHCpID2lou/J4VMYKJPNqe4ZjVzSI9NYbMnMnyG3gkbhIdx66VSXg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-aws": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.7.tgz", - "integrity": "sha512-PoaPpa2NXtSkhGIMIKhsJUXB6UbtTt6Ao3x9JdU9kn7fRZkwD4RjHDGqulucIOz7KeEX/dNRafap6oK9xHe4RA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.9.tgz", + "integrity": "sha512-bDYdnnJGwSkIZ4gzrauu7qzOs/ZAY/FnU4k11LgdMI8BhwMfsbsy2EI1iS+sD/BI5ZnNT9kU5YR3WADeNOmhRg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-bash": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.8.tgz", - "integrity": "sha512-I2CM2pTNthQwW069lKcrVxchJGMVQBzru2ygsHCwgidXRnJL/NTjAPOFTxN58Jc1bf7THWghfEDyKX/oyfc0yg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.2.0.tgz", + "integrity": "sha512-HOyOS+4AbCArZHs/wMxX/apRkjxg6NDWdt0jF9i9XkvJQUltMwEhyA2TWYjQ0kssBsnof+9amax2lhiZnh3kCg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@cspell/dict-shell": "1.1.0" + } }, "node_modules/@cspell/dict-companies": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.11.tgz", - "integrity": "sha512-1gbPfN4fk6Cmg8DbCc+3nFxnHJNNGN1R5T/VzGEp8UpVBcW3OFET2xXFKcJiKSh+DyXB+M2tAx3so6WBEwOK1Q==", + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.12.tgz", + "integrity": "sha512-99FxBNdLOQc3nVQ663Xh7JqDLbIy/AdqOecQ5bk3HpmXpSkoDvTT7XCUU5nQZvmFBrrQlXFKlRRYjLfTEOUDdA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.2.tgz", - "integrity": "sha512-yw5eejWvY4bAnc6LUA44m4WsFwlmgPt2uMSnO7QViGMBDuoeopMma4z9XYvs4lSjTi8fIJs/A1YDfM9AVzb8eg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.3.tgz", + "integrity": "sha512-OFrVXdxCeGKnon36Pe3yFjBuY4kzzEwWFf3vDz+cJTodZDkjFkBifQeTtt5YfimgF8cfAJZXkBCsxjipAgmAiw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cryptocurrencies": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.3.tgz", - "integrity": "sha512-bl5q+Mk+T3xOZ12+FG37dB30GDxStza49Rmoax95n37MTLksk9wBo1ICOlPJ6PnDUSyeuv4SIVKgRKMKkJJglA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.4.tgz", + "integrity": "sha512-6iFu7Abu+4Mgqq08YhTKHfH59mpMpGTwdzDB2Y8bbgiwnGFCeoiSkVkgLn1Kel2++hYcZ8vsAW/MJS9oXxuMag==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-csharp": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.5.tgz", - "integrity": "sha512-c/sFnNgtRwRJxtC3JHKkyOm+U3/sUrltFeNwml9VsxKBHVmvlg4tk4ar58PdpW9/zTlGUkWi2i85//DN1EsUCA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.6.tgz", + "integrity": "sha512-w/+YsqOknjQXmIlWDRmkW+BHBPJZ/XDrfJhZRQnp0wzpPOGml7W0q1iae65P2AFRtTdPKYmvSz7AL5ZRkCnSIw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-css": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.16.tgz", - "integrity": "sha512-70qu7L9z/JR6QLyJPk38fNTKitlIHnfunx0wjpWQUQ8/jGADIhMCrz6hInBjqPNdtGpYm8d1dNFyF8taEkOgrQ==", + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.17.tgz", + "integrity": "sha512-2EisRLHk6X/PdicybwlajLGKF5aJf4xnX2uuG5lexuYKt05xV/J/OiBADmi8q9obhxf1nesrMQbqAt+6CsHo/w==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-dart": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.2.4.tgz", - "integrity": "sha512-of/cVuUIZZK/+iqefGln8G3bVpfyN6ZtH+LyLkHMoR5tEj+2vtilGNk9ngwyR8L4lEqbKuzSkOxgfVjsXf5PsQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.3.0.tgz", + "integrity": "sha512-1aY90lAicek8vYczGPDKr70pQSTQHwMFLbmWKTAI6iavmb1fisJBS1oTmMOKE4ximDf86MvVN6Ucwx3u/8HqLg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-data-science": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.5.tgz", - "integrity": "sha512-nNSILXmhSJox9/QoXICPQgm8q5PbiSQP4afpbkBqPi/u/b3K9MbNH5HvOOa6230gxcGdbZ9Argl2hY/U8siBlg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.6.tgz", + "integrity": "sha512-gOYKZOg358yhnnQfr1/f232REmjeIymXUHJdrLEMPirluv2rzMWvEBBazqRVQ++jMUNg9IduVI0v096ZWMDekA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-django": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.3.tgz", - "integrity": "sha512-yBspeL3roJlO0a1vKKNaWABURuHdHZ9b1L8d3AukX0AsBy9snSggc8xCavPmSzNfeMDXbH+1lgQiYBd3IW03fg==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.4.tgz", + "integrity": "sha512-fX38eUoPvytZ/2GA+g4bbdUtCMGNFSLbdJJPKX2vbewIQGfgSFJKY56vvcHJKAvw7FopjvgyS/98Ta9WN1gckg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-docker": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.11.tgz", - "integrity": "sha512-s0Yhb16/R+UT1y727ekbR/itWQF3Qz275DR1ahOa66wYtPjHUXmhM3B/LT3aPaX+hD6AWmK23v57SuyfYHUjsw==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.12.tgz", + "integrity": "sha512-6d25ZPBnYZaT9D9An/x6g/4mk542R8bR3ipnby3QFCxnfdd6xaWiTcwDPsCgwN2aQZIQ1jX/fil9KmBEqIK/qA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-dotnet": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.8.tgz", - "integrity": "sha512-MD8CmMgMEdJAIPl2Py3iqrx3B708MbCIXAuOeZ0Mzzb8YmLmiisY7QEYSZPg08D7xuwARycP0Ki+bb0GAkFSqg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.9.tgz", + "integrity": "sha512-JGD6RJW5sHtO5lfiJl11a5DpPN6eKSz5M1YBa1I76j4dDOIqgZB6rQexlDlK1DH9B06X4GdDQwdBfnpAB0r2uQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-elixir": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.6.tgz", - "integrity": "sha512-TfqSTxMHZ2jhiqnXlVKM0bUADtCvwKQv2XZL/DI0rx3doG8mEMS8SGPOmiyyGkHpR/pGOq18AFH3BEm4lViHIw==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.7.tgz", + "integrity": "sha512-MAUqlMw73mgtSdxvbAvyRlvc3bYnrDqXQrx5K9SwW8F7fRYf9V4vWYFULh+UWwwkqkhX9w03ZqFYRTdkFku6uA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.28", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.28.tgz", - "integrity": "sha512-BN1PME7cOl7DXRQJ92pEd1f0Xk5sqjcDfThDGkKcsgwbSOY7KnTc/czBW6Pr3WXIchIm6cT12KEfjNqx7U7Rrw==", + "version": "4.3.29", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.29.tgz", + "integrity": "sha512-7kHP0sJ271oS5RqakxvhWvHFoCUFCBDV6+cgIRIpKwW0aYVB4F2AwElGsdeE/XEmihhYUje7e/e6X3IEWHrcrQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.7.tgz", - "integrity": "sha512-qNFo3G4wyabcwnM+hDrMYKN9vNVg/k9QkhqSlSst6pULjdvPyPs1mqz1689xO/v9t8e6sR4IKc3CgUXDMTYOpA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.8.tgz", + "integrity": "sha512-l1u/pDjwrPyWwBd1hCkZhdsK8yLbLFPD2xWz+1tFFI7WaV9ckDZoF3woRc/0wFGRy53yrfSAVuwhoYOQnHe/fA==", "dev": true, "license": "CC BY-SA 4.0" }, @@ -844,30 +874,30 @@ "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.9.tgz", - "integrity": "sha512-U7ycC1cE32A5aEgwzp/iE0TVabonUFnVt+Ygbf6NsIWqEuFWZgZChC7gfztA4T1fpuj602nFdp7eOnTWKORsnQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.10.tgz", + "integrity": "sha512-JEN3627joBVtpa1yfkdN9vz1Z129PoKGHBKjXCEziJvf2Zt1LeULWYYYg/O6pzRR4yzRa5YbXDTuyrN7vX7DFg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-flutter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.0.3.tgz", - "integrity": "sha512-52C9aUEU22ptpgYh6gQyIdA4MP6NPwzbEqndfgPh3Sra191/kgs7CVqXiO1qbtZa9gnYHUoVApkoxRE7mrXHfg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.1.0.tgz", + "integrity": "sha512-3zDeS7zc2p8tr9YH9tfbOEYfopKY/srNsAa+kE3rfBTtQERAZeOhe5yxrnTPoufctXLyuUtcGMUTpxr3dO0iaA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-fonts": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.3.tgz", - "integrity": "sha512-sPd17kV5qgYXLteuHFPn5mbp/oCHKgitNfsZLFC3W2fWEgZlhg4hK+UGig3KzrYhhvQ8wBnmZrAQm0TFKCKzsA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.4.tgz", + "integrity": "sha512-cHFho4hjojBcHl6qxidl9CvUb492IuSk7xIf2G2wJzcHwGaCFa2o3gRcxmIg1j62guetAeDDFELizDaJlVRIOg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-fsharp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.0.4.tgz", - "integrity": "sha512-G5wk0o1qyHUNi9nVgdE1h5wl5ylq7pcBjX8vhjHcO4XBq20D5eMoXjwqMo/+szKAqzJ+WV3BgAL50akLKrT9Rw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.1.0.tgz", + "integrity": "sha512-oguWmHhGzgbgbEIBKtgKPrFSVAFtvGHaQS0oj+vacZqMObwkapcTGu7iwf4V3Bc2T3caf0QE6f6rQfIJFIAVsw==", "dev": true, "license": "MIT" }, @@ -879,16 +909,16 @@ "license": "MIT" }, "node_modules/@cspell/dict-gaming-terms": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.9.tgz", - "integrity": "sha512-AVIrZt3YiUnxsUzzGYTZ1XqgtkgwGEO0LWIlEf+SiDUEVLtv4CYmmyXFQ+WXDN0pyJ0wOwDazWrP0Cu7avYQmQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.1.0.tgz", + "integrity": "sha512-46AnDs9XkgJ2f1Sqol1WgfJ8gOqp60fojpc9Wxch7x+BA63g4JfMV5/M5x0sI0TLlLY8EBSglcr8wQF/7C80AQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-git": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.3.tgz", - "integrity": "sha512-LSxB+psZ0qoj83GkyjeEH/ZViyVsGEF/A6BAo8Nqc0w0HjD2qX/QR4sfA6JHUgQ3Yi/ccxdK7xNIo67L2ScW5A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.4.tgz", + "integrity": "sha512-C44M+m56rYn6QCsLbiKiedyPTMZxlDdEYAsPwwlL5bhMDDzXZ3Ic8OCQIhMbiunhCOJJT+er4URmOmM+sllnjg==", "dev": true, "license": "MIT" }, @@ -900,23 +930,23 @@ "license": "MIT" }, "node_modules/@cspell/dict-google": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.4.tgz", - "integrity": "sha512-JThUT9eiguCja1mHHLwYESgxkhk17Gv7P3b1S7ZJzXw86QyVHPrbpVoMpozHk0C9o+Ym764B7gZGKmw9uMGduQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.5.tgz", + "integrity": "sha512-KNrzfUsoFat94slWzo36g601sIGz6KtE4kBMM0gpqwFLK/MXRyaW65IL4SwysY0PEhuRzg9spLLMnUXuVcY2hQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-haskell": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.4.tgz", - "integrity": "sha512-EwQsedEEnND/vY6tqRfg9y7tsnZdxNqOxLXSXTsFA6JRhUlr8Qs88iUUAfsUzWc4nNmmzQH2UbtT25ooG9x4nA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.5.tgz", + "integrity": "sha512-s4BG/4tlj2pPM9Ha7IZYMhUujXDnI0Eq1+38UTTCpatYLbQqDwRFf2KNPLRqkroU+a44yTUAe0rkkKbwy4yRtQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-html": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.10.tgz", - "integrity": "sha512-I9uRAcdtHbh0wEtYZlgF0TTcgH0xaw1B54G2CW+tx4vHUwlde/+JBOfIzird4+WcMv4smZOfw+qHf7puFUbI5g==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.11.tgz", + "integrity": "sha512-QR3b/PB972SRQ2xICR1Nw/M44IJ6rjypwzA4jn+GH8ydjAX9acFNfc+hLZVyNe0FqsE90Gw3evLCOIF0vy1vQw==", "dev": true, "license": "MIT" }, @@ -928,23 +958,30 @@ "license": "MIT" }, "node_modules/@cspell/dict-java": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.10.tgz", - "integrity": "sha512-pVNcOnmoGiNL8GSVq4WbX/Vs2FGS0Nej+1aEeGuUY9CU14X8yAVCG+oih5ZoLt1jaR8YfR8byUF8wdp4qG4XIw==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.11.tgz", + "integrity": "sha512-T4t/1JqeH33Raa/QK/eQe26FE17eUCtWu+JsYcTLkQTci2dk1DfcIKo8YVHvZXBnuM43ATns9Xs0s+AlqDeH7w==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-julia": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.0.4.tgz", - "integrity": "sha512-bFVgNX35MD3kZRbXbJVzdnN7OuEqmQXGpdOi9jzB40TSgBTlJWA4nxeAKV4CPCZxNRUGnLH0p05T/AD7Aom9/w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.1.0.tgz", + "integrity": "sha512-CPUiesiXwy3HRoBR3joUseTZ9giFPCydSKu2rkh6I2nVjXnl5vFHzOMLXpbF4HQ1tH2CNfnDbUndxD+I+7eL9w==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-k8s": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.9.tgz", - "integrity": "sha512-Q7GELSQIzo+BERl2ya/nBEnZeQC+zJP19SN1pI6gqDYraM51uYJacbbcWLYYO2Y+5joDjNt/sd/lJtLaQwoSlA==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.10.tgz", + "integrity": "sha512-313haTrX9prep1yWO7N6Xw4D6tvUJ0Xsx+YhCP+5YrrcIKoEw5Rtlg8R4PPzLqe6zibw6aJ+Eqq+y76Vx5BZkw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-kotlin": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-kotlin/-/dict-kotlin-1.1.0.tgz", + "integrity": "sha512-vySaVw6atY7LdwvstQowSbdxjXG6jDhjkWVWSjg1XsUckyzH1JRHXe9VahZz1i7dpoFEUOWQrhIe5B9482UyJQ==", "dev": true, "license": "MIT" }, @@ -956,95 +993,95 @@ "license": "MIT" }, "node_modules/@cspell/dict-lorem-ipsum": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.3.tgz", - "integrity": "sha512-WFpDi/PDYHXft6p0eCXuYnn7mzMEQLVeqpO+wHSUd+kz5ADusZ4cpslAA4wUZJstF1/1kMCQCZM6HLZic9bT8A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.4.tgz", + "integrity": "sha512-+4f7vtY4dp2b9N5fn0za/UR0kwFq2zDtA62JCbWHbpjvO9wukkbl4rZg4YudHbBgkl73HRnXFgCiwNhdIA1JPw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-lua": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.6.tgz", - "integrity": "sha512-Jwvh1jmAd9b+SP9e1GkS2ACbqKKRo9E1f9GdjF/ijmooZuHU0hPyqvnhZzUAxO1egbnNjxS/J2T6iUtjAUK2KQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.7.tgz", + "integrity": "sha512-Wbr7YSQw+cLHhTYTKV6cAljgMgcY+EUAxVIZW3ljKswEe4OLxnVJ7lPqZF5JKjlXdgCjbPSimsHqyAbC5pQN/Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-makefile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.3.tgz", - "integrity": "sha512-R3U0DSpvTs6qdqfyBATnePj9Q/pypkje0Nj26mQJ8TOBQutCRAJbr2ZFAeDjgRx5EAJU/+8txiyVF97fbVRViw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.4.tgz", + "integrity": "sha512-E4hG/c0ekPqUBvlkrVvzSoAA+SsDA9bLi4xSV3AXHTVru7Y2bVVGMPtpfF+fI3zTkww/jwinprcU1LSohI3ylw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-markdown": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.7.tgz", - "integrity": "sha512-F9SGsSOokFn976DV4u/1eL4FtKQDSgJHSZ3+haPRU5ki6OEqojxKa8hhj4AUrtNFpmBaJx/WJ4YaEzWqG7hgqg==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.9.tgz", + "integrity": "sha512-j2e6Eg18BlTb1mMP1DkyRFMM/FLS7qiZjltpURzDckB57zDZbUyskOFdl4VX7jItZZEeY0fe22bSPOycgS1Z5A==", "dev": true, "license": "MIT", "peerDependencies": { - "@cspell/dict-css": "^4.0.16", - "@cspell/dict-html": "^4.0.10", + "@cspell/dict-css": "^4.0.17", + "@cspell/dict-html": "^4.0.11", "@cspell/dict-html-symbol-entities": "^4.0.3", - "@cspell/dict-typescript": "^3.1.11" + "@cspell/dict-typescript": "^3.2.0" } }, "node_modules/@cspell/dict-monkeyc": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.9.tgz", - "integrity": "sha512-Jvf6g5xlB4+za3ThvenYKREXTEgzx5gMUSzrAxIiPleVG4hmRb/GBSoSjtkGaibN3XxGx5x809gSTYCA/IHCpA==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.10.tgz", + "integrity": "sha512-7RTGyKsTIIVqzbvOtAu6Z/lwwxjGRtY5RkKPlXKHEoEAgIXwfDxb5EkVwzGQwQr8hF/D3HrdYbRT8MFBfsueZw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-node": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.5.tgz", - "integrity": "sha512-7NbCS2E8ZZRZwlLrh2sA0vAk9n1kcTUiRp/Nia8YvKaItGXLfxYqD2rMQ3HpB1kEutal6hQLVic3N2Yi1X7AaA==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.6.tgz", + "integrity": "sha512-CEbhPCpxGvRNByGolSBTrXXW2rJA4bGqZuTx1KKO85mwR6aadeOmUE7xf/8jiCkXSy+qvr9aJeh+jlfXcsrziQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.20", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.20.tgz", - "integrity": "sha512-vE9pFIifCDChsVhhUDuVtnwxygOdtHNluDm+8FkgC84M6LwiUVJr/CuSOI/SCR0oI9iiFp0VvMz194B6XwMv3g==", + "version": "5.1.22", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.22.tgz", + "integrity": "sha512-fZBTn8QHr8pAv1/I14CmdDWpVkovCfYpSYiGfV1SZkOjrsKLzPxsP84eaP3RijbFtYj3GMplVN27FR3H5oHfiw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-php": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.13.tgz", - "integrity": "sha512-P6sREMZkhElzz/HhXAjahnICYIqB/HSGp1EhZh+Y6IhvC15AzgtDP8B8VYCIsQof6rPF1SQrFwunxOv8H1e2eg==", + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.14.tgz", + "integrity": "sha512-7zur8pyncYZglxNmqsRycOZ6inpDoVd4yFfz1pQRe5xaRWMiK3Km4n0/X/1YMWhh3e3Sl/fQg5Axb2hlN68t1g==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-powershell": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.13.tgz", - "integrity": "sha512-0qdj0XZIPmb77nRTynKidRJKTU0Fl+10jyLbAhFTuBWKMypVY06EaYFnwhsgsws/7nNX8MTEQuewbl9bWFAbsg==", + "version": "5.0.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.14.tgz", + "integrity": "sha512-ktjjvtkIUIYmj/SoGBYbr3/+CsRGNXGpvVANrY0wlm/IoGlGywhoTUDYN0IsGwI2b8Vktx3DZmQkfb3Wo38jBA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-public-licenses": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.11.tgz", - "integrity": "sha512-rR5KjRUSnVKdfs5G+gJ4oIvQvm8+NJ6cHWY2N+GE69/FSGWDOPHxulCzeGnQU/c6WWZMSimG9o49i9r//lUQyA==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.12.tgz", + "integrity": "sha512-obreJMVbz8ZrXyc60PcS/B2FwXaO3AWPO2x50zrI/n4UDuBr/UdPb6M1q++6c08n+151I35GEx52xRFiToSg4g==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.13.tgz", - "integrity": "sha512-mZIcmo9qif8LkJ6N/lqTZawcOk2kVTcuWIUOSbMcjyomO0XZ7iWz15TfONyr03Ea/l7o5ULV+MZ4vx76bAUb7w==", + "version": "4.2.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.14.tgz", + "integrity": "sha512-NZ/rsTH5gqTlEwbSg0vn5b1TsyzrUvA6ykwCVCwsVDdlQAS82cyDsF9JqHp8S4d6PFykmkfSxtAXYyOUr0KCbg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-data-science": "^2.0.5" + "@cspell/dict-data-science": "^2.0.6" } }, "node_modules/@cspell/dict-r": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.4.tgz", - "integrity": "sha512-cBpRsE/U0d9BRhiNRMLMH1PpWgw+N+1A2jumgt1if9nBGmQw4MUpg2u9I0xlFVhstTIdzXiLXMxP45cABuiUeQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.1.0.tgz", + "integrity": "sha512-k2512wgGG0lTpTYH9w5Wwco+lAMf3Vz7mhqV8+OnalIE7muA0RSuD9tWBjiqLcX8zPvEJr4LdgxVju8Gk3OKyA==", "dev": true, "license": "MIT" }, @@ -1056,76 +1093,83 @@ "license": "MIT" }, "node_modules/@cspell/dict-rust": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.10.tgz", - "integrity": "sha512-6o5C8566VGTTctgcwfF3Iy7314W0oMlFFSQOadQ0OEdJ9Z9ERX/PDimrzP3LGuOrvhtEFoK8pj+BLnunNwRNrw==", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.11.tgz", + "integrity": "sha512-OGWDEEzm8HlkSmtD8fV3pEcO2XBpzG2XYjgMCJCRwb2gRKvR+XIm6Dlhs04N/K2kU+iH8bvrqNpM8fS/BFl0uw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-scala": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.6.tgz", - "integrity": "sha512-tl0YWAfjUVb4LyyE4JIMVE8DlLzb1ecHRmIWc4eT6nkyDqQgHKzdHsnusxFEFMVLIQomgSg0Zz6hJ5S1E4W4ww==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.7.tgz", + "integrity": "sha512-yatpSDW/GwulzO3t7hB5peoWwzo+Y3qTc0pO24Jf6f88jsEeKmDeKkfgPbYuCgbE4jisGR4vs4+jfQZDIYmXPA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-shell": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-shell/-/dict-shell-1.1.0.tgz", + "integrity": "sha512-D/xHXX7T37BJxNRf5JJHsvziFDvh23IF/KvkZXNSh8VqcRdod3BAz9VGHZf6VDqcZXr1VRqIYR3mQ8DSvs3AVQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.1.tgz", - "integrity": "sha512-8FiZHeeTqBdjsw4uBsZ9GIV9zEUbr49bBeEyVGFmUMZYwhAzC9riGqbTWco277X5Mabe8OjbYxqiP2/snC6w5w==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.2.tgz", + "integrity": "sha512-cgteXRzx2W/Ug7QSdFJrVxLES7krrZEjZ9J6sXRWOsVYFpgu2Gup8NKmjKOZ8NTnCjHQFrMnbmKdv56q9Kwixw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-sql": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.8.tgz", - "integrity": "sha512-dJRE4JV1qmXTbbGm6WIcg1knmR6K5RXnQxF4XHs5HA3LAjc/zf77F95i5LC+guOGppVF6Hdl66S2UyxT+SAF3A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.2.0.tgz", + "integrity": "sha512-MUop+d1AHSzXpBvQgQkCiok8Ejzb+nrzyG16E8TvKL2MQeDwnIvMe3bv90eukP6E1HWb+V/MA/4pnq0pcJWKqQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-svelte": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.5.tgz", - "integrity": "sha512-sseHlcXOqWE4Ner9sg8KsjxwSJ2yssoJNqFHR9liWVbDV+m7kBiUtn2EB690TihzVsEmDr/0Yxrbb5Bniz70mA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.6.tgz", + "integrity": "sha512-8LAJHSBdwHCoKCSy72PXXzz7ulGROD0rP1CQ0StOqXOOlTUeSFaJJlxNYjlONgd2c62XBQiN2wgLhtPN+1Zv7Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-swift": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.4.tgz", - "integrity": "sha512-CsFF0IFAbRtYNg0yZcdaYbADF5F3DsM8C4wHnZefQy8YcHP/qjAF/GdGfBFBLx+XSthYuBlo2b2XQVdz3cJZBw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.5.tgz", + "integrity": "sha512-3lGzDCwUmnrfckv3Q4eVSW3sK3cHqqHlPprFJZD4nAqt23ot7fic5ALR7J4joHpvDz36nHX34TgcbZNNZOC/JA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-terraform": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.0.7.tgz", - "integrity": "sha512-Ip7tOlAt/qUVdWYyDMA7DlKMpQ6sjtrsXk4vcpqXoYpoJlzMoDce7pw+fPhHshtNOFBAZ4nOrszlLu6APuy+HQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.1.0.tgz", + "integrity": "sha512-G55pcUUxeXAhejstmD35B47SkFd4uqCQimc+CMgq8Nx0dr03guL2iMsz8faRWQGkCnGimX8S91rbOhDv9p/heg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-typescript": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.11.tgz", - "integrity": "sha512-FwvK5sKbwrVpdw0e9+1lVTl8FPoHYvfHRuQRQz2Ql5XkC0gwPPkpoyD1zYImjIyZRoYXk3yp9j8ss4iz7A7zoQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.0.tgz", + "integrity": "sha512-Pk3zNePLT8qg51l0M4g1ISowYAEGxTuNfZlgkU5SvHa9Cu7x/BWoyYq9Fvc3kAyoisCjRPyvWF4uRYrPitPDFw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-vue": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.3.tgz", - "integrity": "sha512-akmYbrgAGumqk1xXALtDJcEcOMYBYMnkjpmGzH13Ozhq1mkPF4VgllFQlm1xYde+BUKNnzMgPEzxrL2qZllgYA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.4.tgz", + "integrity": "sha512-0dPtI0lwHcAgSiQFx8CzvqjdoXROcH+1LyqgROCpBgppommWpVhbQ0eubnKotFEXgpUCONVkeZJ6Ql8NbTEu+w==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.1.tgz", - "integrity": "sha512-XQtr2olYOtqbg49E+8SISd6I5DzfxmsKINDn0ZgaTFeLalnNdF3ewDU4gOEbApIzGffRa1mW9t19MsiVrznSDw==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.2.tgz", + "integrity": "sha512-n3AVbyBlTn/pLtYK62mqgDfJIuQHUTY/k8SMUCjyjfgoqd3LcKhS1PmbLfDWPMTODK30cSMMTLejjy2bL6ksEw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.1", + "@cspell/url": "8.17.2", "import-meta-resolve": "^4.1.0" }, "engines": { @@ -1133,9 +1177,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.1.tgz", - "integrity": "sha512-AxYw6j7EPYtDFAFjwybjFpMc9waXQzurfBXmEVfQ5RQRlbylujLZWwR6GnMqofeNg4oGDUpEjcAZFrgdkvMQlA==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.2.tgz", + "integrity": "sha512-2B+dB4Ls2xiOjg+vEEbAuJTHtMfXSihVzfLGnj9+qUfq47iqrz4ZBvCOfZhYdiVaaZJoZUgIw8ljrUfqFzYDAg==", "dev": true, "license": "MIT", "engines": { @@ -1143,9 +1187,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.1.tgz", - "integrity": "sha512-8cY3vLAKdt5gQEMM3Gr57BuQ8sun2NjYNh9qTdrctC1S9gNC7XzFghTYAfHSWR4VrOUcMFLO/izMdsc1KFvFOA==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.2.tgz", + "integrity": "sha512-LbbhdVwtqyJ71X+O7e2PqpDp7zLiY8jmW2CJFLjZYWTUawgav2bpwECGq6O9Gnwqe+fj7yWxGJFDSpXQcCJQAw==", "dev": true, "license": "MIT", "engines": { @@ -1153,15 +1197,87 @@ } }, "node_modules/@cspell/url": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.1.tgz", - "integrity": "sha512-LMvReIndW1ckvemElfDgTt282fb2C3C/ZXfsm0pJsTV5ZmtdelCHwzmgSBmY5fDr7D66XDp8EurotSE0K6BTvw==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.2.tgz", + "integrity": "sha512-yy4eYWNX2iutXmy4Igbn/hL/NYaNt94DylohPtgVr0Zxnn/AAArt9Bv1KXPpjB8VFy2wzzPzWmZ+MWDUVpHCbg==", "dev": true, "license": "MIT", "engines": { "node": ">=18.0" } }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz", + "integrity": "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.1.tgz", + "integrity": "sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz", + "integrity": "sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.1", + "@csstools/css-calc": "^2.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, "node_modules/@csstools/css-parser-algorithms": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", @@ -1396,9 +1512,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", - "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -1475,9 +1591,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", - "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", + "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1493,11 +1609,12 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", - "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "license": "Apache-2.0", "dependencies": { + "@eslint/core": "^0.10.0", "levn": "^0.4.1" }, "engines": { @@ -2024,6 +2141,16 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@keyv/serialize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz", + "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2457,9 +2584,9 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.12.1.tgz", - "integrity": "sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.13.0.tgz", + "integrity": "sha512-RnO1SaiCFHn666wNz2QfZEFxvmiNRqhzaMXHXxXXKt+MEP7aajlPxUSMIQpKAaJfverpovEYqjBOXDq6dDcaOQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2573,6 +2700,7 @@ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/ms": "*" } @@ -2644,7 +2772,8 @@ "version": "0.16.7", "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/keyv": { "version": "3.1.4", @@ -2660,12 +2789,13 @@ "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "20.17.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz", - "integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==", + "version": "20.17.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.12.tgz", + "integrity": "sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -2692,7 +2822,8 @@ "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/yargs": { "version": "17.0.33", @@ -2722,14 +2853,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz", - "integrity": "sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", + "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2" + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2740,9 +2871,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.2.tgz", - "integrity": "sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", + "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", "dev": true, "license": "MIT", "engines": { @@ -2754,20 +2885,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz", - "integrity": "sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz", + "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/visitor-keys": "8.20.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2781,16 +2912,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.2.tgz", - "integrity": "sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz", + "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.18.2", - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/typescript-estree": "8.18.2" + "@typescript-eslint/scope-manager": "8.20.0", + "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/typescript-estree": "8.20.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2805,13 +2936,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz", - "integrity": "sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz", + "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", + "@typescript-eslint/types": "8.20.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2947,9 +3078,9 @@ } }, "node_modules/ansis": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.5.2.tgz", - "integrity": "sha512-5uGcUZRbORJeEppVdWfZOSybTMz+Ou+84HepgK081Yk5+pPMMzWf/XGxiAT6bfBqCghRB4MwBtYn0CHqINRVag==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.9.0.tgz", + "integrity": "sha512-PcDrVe15ldexeZMsVLBAzBwF2KhZgaU0R+CHxH+x5kqn/pO+UWVBZJ+NEXMPpEOLUFeNsnNdoWYc2gwO+MVkDg==", "license": "ISC", "engines": { "node": ">=16" @@ -3334,6 +3465,27 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", @@ -3490,9 +3642,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", - "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -3532,6 +3684,31 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -3557,6 +3734,17 @@ "node": ">= 0.8" } }, + "node_modules/cacheable": { + "version": "1.8.7", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.7.tgz", + "integrity": "sha512-AbfG7dAuYNjYxFUtL1lAqmlWdxczCJ47w7cFjhGcnGnUdwSo6VgmSojfoW3tUI12HUkgTJ5kqj78yyq6TsFtlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^1.6.0", + "keyv": "^5.2.3" + } + }, "node_modules/cacheable-lookup": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", @@ -3586,6 +3774,16 @@ "node": ">=8" } }, + "node_modules/cacheable/node_modules/keyv": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.2.3.tgz", + "integrity": "sha512-AGKecUfzrowabUv0bH1RIR5Vf7w+l4S3xtQAypKaUpTdIR1EbrAcTxHCrpo9Q+IWeUlFE2palRtgIQcgm+PQJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.0.2" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -3653,9 +3851,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001690", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", - "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", + "version": "1.0.30001692", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", + "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", "dev": true, "funding": [ { @@ -3733,6 +3931,7 @@ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -3743,6 +3942,7 @@ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -3753,6 +3953,7 @@ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -4049,9 +4250,9 @@ } }, "node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.0.0.tgz", + "integrity": "sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ==", "dev": true, "license": "MIT", "engines": { @@ -4247,25 +4448,25 @@ } }, "node_modules/cspell": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.1.tgz", - "integrity": "sha512-D0lw8XTXrTycNzOn5DkfPJNUT00X53OgvFDm+0SzhBr1r+na8LEh3CnQ6zKYVU0fL0x8vU82vs4jmGjDho9mPg==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.2.tgz", + "integrity": "sha512-y+INkxDa+M9f+gsyyMLjKh1tF20r2g5Gn22peSRJglrNLQtmDuRtDT9vyDHANXZcH5g6pHDnENQu/+P2Tiyu8Q==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.17.1", - "@cspell/cspell-pipe": "8.17.1", - "@cspell/cspell-types": "8.17.1", - "@cspell/dynamic-import": "8.17.1", - "@cspell/url": "8.17.1", - "chalk": "^5.3.0", + "@cspell/cspell-json-reporter": "8.17.2", + "@cspell/cspell-pipe": "8.17.2", + "@cspell/cspell-types": "8.17.2", + "@cspell/dynamic-import": "8.17.2", + "@cspell/url": "8.17.2", + "chalk": "^5.4.1", "chalk-template": "^1.1.0", - "commander": "^12.1.0", - "cspell-dictionary": "8.17.1", - "cspell-gitignore": "8.17.1", - "cspell-glob": "8.17.1", - "cspell-io": "8.17.1", - "cspell-lib": "8.17.1", + "commander": "^13.0.0", + "cspell-dictionary": "8.17.2", + "cspell-gitignore": "8.17.2", + "cspell-glob": "8.17.2", + "cspell-io": "8.17.2", + "cspell-lib": "8.17.2", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", @@ -4284,46 +4485,46 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.1.tgz", - "integrity": "sha512-x1S7QWprgUcwuwiJB1Ng0ZTBC4G50qP9qQyg/aroMkcdMsHfk26E8jUGRPNt4ftHFzS4YMhwtXuJQ9IgRUuNPA==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.2.tgz", + "integrity": "sha512-g08lRd/smLk2je0j7HlCjdDa0dSTyI2oRP3gScWlsyXjb4NSr9qO0Wzyn5BfPgrqFdS/z4dXbHe+tnLQZCt9iQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.17.1", + "@cspell/cspell-types": "8.17.2", "comment-json": "^4.2.5", - "yaml": "^2.6.1" + "yaml": "^2.7.0" }, "engines": { "node": ">=18" } }, "node_modules/cspell-dictionary": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.1.tgz", - "integrity": "sha512-zSl9l3wii+x16yc2NVZl/+CMLeLBAiuEd5YoFkOYPcbTJnfPwdjMNcj71u7wBvNJ+qwbF+kGbutEt15yHW3NBw==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.2.tgz", + "integrity": "sha512-2JC9RRsZruCs3AHId/8X63fSxDoF94dleRp8y/dXS9LIX7NruofohUJwzc/3tlgzCWWdaek1RXhO5xaYX74QtA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.1", - "@cspell/cspell-types": "8.17.1", - "cspell-trie-lib": "8.17.1", - "fast-equals": "^5.0.1" + "@cspell/cspell-pipe": "8.17.2", + "@cspell/cspell-types": "8.17.2", + "cspell-trie-lib": "8.17.2", + "fast-equals": "^5.2.2" }, "engines": { "node": ">=18" } }, "node_modules/cspell-gitignore": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.1.tgz", - "integrity": "sha512-bk727Zf4FBCjm9Mwvyreyhgjwe+YhPQEW7PldkHiinKd+Irfez4s8GXLQb1EgV0UpvViqaqBqLmngjZdS30BTA==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.2.tgz", + "integrity": "sha512-zCTTN30zV96LkZmUDrLamEHpLLUGohKglKJ4iXoHQC8pDU3xTsV2qzeCQjM9SEmU3VbE1TzWq+vj0fslasv6pA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.1", - "cspell-glob": "8.17.1", - "cspell-io": "8.17.1", + "@cspell/url": "8.17.2", + "cspell-glob": "8.17.2", + "cspell-io": "8.17.2", "find-up-simple": "^1.0.0" }, "bin": { @@ -4334,13 +4535,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.1.tgz", - "integrity": "sha512-cUwM5auSt0RvLX7UkP2GEArJRWc85l51B1voArl+3ZIKeMZwcJpJgN3qvImtF8yRTZwYeYCs1sgsihb179q+mg==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.2.tgz", + "integrity": "sha512-MTgrWX12oY8Pq/M3PEYCTHwD6w6l+DPtBWm958nhR4dboUbwi/3KfqCtdorkhnuClqLDQuuZHp0uGBXB4cdQrw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.1", + "@cspell/url": "8.17.2", "micromatch": "^4.0.8" }, "engines": { @@ -4348,14 +4549,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.1.tgz", - "integrity": "sha512-H5tLcBuW7aUj9L0rR+FSbnWPEsWb8lWppHVidtqw9Ll1CUHWOZC9HTB2RdrhJZrsz/8DJbM2yNbok0Xt0VAfdw==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.2.tgz", + "integrity": "sha512-Asg5XRvrg2yHCvBwzARBPSwI4P5/unN+bKBlxqFazHgR72WJE+ASeobfUNfGi/RxJA2+m0hO91oYtvq6LfK52w==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.1", - "@cspell/cspell-types": "8.17.1" + "@cspell/cspell-pipe": "8.17.2", + "@cspell/cspell-types": "8.17.2" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4365,44 +4566,44 @@ } }, "node_modules/cspell-io": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.1.tgz", - "integrity": "sha512-liIOsblt7oVItifzRAbuxiYrwlgw1VOqKppMxVKtYoAn2VUuuEpjCj6jLWpoTqSszR/38o7ChsHY1LHakhJZmw==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.2.tgz", + "integrity": "sha512-IUdhbO6gsWYiM2dgudFJQTfnFCDYjLOqal3SxH5o8oOWeu5iIZ+s3N8E1odz0L5zF2Go7zDQSKvPr7Y9OOoRfw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.17.1", - "@cspell/url": "8.17.1" + "@cspell/cspell-service-bus": "8.17.2", + "@cspell/url": "8.17.2" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.1.tgz", - "integrity": "sha512-66n83Q7bK5tnvkDH7869/pBY/65AKmZVfCOAlsbhJn3YMDbNHFCHR0d1oNMlqG+n65Aco89VGwYfXxImZY+/mA==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.2.tgz", + "integrity": "sha512-ZgkTvGh9FO+R3v5TaTqlrJEylWyZhNOzbtrQ5W35Hb3tZ9IJJklxjlcGe+gbFsjGi56kLj6c5L2NR7YX/Fdu5Q==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.17.1", - "@cspell/cspell-pipe": "8.17.1", - "@cspell/cspell-resolver": "8.17.1", - "@cspell/cspell-types": "8.17.1", - "@cspell/dynamic-import": "8.17.1", - "@cspell/filetypes": "8.17.1", - "@cspell/strong-weak-map": "8.17.1", - "@cspell/url": "8.17.1", + "@cspell/cspell-bundled-dicts": "8.17.2", + "@cspell/cspell-pipe": "8.17.2", + "@cspell/cspell-resolver": "8.17.2", + "@cspell/cspell-types": "8.17.2", + "@cspell/dynamic-import": "8.17.2", + "@cspell/filetypes": "8.17.2", + "@cspell/strong-weak-map": "8.17.2", + "@cspell/url": "8.17.2", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.17.1", - "cspell-dictionary": "8.17.1", - "cspell-glob": "8.17.1", - "cspell-grammar": "8.17.1", - "cspell-io": "8.17.1", - "cspell-trie-lib": "8.17.1", + "cspell-config-lib": "8.17.2", + "cspell-dictionary": "8.17.2", + "cspell-glob": "8.17.2", + "cspell-grammar": "8.17.2", + "cspell-io": "8.17.2", + "cspell-trie-lib": "8.17.2", "env-paths": "^3.0.0", - "fast-equals": "^5.0.1", + "fast-equals": "^5.2.2", "gensequence": "^7.0.0", "import-fresh": "^3.3.0", "resolve-from": "^5.0.0", @@ -4415,14 +4616,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.1.tgz", - "integrity": "sha512-13WNa5s75VwOjlGzWprmfNbBFIfXyA7tYYrbV+LugKkznyNZJeJPojHouEudcLq3SYb2Q6tJ7qyWcuT5bR9qPA==", + "version": "8.17.2", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.2.tgz", + "integrity": "sha512-Bw9q8EWFihkQGo8fNdfkUqYOTsC161+wrQxR7m74K4bKEmQgm0mS0sLHKUwxEOZVGGLmIw9dMQl+8WnTgqOaMQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.1", - "@cspell/cspell-types": "8.17.1", + "@cspell/cspell-pipe": "8.17.2", + "@cspell/cspell-types": "8.17.2", "gensequence": "^7.0.0" }, "engines": { @@ -4480,13 +4681,14 @@ } }, "node_modules/cssstyle": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", - "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz", + "integrity": "sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==", "dev": true, "license": "MIT", "dependencies": { - "rrweb-cssom": "^0.7.1" + "@asamuzakjp/css-color": "^2.8.2", + "rrweb-cssom": "^0.8.0" }, "engines": { "node": ">=18" @@ -4616,6 +4818,7 @@ "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", "dev": true, + "license": "MIT", "dependencies": { "character-entities": "^2.0.0" }, @@ -4764,6 +4967,7 @@ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4810,6 +5014,7 @@ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "dev": true, + "license": "MIT", "dependencies": { "dequal": "^2.0.0" }, @@ -4915,9 +5120,9 @@ } }, "node_modules/domutils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", - "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", @@ -4949,9 +5154,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "32.2.7", - "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.7.tgz", - "integrity": "sha512-y8jbQRG3xogF70XPlk5c+dWe5iRfUBo28o2NMpKd/CcW7ENIaWtBlGima8/8nmRdAaYTy1+yIt6KB0Lon9H8cA==", + "version": "32.2.8", + "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.8.tgz", + "integrity": "sha512-jaAgBeFKjH6Cd7CnG7XhApZtLz2ewUXLyf1rKh9D+eaFD5XCYQpH77PhmrT5u0IpSP6eSZoHpAQ0sMqOFsh6kA==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4968,9 +5173,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.76", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", - "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", + "version": "1.5.80", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.80.tgz", + "integrity": "sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==", "dev": true, "license": "ISC" }, @@ -5193,9 +5398,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.7.tgz", - "integrity": "sha512-OygGC8kIcDhXX+6yAZRGLqwi2CmEXCbLQixeGUgYeR+Qwlppqmo7DIDr8XibtEBZp+fJcoYpoatp5qwLMEdcqQ==", + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.2", @@ -5209,10 +5414,11 @@ "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", + "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.6", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -5233,9 +5439,12 @@ "object-inspect": "^1.13.3", "object-keys": "^1.1.1", "object.assign": "^4.1.7", + "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -5291,14 +5500,15 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -5388,18 +5598,18 @@ } }, "node_modules/eslint": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", - "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", + "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", + "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.17.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/js": "9.18.0", + "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", @@ -5631,6 +5841,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.19.0.tgz", "integrity": "sha512-L1RCeuEcZHrOC2KJqRctgHrndLufICo4VSHNZEnGEF7PkZXWZrxUBc17I5Cdolarlk+5kIW9IJ+zettXUuELHg==", "dev": true, + "license": "MIT", "dependencies": { "@altano/repository-tools": "^0.1.1", "detect-indent": "6.1.0", @@ -6033,9 +6244,9 @@ "license": "Apache-2.0" }, "node_modules/fast-equals": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", - "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", + "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", "dev": true, "license": "MIT", "engines": { @@ -6043,9 +6254,9 @@ } }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { @@ -6053,7 +6264,7 @@ "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -6091,9 +6302,19 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { @@ -6456,21 +6677,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", + "get-proto": "^1.0.0", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -6489,6 +6710,19 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stdin": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", @@ -6952,6 +7186,13 @@ "node": ">=18.0.0" } }, + "node_modules/hookified": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.6.0.tgz", + "integrity": "sha512-se7cpwTA+iA/eY548Bu03JJqBiEZAqU2jnyKdj5B5qurtBg64CZGHTgqCv4Yh7NWu6FGI09W61MCq+NoPj9GXA==", + "dev": true, + "license": "MIT" + }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -7121,6 +7362,27 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -7297,6 +7559,7 @@ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -7307,6 +7570,7 @@ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", "dev": true, + "license": "MIT", "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" @@ -7341,12 +7605,15 @@ "license": "MIT" }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz", + "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==", "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7463,6 +7730,7 @@ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -7516,12 +7784,15 @@ } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7547,6 +7818,7 @@ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -8495,23 +8767,23 @@ } }, "node_modules/jsdom": { - "version": "25.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", - "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.0.0.tgz", + "integrity": "sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw==", "dev": true, "license": "MIT", "dependencies": { - "cssstyle": "^4.1.0", + "cssstyle": "^4.2.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", - "form-data": "^4.0.0", + "form-data": "^4.0.1", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", + "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.12", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^5.0.0", @@ -8519,7 +8791,7 @@ "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0", + "whatwg-url": "^14.1.0", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, @@ -8527,7 +8799,7 @@ "node": ">=18" }, "peerDependencies": { - "canvas": "^2.11.2" + "canvas": "^3.0.0" }, "peerDependenciesMeta": { "canvas": { @@ -8671,14 +8943,15 @@ "license": "MIT" }, "node_modules/katex": { - "version": "0.16.19", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.19.tgz", - "integrity": "sha512-3IA6DYVhxhBabjSLTNO9S4+OliA3Qvb8pBQXMfC4WxXJgLwZgnfDl0BmB4z6nBMdznBsZ+CGM8DrGZ5hcguDZg==", + "version": "0.16.20", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.20.tgz", + "integrity": "sha512-jjuLaMGD/7P8jUTpdKhA9IoqnH+yMFB3sdAFtq5QdAqeP2PjiSbnC3EaguKPNtv6dXXanHxp1ckwvF4a86LBig==", "dev": true, "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" ], + "license": "MIT", "dependencies": { "commander": "^8.3.0" }, @@ -8691,6 +8964,7 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12" } @@ -8797,6 +9071,7 @@ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, + "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" } @@ -8842,6 +9117,16 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/lint-staged/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/lint-staged/node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -8986,6 +9271,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/listr2": { "version": "8.2.5", "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", @@ -9207,6 +9505,7 @@ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -9224,6 +9523,7 @@ "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.37.3.tgz", "integrity": "sha512-eoQqH0291YCCjd+Pe1PUQ9AmWthlVmS0XWgcionkZ8q34ceZyRI+pYvsWksXJJL8OBkWCPwp1h/pnXxrPFC4oA==", "dev": true, + "license": "MIT", "dependencies": { "markdown-it": "14.1.0", "micromark": "4.0.1", @@ -9247,6 +9547,7 @@ "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.17.1.tgz", "integrity": "sha512-n1Im9lhKJJE12/u2N0GWBwPqeb0HGdylN8XpSFg9hbj35+QalY9Vi6mxwUQdG6wlSrrIq9ZDQ0Q85AQG9V2WOg==", "dev": true, + "license": "MIT", "dependencies": { "globby": "14.0.2", "js-yaml": "4.1.0", @@ -9322,7 +9623,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/media-typer": { "version": "0.3.0", @@ -9396,6 +9698,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", @@ -9431,6 +9734,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", @@ -9455,6 +9759,7 @@ "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", "dev": true, + "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", @@ -9474,6 +9779,7 @@ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", "dev": true, + "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", @@ -9490,6 +9796,7 @@ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", "dev": true, + "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", @@ -9510,6 +9817,7 @@ "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", "dev": true, + "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", @@ -9527,6 +9835,7 @@ "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", "dev": true, + "license": "MIT", "dependencies": { "@types/katex": "^0.16.0", "devlop": "^1.0.0", @@ -9556,6 +9865,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", @@ -9577,6 +9887,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", @@ -9599,6 +9910,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" @@ -9619,6 +9931,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", @@ -9641,6 +9954,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", @@ -9663,6 +9977,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" @@ -9683,6 +9998,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0" } @@ -9702,6 +10018,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", @@ -9723,6 +10040,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" @@ -9743,6 +10061,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0" } @@ -9761,7 +10080,8 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ] + ], + "license": "MIT" }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", @@ -9777,7 +10097,8 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ] + ], + "license": "MIT" }, "node_modules/micromark-util-normalize-identifier": { "version": "2.0.1", @@ -9794,6 +10115,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0" } @@ -9813,6 +10135,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-types": "^2.0.0" } @@ -9832,6 +10155,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", @@ -9853,6 +10177,7 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT", "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", @@ -9874,7 +10199,8 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ] + ], + "license": "MIT" }, "node_modules/micromark-util-types": { "version": "2.0.1", @@ -9890,7 +10216,8 @@ "type": "OpenCollective", "url": "https://opencollective.com/unified" } - ] + ], + "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", @@ -10433,6 +10760,23 @@ "node": ">= 0.8.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -10516,9 +10860,9 @@ } }, "node_modules/package-json-validator": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.7.1.tgz", - "integrity": "sha512-4LMljZxpshPCaeK4RxAgTe7bn6sGZl+K2+ehSRju/OdDkTrcBiggEtuLaistTRjqVZ4a/LB+ClbPUSZP7d3xew==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.7.3.tgz", + "integrity": "sha512-QWUV5rMxLe/QNMJ1t+/xYC8xY15lcAfcsKE/JAqTUt0KKhvO0idz4ZQdXvhLzz2Rf3KcEtaI5ZxsvgOrKIYRuA==", "dev": true, "license": "MIT", "dependencies": { @@ -10555,6 +10899,7 @@ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", "dev": true, + "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", @@ -11041,9 +11386,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.0.tgz", + "integrity": "sha512-27VKOqrYfPncKA2NrFOVhP5MGAfHKLYn/Q0mz9cNQyRAKYi3VNHwYU2qKKqPCqgBmeeJ0uAFB56NumXZ5ZReXg==", "dev": true, "funding": [ { @@ -11061,7 +11406,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -11295,6 +11640,7 @@ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -11458,18 +11804,18 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", - "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "dunder-proto": "^1.0.1", - "es-abstract": "^1.23.6", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" }, "engines": { @@ -11480,14 +11826,16 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -11720,9 +12068,9 @@ "license": "0BSD" }, "node_modules/rrweb-cssom": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", "dev": true, "license": "MIT" }, @@ -11809,6 +12157,22 @@ ], "license": "MIT" }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -12006,6 +12370,20 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -12369,9 +12747,9 @@ "license": "MIT" }, "node_modules/sort-package-json": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.12.0.tgz", - "integrity": "sha512-/HrPQAeeLaa+vbAH/znjuhwUluuiM/zL5XX9kop8UpDgjtyWKt43hGDk2vd/TBdDpzIyzIHVUgmYofzYrAQjew==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.13.0.tgz", + "integrity": "sha512-y1iCgJ+ZrOSgkzuhtpaxxsCLeUPZbEbIxcMDBde6JwpkZ3e9vVQhZ46iCD97GYImdgBLtXSPxxS9LqZbL6Th2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -12704,9 +13082,9 @@ } }, "node_modules/stylelint": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.12.0.tgz", - "integrity": "sha512-F8zZ3L/rBpuoBZRvI4JVT20ZanPLXfQLzMOZg1tzPflRVh9mKpOZ8qcSIhh1my3FjAjZWG4T2POwGnmn6a6hbg==", + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.13.1.tgz", + "integrity": "sha512-691JjSIIcP6f9QJFz0J0/AMG3lupE9RqYAgYCON3wiqp5nQiKqDYIsz321GeTOYNznoRPNh0Mf6VjzP1eBVz/Q==", "dev": true, "funding": [ { @@ -12729,16 +13107,16 @@ "colord": "^2.9.3", "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.3", - "css-tree": "^3.0.1", + "css-tree": "^3.1.0", "debug": "^4.3.7", - "fast-glob": "^3.3.2", + "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^9.1.0", + "file-entry-cache": "^10.0.5", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", - "ignore": "^6.0.2", + "ignore": "^7.0.1", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", "known-css-properties": "^0.35.0", @@ -12767,9 +13145,9 @@ } }, "node_modules/stylelint-config-recommended": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", - "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-15.0.0.tgz", + "integrity": "sha512-9LejMFsat7L+NXttdHdTq94byn25TD+82bzGRiV1Pgasl99pWnwipXS5DguTpp3nP1XjvLXVnEJIuYBfsRjRkA==", "dev": true, "funding": [ { @@ -12786,13 +13164,13 @@ "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.1.0" + "stylelint": "^16.13.0" } }, "node_modules/stylelint-config-standard": { - "version": "36.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz", - "integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==", + "version": "37.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-37.0.0.tgz", + "integrity": "sha512-+6eBlbSTrOn/il2RlV0zYGQwRTkr+WtzuVSs1reaWGObxnxLpbcspCUYajVQHonVfxVw2U+h42azGhrBvcg8OA==", "dev": true, "funding": [ { @@ -12806,13 +13184,13 @@ ], "license": "MIT", "dependencies": { - "stylelint-config-recommended": "^14.0.1" + "stylelint-config-recommended": "^15.0.0" }, "engines": { "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.1.0" + "stylelint": "^16.13.0" } }, "node_modules/stylelint-prettier": { @@ -12846,6 +13224,28 @@ "dev": true, "license": "MIT" }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.5.tgz", + "integrity": "sha512-umpQsJrBNsdMDgreSryMEXvJh66XeLtZUwA8Gj7rHGearGufUFv6rB/bcXRFsiGWw/VeSUgUofF4Rf2UKEOrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^6.1.5" + } + }, + "node_modules/stylelint/node_modules/flat-cache": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.5.tgz", + "integrity": "sha512-QR+2kN38f8nMfiIQ1LHYjuDEmZNZVjxuxY+HufbS3BW0EX01Q5OnH7iduOYRutmgiXb797HAKcXUeXrvRjjgSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cacheable": "^1.8.7", + "flatted": "^3.3.2", + "hookified": "^1.6.0" + } + }, "node_modules/stylelint/node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -12878,9 +13278,9 @@ } }, "node_modules/stylelint/node_modules/ignore": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", - "integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.1.tgz", + "integrity": "sha512-D1gVletsbVOoiXF963rgZnfobGAbq7Lb+dz3fcBmlOmZg6hHkpbycLqL8PLNB8f4GVv6dOVYwhPL/r7hwiH0Fw==", "dev": true, "license": "MIT", "engines": { @@ -13036,9 +13436,10 @@ "license": "0BSD" }, "node_modules/systeminformation": { - "version": "5.24.3", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.24.3.tgz", - "integrity": "sha512-f7uvLgsQIj9/gNcbNZWgw27sNJO5tQvi2tCo4/eVlynxS5slaa7EAN2vSD5jh0YljyjE8qQZ3qtAr7EkDCRyMw==", + "version": "5.25.11", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.25.11.tgz", + "integrity": "sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==", + "license": "MIT", "os": [ "darwin", "linux", @@ -13181,22 +13582,22 @@ } }, "node_modules/tldts": { - "version": "6.1.70", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.70.tgz", - "integrity": "sha512-/W1YVgYVJd9ZDjey5NXadNh0mJXkiUMUue9Zebd0vpdo1sU+H4zFFTaJ1RKD4N6KFoHfcXy6l+Vu7bh+bdWCzA==", + "version": "6.1.71", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.71.tgz", + "integrity": "sha512-LQIHmHnuzfZgZWAf2HzL83TIIrD8NhhI0DVxqo9/FdOd4ilec+NTNZOlDZf7EwrTNoutccbsHjvWHYXLAtvxjw==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.70" + "tldts-core": "^6.1.71" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.70", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.70.tgz", - "integrity": "sha512-RNnIXDB1FD4T9cpQRErEqw6ZpjLlGdMOitdV+0xtbsnwr4YFka1zpc7D4KD+aAn8oSG5JyFrdasZTE04qDE9Yg==", + "version": "6.1.71", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.71.tgz", + "integrity": "sha512-LRbChn2YRpic1KxY+ldL1pGXN/oVvKfCVufwfVzEQdFYNo39uF7AJa/WXdo+gYO7PTvdfkCPCed6Hkvz/kR7jg==", "dev": true, "license": "MIT" }, @@ -13229,9 +13630,9 @@ } }, "node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.0.tgz", + "integrity": "sha512-rvZUv+7MoBYTiDmFPBrhL7Ujx9Sk+q9wwm22x8c8T5IJaR+Wsyc7TNxbVxo84kZoRJZZMazowFLqpankBEQrGg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13255,16 +13656,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/tsconfig-paths": { @@ -13460,9 +13861,9 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -13478,7 +13879,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/uglify-js": { "version": "3.19.3", @@ -13512,9 +13914,9 @@ } }, "node_modules/undici": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.2.0.tgz", - "integrity": "sha512-klt+0S55GBViA9nsq48/NSCo4YX5mjydjypxD7UmHh/brMu8h/Mhd/F7qAeoH2NOO8SDTk6kjnTFc4WpzmfYpQ==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.2.1.tgz", + "integrity": "sha512-U2k0XHLJfaciARRxDcqTk2AZQsGXerHzdvfCZcy1hNhSf5KCAF4jIQQxL+apQviOekhRFPqED6Of5/+LcUSLzQ==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -13559,9 +13961,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "dev": true, "funding": [ { @@ -13580,7 +13982,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -14040,9 +14442,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 90016705be..9852fa3730 100644 --- a/package.json +++ b/package.json @@ -63,10 +63,10 @@ }, "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.5.2", + "ansis": "^3.9.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.17.0", + "eslint": "^9.18.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -79,12 +79,12 @@ "pm2": "^5.4.3", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.24.3", - "undici": "^7.2.0" + "systeminformation": "^5.25.11", + "undici": "^7.2.1" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.12.1", - "cspell": "^8.17.1", + "@stylistic/eslint-plugin": "^2.13.0", + "cspell": "^8.17.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.10.0", "eslint-plugin-jsdoc": "^50.6.1", @@ -92,18 +92,18 @@ "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", - "jsdom": "^25.0.1", + "jsdom": "^26.0.0", "lint-staged": "^15.3.0", "markdownlint-cli2": "^0.17.1", "playwright": "^1.49.1", "prettier": "^3.4.2", "sinon": "^19.0.2", - "stylelint": "^16.12.0", - "stylelint-config-standard": "^36.0.1", + "stylelint": "^16.13.1", + "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.2" }, "optionalDependencies": { - "electron": "^32.2.7" + "electron": "^32.2.8" }, "engines": { "node": ">=20.18.1 <21 || >=22" From 6e40c446f426d4b8226ed8203c0144a7312925bd Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 14 Jan 2025 22:58:14 +0100 Subject: [PATCH 183/418] fix wrong port in log message when starting server only (#3697) fixes #3696 --- CHANGELOG.md | 1 + serveronly/index.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 782ecb47e3..08f5ba3240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ planned for 2025-04-01 - [tests] Electron tests: Fixes for running under new github image ubuntu-24.04, replace xserver with labwc, running under xserver and labwc depending on env variable WAYLAND_DISPLAY is set (#3676) - [calendar] Fix arrayed symbols, #3267, again, add testcase, add testcase for #3678 - [weather] Fix wrong weatherCondition name in openmeteo provider which lead to n/a icon +- [core] Fix wrong port in log message when starting server only (#3696) ## [2.30.0] - 2025-01-01 diff --git a/serveronly/index.js b/serveronly/index.js index 66632ac105..6156a0a0a5 100644 --- a/serveronly/index.js +++ b/serveronly/index.js @@ -4,5 +4,5 @@ const Log = require("../js/logger"); app.start().then((config) => { const bindAddress = config.address ? config.address : "localhost"; const httpType = config.useHttps ? "https" : "http"; - Log.info(`\n>>> Ready to go! Please point your browser to: ${httpType}://${bindAddress}:${config.port} <<<`); + Log.info(`\n>>> Ready to go! Please point your browser to: ${httpType}://${bindAddress}:${global.mmPort || config.port} <<<`); }); From 77fe01175c21e00d4cf101ab244341c0413b05ed Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 17 Jan 2025 19:03:28 +0100 Subject: [PATCH 184/418] Use different issue templates (#3695) This PR will introduce different issue templates for bug reports, feature requests and so on on GitHub. There is still room for fine-tuning, but it's reached a state to show it to you and get feedback. I think that this can lead to better bug reports. You can see the result in my repo: https://github.com/KristjanESPERANTO/MagicMirror/issues/new/choose Feel free to create new issues for testing. What do you think? Do we want to pursue this further? --- .github/CONTRIBUTING.md | 28 ---- .github/ISSUE_TEMPLATE.md | 52 ------- .github/ISSUE_TEMPLATE/bug_report.yml | 154 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/change_request.yml | 41 ++++++ .github/ISSUE_TEMPLATE/config.yml | 14 ++ .github/ISSUE_TEMPLATE/feature_request.yml | 67 +++++++++ .github/PULL_REQUEST_TEMPLATE.md | 2 +- CHANGELOG.md | 1 + 8 files changed, 278 insertions(+), 81 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/change_request.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 1f897d047e..f934c59ccf 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -36,31 +36,3 @@ To run all tests, use `npm run test`. The specific test commands are defined in `package.json`. So you can also run the specific tests with other commands, e.g. `npm run test:unit` or `npx jest tests/e2e/env_spec.js`. - -## Submitting Issues - -Please only submit reproducible issues. - -If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt) - -Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting) - -When submitting a new issue, please supply the following information: - -**Platform**: Place your platform here... give us your web browser/Electron version _and_ your hardware (Raspberry Pi 2/3/4, Windows, Mac, Linux, System V UNIX). - -**Node Version**: Make sure it's version 20 or later (recommended is 22). - -**MagicMirror² Version**: Please let us know which version of MagicMirror² you are running. It can be found in the `package.json` file. - -**Description**: Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem. - -**Steps to Reproduce**: List the step by step process to reproduce the issue. - -**Expected Results**: Describe what you expected to see. - -**Actual Results**: Describe what you actually saw. - -**Configuration**: What does the used config.js file look like? Don't forget to remove any sensitive information! - -**Additional Notes**: Provide any other relevant notes not previously mentioned. This is optional. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 2aa4b4d87f..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,52 +0,0 @@ -Hello and thank you for opening an issue. - -**⚠️ Please make sure that you have read the following lines before submitting your Issue:** - -## I'm not sure if this is a bug - -If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt) - -## I'm having troubles installing or configuring MagicMirror - -Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting) - -A common problem is that your config file could be invalid. Please run in your MagicMirror² directory: `npm run config:check` and see if it reports an error. - -## I found a bug in the MagicMirror² installer - -If you are facing an issue or found a bug while trying to install MagicMirror² via the installer please report it in the respective GitHub repository: -[https://github.com/sdetweil/MagicMirror_scripts](https://github.com/sdetweil/MagicMirror_scripts) - -## I found a bug in the MagicMirror² Docker image - -If you are facing an issue or found a bug while running MagicMirror² inside a Docker container please create an issue in the corresponding repository: -[https://gitlab.com/khassel/magicmirror](https://gitlab.com/khassel/magicmirror) - -## I'm having troubles installing or configuring foreign modules - -Please open an issue in the module repository or ask for help in the [forum](https://forum.magicmirror.builders/) - ---- - -## I found a bug in MagicMirror - -Please make sure to only submit reproducible issues. You can safely remove everything above the dividing line. -When submitting a new issue, please supply the following information: - -**Platform**: Place your platform here... give us your web browser/Electron version _and_ your hardware (Raspberry Pi 2/3/4, Windows, Mac, Linux, System V UNIX). - -**Node Version**: Make sure it's version 20 or later (recommended is 22). - -**MagicMirror² Version**: Please let us know which version of MagicMirror² you are running. It can be found in the `package.json` file. - -**Description**: Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem. - -**Steps to Reproduce**: List the step by step process to reproduce the issue. - -**Expected Results**: Describe what you expected to see. - -**Actual Results**: Describe what you actually saw. - -**Configuration**: What does the used config.js file look like? Don't forget to remove any sensitive information! - -**Additional Notes**: Provide any other relevant notes not previously mentioned. This is optional. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..d9777a4d5d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,154 @@ +name: 🐛 Report a problem +description: Report an issue with MagicMirror² 🚨 +title: "[Bug] {{ brief description }}" +labels: + - bug +body: + - type: markdown + attributes: + value: | + Thanks for reporting a bug! Please fill in the following template to help us reproduce the issue. + Please only submit reproducible issues. If you're not sure if it's a real bug or if it's just you, please open a topic on the forum. + - type: textarea + id: environment + attributes: + label: Environment + description: | + Please tell us about how your MagicMirror² is set up. + + Optimal would be the systeminformation from the logs, which looks like this: + ```bash + [2025-01-14 20:05:03.529] [INFO] System information: + ### SYSTEM: manufacturer: Raspberry Pi Foundation; model: Raspberry Pi 4 Model B Rev 1.5; virtual: false + ### OS: platform: linux; distro: Debian GNU/Linux; release: 12; arch: arm64; kernel: 6.1.21-v8+ + ### VERSIONS: electron: 31.2.1; used node: 20.15.0; installed node: 22.4.1; npm: 10.8.1; pm2: + ### OTHER: timeZone: Europe/Berlin; ELECTRON_ENABLE_GPU: undefined + ``` + + If you can't provide this information, please provide the following: + - MagicMirror² version: Can be found in the `package.json` file. Please use the latest version before reporting a bug. + - Node version: Run `node -v` to find out. Make sure it's version 20 or later (recommended is 22). + - npm version: Run `npm -v` to find out. + - Platform: Are you using a Raspberry Pi (2/3/4/5), Windows, Mac, Linux, Docker, or something else? + value: | + MagicMirror² version: + Node version: + npm version: + Platform: + validations: + required: true + - type: dropdown + id: start-option + attributes: + label: Which start option are you using? + description: | + Please keep in mind that some problems are specific to certain start options. + options: + - "npm run start" + - "npm run start:wayland" + - "npm run start:windows" + - "npm run start:x11" + - "npm run server" + - "node clientonly --address ... --port ..." + validations: + required: true + - type: dropdown + id: pm2 + attributes: + label: Are you using PM2? + options: + - "No" + - "Yes" + - "I don't know" + validations: + required: true + - type: dropdown + id: module + attributes: + label: Module + description: | + If the issue is related to a specific module, please provide the name of the module. + Note: Please don't report issues with 3rd party modules here. Report them on the module's repository. + options: + - "alert" + - "calendar" + - "clock" + - "compliments" + - "helloworld" + - "newsfeed" + - "updatenotification" + - "weather" + - type: checkboxes + id: module-disabled + attributes: + label: Have you tried disabling other modules? + options: + - label: "Yes" + - label: "No" + - type: checkboxes + id: search + attributes: + label: Have you searched if someone else has already reported the issue on the forum or in the issues? + options: + - label: "Yes" + required: true + - type: textarea + id: description + attributes: + label: What did you do? + description: | + Please include a *minimal* reproduction case. List the step by step process to reproduce the issue. + You can use Markdown in this field. + value: | +
+ Configuration + + ``` + + ``` +
+ + ```js + + ``` + + Steps to reproduce the issue: + validations: + required: true + - type: textarea + id: expectation + attributes: + label: What did you expect to happen? + description: | + You can use Markdown in this field. + validations: + required: true + - type: textarea + id: lint-output + attributes: + label: What actually happened? + description: | + Please copy-paste relevant log output or error messages. + You can use Markdown in this field. + validations: + required: true + + - type: textarea + id: comments + attributes: + label: Additional comments + description: | + Is there anything else that's important for the team to know? + Fill out all fields and provide as much information as possible. + Adding screenshots might help us understand your problem better. + + - type: checkboxes + attributes: + label: Participation + options: + - label: "I am willing to submit a pull request for this change." + required: false + + - type: markdown + attributes: + value: Please **do not** open a pull request until this issue has been accepted by the team. diff --git a/.github/ISSUE_TEMPLATE/change_request.yml b/.github/ISSUE_TEMPLATE/change_request.yml new file mode 100644 index 0000000000..92503877e0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/change_request.yml @@ -0,0 +1,41 @@ +name: 🔀 Request a change +description: Request a change that is not a bug fix, a feature request or a support request. +title: "[Change Request] {{ brief description }}" +labels: + - enhancement + - core +body: + - type: markdown + attributes: + value: Thanks for requesting a change! Please fill in the following template to help us understand your request. + - type: textarea + attributes: + label: What problem do you want to solve with this change? + description: | + Please explain your use case in as much detail as possible. + placeholder: | + Currently... + validations: + required: true + - type: textarea + attributes: + label: What do you think is the correct solution? + description: | + Please explain how you'd like to change MagicMirror² to address the problem. + placeholder: | + I'd like MagicMirror² to... + validations: + required: true + - type: checkboxes + attributes: + label: Participation + options: + - label: I am willing to submit a pull request for this change. + required: false + - type: markdown + attributes: + value: Please **do not** open a pull request until this issue has been accepted by the team. + - type: textarea + attributes: + label: Additional comments + description: Is there anything else that's important for the team to know? diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..fc4b85ad93 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: false +contact_links: + - name: 📚 Documentation + url: https://github.com/MagicMirrorOrg/MagicMirror-Documentation/issues + about: This issue tracker is not for documentation issues. Please file documentation issues on the docs repo. + - name: 🤔 Support Question + url: https://forum.magicmirror.builders/ + about: Problems installing or configuring your MagicMirror? Please post your question on the MagicMirror² Forum. + - name: 💬 Exchange of ideas + url: https://discord.gg/AmGBBwPph5 + about: This issue tracker is not for general discussion. Please use the Discord channel. + - name: 📦 Issues with a 3rd-party module + url: https://kristjanesperanto.github.io/MagicMirror-3rd-Party-Modules/ + about: This issue tracker is not for 3rd-party module issues. Please file 3rd-party module issues on the module's repo. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000..a0ea2f9253 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,67 @@ +name: 🚀 Feature Request +description: Suggest a new feature for MagicMirror² 💡 +title: "[Feature Request] {{ brief description }}" +body: + - type: checkboxes + id: prerequisites + attributes: + label: Prerequisites + description: Please ensure you have completed all of the following. + options: + - label: I am running the latest version of MagicMirror², and know that this feature is not available now. + required: true + - label: I know my issue is not related to a third-party module. + required: true + - label: I have searched for [existing issues](https://github.com/MagicMirrorOrg/MagicMirror/issues) that already include this feature request, without success. + required: true + + - type: textarea + id: description + attributes: + label: Describe the Feature Request + description: A clear and concise description of what the feature does. + validations: + required: true + + - type: textarea + id: use-case + attributes: + label: Describe the Use Case + description: A clear and concise use case for what problem this feature would solve. + validations: + required: true + + - type: textarea + id: proposed-solution + attributes: + label: Describe Preferred Solution + description: A clear and concise description of how you want this feature to be added to MagicMirror². + + - type: textarea + id: alternatives-considered + attributes: + label: Describe Alternatives + description: A clear and concise description of any alternative solutions or features you have considered. + + - type: textarea + id: related-code + attributes: + label: Related Code + description: If you are able to illustrate the feature request with an example, please provide a sample here. + + - type: textarea + id: additional-information + attributes: + label: Additional Information + description: List any other information that is relevant to your issue. Related issues, suggestions on how to implement, Stack Overflow links, forum links, etc. + + - type: checkboxes + attributes: + label: Participation + options: + - label: I am willing to submit a pull request for this change. + required: false + + - type: markdown + attributes: + value: Please **do not** open a pull request until this issue has been accepted by the team. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ace1e86435..e3dc222245 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,4 @@ -Hello and thank you for wanting to contribute to the MagicMirror² project +Hello and thank you for wanting to contribute to the MagicMirror² project! **Please make sure that you have followed these 4 rules before submitting your Pull Request:** diff --git a/CHANGELOG.md b/CHANGELOG.md index 08f5ba3240..4f4252a704 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ planned for 2025-04-01 - [core] starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) (#3677) - [core] Optimize systeminformation calls and output +- [core] Add issue templates for feature requests and bug reports ### Removed From 53ac31dcf3ad1acc7c43d330aa2b2e598cbba8d2 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 19 Jan 2025 16:29:28 +0100 Subject: [PATCH 185/418] Adapt `start:x11:dev` script (#3700) This doesn't actually change anything functionally, but with this we use the same schema as for `start:wayland:dev` and `start:windows:dev`. --- CHANGELOG.md | 9 +++++---- package.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f4252a704..5ce2668ba3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,21 +18,22 @@ planned for 2025-04-01 ### Changed - [core] starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) (#3677) -- [core] Optimize systeminformation calls and output -- [core] Add issue templates for feature requests and bug reports +- [core] Optimize systeminformation calls and output (#3689) +- [core] Add issue templates for feature requests and bug reports (#3695) +- [core] Adapt `start:x11:dev` script ### Removed ### Updated -- [core] Update dependencies and formatting +- [core] Update dependencies and formatting (#3693) ### Fixed - [calendar] Fix clipping events being broadcast (#3678) - [tests] Electron tests: Fixes for running under new github image ubuntu-24.04, replace xserver with labwc, running under xserver and labwc depending on env variable WAYLAND_DISPLAY is set (#3676) - [calendar] Fix arrayed symbols, #3267, again, add testcase, add testcase for #3678 -- [weather] Fix wrong weatherCondition name in openmeteo provider which lead to n/a icon +- [weather] Fix wrong weatherCondition name in openmeteo provider which lead to n/a icon (#3691) - [core] Fix wrong port in log message when starting server only (#3696) ## [2.30.0] - 2025-01-01 diff --git a/package.json b/package.json index 9852fa3730..f7086dd663 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "start:windows": ".\\node_modules\\.bin\\electron js\\electron.js", "start:windows:dev": "npm run start:windows -- dev", "start:x11": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js", - "start:x11:dev": "npm run start -- dev", + "start:x11:dev": "npm run start:x11 -- dev", "test": "NODE_ENV=test jest -i --forceExit", "test:calendar": "node ./modules/default/calendar/debug.js", "test:coverage": "NODE_ENV=test jest --coverage -i --verbose false --forceExit", From af77b7b628881ec22ae25d220be1affa34746446 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Thu, 23 Jan 2025 01:37:41 -0600 Subject: [PATCH 186/418] fix #3701, calculation wrong, added testcase, ics, config (#3702) fixes #3701 offset calculation wrong when user looking back at east coast event added testcase --- CHANGELOG.md | 1 + .../default/calendar/calendarfetcherutils.js | 4 ++- .../chicago-looking-at-ny-recurring.js | 33 +++++++++++++++++++ tests/electron/modules/calendar_spec.js | 5 +++ tests/mocks/chicago-nyedge.ics | 15 +++++++++ 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/configs/modules/calendar/chicago-looking-at-ny-recurring.js create mode 100644 tests/mocks/chicago-nyedge.ics diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ce2668ba3..1d1a004c0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ planned for 2025-04-01 - [calendar] Fix arrayed symbols, #3267, again, add testcase, add testcase for #3678 - [weather] Fix wrong weatherCondition name in openmeteo provider which lead to n/a icon (#3691) - [core] Fix wrong port in log message when starting server only (#3696) +- [calendar] NewYork event processed on system in Central timezone shows wrong time #3701 ## [2.30.0] - 2025-01-01 diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index b89f5962c2..df567af4f6 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -662,9 +662,11 @@ const CalendarFetcherUtils = { Log.debug("signs are the same"); if (Math.sign(eventDiff) === -1) { //if west, looking at more west + // -350 <-300 if (nowDiff < eventDiff) { //-600 -420 - eventDiff = -(eventDiff - (nowDiff - eventDiff)); //-180 + //300 -300 -360 +300 + eventDiff = nowDiff - eventDiff; //-180 Log.debug("now looking back east delta diff=", eventDiff); } else { diff --git a/tests/configs/modules/calendar/chicago-looking-at-ny-recurring.js b/tests/configs/modules/calendar/chicago-looking-at-ny-recurring.js new file mode 100644 index 0000000000..1cab2375d6 --- /dev/null +++ b/tests/configs/modules/calendar/chicago-looking-at-ny-recurring.js @@ -0,0 +1,33 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + maximumNumberOfDays: 28, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/chicago-nyedge.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 6143d29a36..0f8ee5803b 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -253,6 +253,11 @@ describe("Calendar module", () => { // just await expect(doTestTableContent(".calendar .event", ".time", "29th.Oct, 05:00-30th.Oct, 18:00", first)).resolves.toBe(true); }); + it("viewing from further west in diff timezones", async () => { + await helpers.startApplication("tests/configs/modules/calendar/chicago-looking-at-ny-recurring.js", "22 Jan 2025 14:30:00 GMT-06:00", [], "America/Chicago"); + // just + await expect(doTestTableContent(".calendar .event", ".time", "22nd.Jan, 17:30-19:30", first)).resolves.toBe(true); + }); }); describe("one event non repeating", () => { diff --git a/tests/mocks/chicago-nyedge.ics b/tests/mocks/chicago-nyedge.ics new file mode 100644 index 0000000000..641ff022d2 --- /dev/null +++ b/tests/mocks/chicago-nyedge.ics @@ -0,0 +1,15 @@ +BEGIN:VEVENT +DTSTART;TZID=America/New_York:20240918T183000 +DTEND;TZID=America/New_York:20240918T203000 +RRULE:FREQ=WEEKLY;BYDAY=WE +EXDATE;TZID=America/New_York:20241127T183000 +EXDATE;TZID=America/New_York:20241225T183000 +DTSTAMP:20250122T045443Z +UID:_@google.com +CREATED:20240916T131843Z +LAST-MODIFIED:20241222T235014Z +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Derby +TRANSP:OPAQUE +END:VEVENT \ No newline at end of file From d6f2e7165f4501e4ee9edfe0c7bd4521917ab3f5 Mon Sep 17 00:00:00 2001 From: Magnus <34011212+MagMar94@users.noreply.github.com> Date: Mon, 27 Jan 2025 22:41:51 +0100 Subject: [PATCH 187/418] Fix frozen Yr weather-module (#3706) Fixes #3296 The problem was that the fetch-methods threw errors when something went wrong instead of calling `updateAvailable()`. `updateAvailable()` must be called in order to schedule the next update. I added some filtering for the hourly forecast that removes hours in the past. If the API call fails we use the cached data, but we should only display hours in the future. --- CHANGELOG.md | 2 ++ modules/default/weather/providers/yr.js | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d1a004c0b..1e02f2dcd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ planned for 2025-04-01 - [core] Optimize systeminformation calls and output (#3689) - [core] Add issue templates for feature requests and bug reports (#3695) - [core] Adapt `start:x11:dev` script +- [weather/yr] The Yr weather provider now enforces a minimum `updateInterval` of 600 000 ms (10 minutes) to comply with the terms of service. If a lower value is set, it will be automatically increased to this minimum. ### Removed @@ -36,6 +37,7 @@ planned for 2025-04-01 - [weather] Fix wrong weatherCondition name in openmeteo provider which lead to n/a icon (#3691) - [core] Fix wrong port in log message when starting server only (#3696) - [calendar] NewYork event processed on system in Central timezone shows wrong time #3701 +- [weather/yr] The Yr weather provider is now able to recover from bad API resposes instead of freezing (#3296) ## [2.30.0] - 2025-01-01 diff --git a/modules/default/weather/providers/yr.js b/modules/default/weather/providers/yr.js index f305a1c09d..a89dacd824 100644 --- a/modules/default/weather/providers/yr.js +++ b/modules/default/weather/providers/yr.js @@ -23,6 +23,10 @@ WeatherProvider.register("yr", { Log.error("The Yr weather provider requires local storage."); throw new Error("Local storage not available"); } + if (this.config.updateInterval < 600000) { + Log.warn("The Yr weather provider requires a minimum update interval of 10 minutes (600 000 ms). The configuration has been adjusted to meet this requirement."); + this.delegate.config.updateInterval = 600000; + } Log.info(`Weather provider: ${this.providerName} started.`); }, @@ -34,7 +38,7 @@ WeatherProvider.register("yr", { }) .catch((error) => { Log.error(error); - throw new Error(error); + this.updateAvailable(); }); }, @@ -119,7 +123,12 @@ WeatherProvider.register("yr", { }) .catch((err) => { Log.error(err); - reject("Unable to get weather data from Yr."); + if (weatherData) { + Log.warn("Using outdated cached weather data."); + resolve(weatherData); + } else { + reject("Unable to get weather data from Yr."); + } }) .finally(() => { localStorage.removeItem("yrIsFetchingWeatherData"); @@ -497,7 +506,7 @@ WeatherProvider.register("yr", { }) .catch((error) => { Log.error(error); - throw new Error(error); + this.updateAvailable(); }); }, @@ -530,7 +539,15 @@ WeatherProvider.register("yr", { getHourlyForecastFrom (weatherData) { const series = []; + const now = moment({ + year: moment().year(), + month: moment().month(), + day: moment().date(), + hour: moment().hour() + }); for (const forecast of weatherData.properties.timeseries) { + if (now.isAfter(moment(forecast.time))) continue; + forecast.symbol = forecast.data.next_1_hours?.summary?.symbol_code; forecast.precipitationAmount = forecast.data.next_1_hours?.details?.precipitation_amount; forecast.precipitationProbability = forecast.data.next_1_hours?.details?.probability_of_precipitation; @@ -600,7 +617,7 @@ WeatherProvider.register("yr", { }) .catch((error) => { Log.error(error); - throw new Error(error); + this.updateAvailable(); }); } }); From f34c8f2993bf68b09df86cd43aa8168f52d43f86 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 31 Jan 2025 22:54:48 +0100 Subject: [PATCH 188/418] update github workflows (#3709) to call `sudo apt-get update` before `sudo apt-get install` I had problems running the tests on my fork, while running the `apt-get install` command in automated tests workflow I got ```bash E: Failed to fetch http://security.ubuntu.com/ubuntu/pool/main/m/mesa/libegl-mesa0_24.0.9-0ubuntu0.3_amd64.deb 404 Not Found [IP: 52.147.219.192 80] ``` Found a similar [Issue](https://github.com/actions/runner-images/issues/10785#issuecomment-2420741561) with a solution which is to run `sudo apt-get update` before. --- .github/workflows/automated-tests.yaml | 4 +++- .github/workflows/electron-rebuild.yaml | 4 +++- CHANGELOG.md | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index b6ab34a6ad..f10850123f 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -41,7 +41,9 @@ jobs: node-version: [20.18.1, 20.x, 22.x, 23.x] steps: - name: Install electron dependencies and labwc - run: sudo apt-get install -y libnss3 libasound2t64 labwc + run: | + sudo apt-get update + sudo apt-get install -y libnss3 libasound2t64 labwc - name: "Checkout code" uses: actions/checkout@v4 - name: "Use Node.js ${{ matrix.node-version }}" diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index 5d310e1cfb..fa3aec7106 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -22,7 +22,9 @@ jobs: - name: Install @electron/rebuild run: npm install @electron/rebuild - name: Install node-libgpiod deps - run: sudo apt-get install gpiod libgpiod2 libgpiod-dev + run: | + sudo apt-get update + sudo apt-get install gpiod libgpiod2 libgpiod-dev - name: Install test library (node-libgpiod) to be rebuilded run: npm install node-libgpiod - name: Run electron-rebuild diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e02f2dcd8..92c9803367 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ planned for 2025-04-01 - [core] Add issue templates for feature requests and bug reports (#3695) - [core] Adapt `start:x11:dev` script - [weather/yr] The Yr weather provider now enforces a minimum `updateInterval` of 600 000 ms (10 minutes) to comply with the terms of service. If a lower value is set, it will be automatically increased to this minimum. +- [workflow] Run `sudo apt-get update` before installing packages to avoid install errors ### Removed From e00a6667956fea16bab8cf55f5bd76e129072b1f Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Sat, 1 Feb 2025 15:02:29 +0900 Subject: [PATCH 189/418] chore: update newsfeed.js (#3692) Therefor -> Therefore refs: #3690 --- modules/default/newsfeed/newsfeed.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 95c4cde91e..34f040a508 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -57,7 +57,7 @@ Module.register("newsfeed", { // Define required translations. getTranslations () { // The translations for the default modules are defined in the core translation files. - // Therefor we can just return false. Otherwise we should have returned a dictionary. + // Therefore we can just return false. Otherwise we should have returned a dictionary. // If you're trying to build your own module including translations, check out the documentation. return false; }, From aa20eadca3e7d5b52d7e6b31917b9fc4cbaa24d6 Mon Sep 17 00:00:00 2001 From: Veeck Date: Sat, 1 Feb 2025 22:24:49 +0100 Subject: [PATCH 190/418] Monthly update to dependencies (#3717) nothing to see here really --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: veeck --- CHANGELOG.md | 8 +- package-lock.json | 513 +++++++++++++++++++-------------------- package.json | 28 +-- vendor/package-lock.json | 8 +- vendor/package.json | 2 +- 5 files changed, 278 insertions(+), 281 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92c9803367..de08f18f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,16 +28,16 @@ planned for 2025-04-01 ### Updated -- [core] Update dependencies and formatting (#3693) +- [core] Update dependencies and formatting (#3693, #3717) ### Fixed - [calendar] Fix clipping events being broadcast (#3678) -- [tests] Electron tests: Fixes for running under new github image ubuntu-24.04, replace xserver with labwc, running under xserver and labwc depending on env variable WAYLAND_DISPLAY is set (#3676) +- [tests] Fix Electron tests by running them under new github image ubuntu-24.04, replace xserver with labwc, running under xserver and labwc depending on env variable WAYLAND_DISPLAY is set (#3676) - [calendar] Fix arrayed symbols, #3267, again, add testcase, add testcase for #3678 - [weather] Fix wrong weatherCondition name in openmeteo provider which lead to n/a icon (#3691) - [core] Fix wrong port in log message when starting server only (#3696) -- [calendar] NewYork event processed on system in Central timezone shows wrong time #3701 +- [calendar] Fix NewYork event processed on system in Central timezone shows wrong time #3701 - [weather/yr] The Yr weather provider is now able to recover from bad API resposes instead of freezing (#3296) ## [2.30.0] - 2025-01-01 @@ -136,7 +136,7 @@ Thanks to: @bugsounet, @dkallen78, @jargordon, @khassel, @KristjanESPERANTO, @Ma - [core] Detail optimizations in `config_check.js` - [core] Updated minimal needed node version in `package.json` (currently v20.9.0) (#3559) and except for v21 (no security updates) (#3561) - [linter] Switch to ESLint v9 and flat config and replace `eslint-plugin-unicorn` by `@eslint/js` -- [core] fix discovering module positions twice after #3450 +- [core] Fix discovering module positions twice after #3450 ### Fixed diff --git a/package-lock.json b/package-lock.json index 23a62b010d..8ca103da0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,10 @@ "license": "MIT", "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.9.0", + "ansis": "^3.10.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.18.0", + "eslint": "^9.19.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -28,33 +28,33 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.2.1" + "undici": "^7.3.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.13.0", - "cspell": "^8.17.2", + "@stylistic/eslint-plugin": "^3.0.1", + "cspell": "^8.17.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^28.10.0", - "eslint-plugin-jsdoc": "^50.6.1", - "eslint-plugin-package-json": "^0.19.0", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-jsdoc": "^50.6.3", + "eslint-plugin-package-json": "^0.21.1", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^26.0.0", - "lint-staged": "^15.3.0", - "markdownlint-cli2": "^0.17.1", - "playwright": "^1.49.1", + "lint-staged": "^15.4.3", + "markdownlint-cli2": "^0.17.2", + "playwright": "^1.50.1", "prettier": "^3.4.2", "sinon": "^19.0.2", - "stylelint": "^16.13.1", + "stylelint": "^16.14.1", "stylelint-config-standard": "^37.0.0", - "stylelint-prettier": "^5.0.2" + "stylelint-prettier": "^5.0.3" }, "engines": { "node": ">=20.18.1 <21 || >=22" }, "optionalDependencies": { - "electron": "^32.2.8" + "electron": "^32.3.0" } }, "node_modules/@altano/repository-tools": { @@ -619,9 +619,9 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.2.tgz", - "integrity": "sha512-t+DQtruJF2cYfXF5GC4F0O/PQR04hL5WH55R9oOaor5i7K8ejbw6+jex2LB0XbZFf3qBhXNSnMPuM3b/113LnA==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.3.tgz", + "integrity": "sha512-6uOF726o3JnExAUKM20OJJXZo+Qf9Jt64nkVwnVXx7Upqr5I9Pb1npYPEAIpUA03SnWYmKwUIqhAmkwrN+bLPA==", "dev": true, "license": "MIT", "dependencies": { @@ -629,19 +629,19 @@ "@cspell/dict-al": "^1.1.0", "@cspell/dict-aws": "^4.0.9", "@cspell/dict-bash": "^4.2.0", - "@cspell/dict-companies": "^3.1.12", + "@cspell/dict-companies": "^3.1.13", "@cspell/dict-cpp": "^6.0.3", "@cspell/dict-cryptocurrencies": "^5.0.4", "@cspell/dict-csharp": "^4.0.6", "@cspell/dict-css": "^4.0.17", "@cspell/dict-dart": "^2.3.0", - "@cspell/dict-data-science": "^2.0.6", + "@cspell/dict-data-science": "^2.0.7", "@cspell/dict-django": "^4.1.4", "@cspell/dict-docker": "^1.1.12", "@cspell/dict-dotnet": "^5.0.9", "@cspell/dict-elixir": "^4.0.7", - "@cspell/dict-en_us": "^4.3.29", - "@cspell/dict-en-common-misspellings": "^2.0.8", + "@cspell/dict-en_us": "^4.3.30", + "@cspell/dict-en-common-misspellings": "^2.0.9", "@cspell/dict-en-gb": "1.1.33", "@cspell/dict-filetypes": "^3.0.10", "@cspell/dict-flutter": "^1.1.0", @@ -651,7 +651,7 @@ "@cspell/dict-gaming-terms": "^1.1.0", "@cspell/dict-git": "^3.0.4", "@cspell/dict-golang": "^6.0.18", - "@cspell/dict-google": "^1.0.5", + "@cspell/dict-google": "^1.0.8", "@cspell/dict-haskell": "^4.0.5", "@cspell/dict-html": "^4.0.11", "@cspell/dict-html-symbol-entities": "^4.0.3", @@ -666,17 +666,17 @@ "@cspell/dict-markdown": "^2.0.9", "@cspell/dict-monkeyc": "^1.0.10", "@cspell/dict-node": "^5.0.6", - "@cspell/dict-npm": "^5.1.22", + "@cspell/dict-npm": "^5.1.24", "@cspell/dict-php": "^4.0.14", "@cspell/dict-powershell": "^5.0.14", - "@cspell/dict-public-licenses": "^2.0.12", - "@cspell/dict-python": "^4.2.14", + "@cspell/dict-public-licenses": "^2.0.13", + "@cspell/dict-python": "^4.2.15", "@cspell/dict-r": "^2.1.0", "@cspell/dict-ruby": "^5.0.7", "@cspell/dict-rust": "^4.0.11", "@cspell/dict-scala": "^5.0.7", "@cspell/dict-shell": "^1.1.0", - "@cspell/dict-software-terms": "^4.2.2", + "@cspell/dict-software-terms": "^4.2.4", "@cspell/dict-sql": "^2.2.0", "@cspell/dict-svelte": "^1.0.6", "@cspell/dict-swift": "^2.0.5", @@ -689,22 +689,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.2.tgz", - "integrity": "sha512-9QFzuSApaK7SYB50iCTRIUDjFZf6DXTFj8+qTR2cky+/YmEcHDpJieJVCd3STONO4m2JyqIsV7faEuA6M0YcHg==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.3.tgz", + "integrity": "sha512-RWSfyHOin/d9CqLjz00JMvPkag3yUSsQZr6G9BnCT5cMEO/ws8wQZzA54CNj/LAOccbknTX65SSroPPAtxs56w==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.17.2" + "@cspell/cspell-types": "8.17.3" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.2.tgz", - "integrity": "sha512-LOTKK+hZSUc7vaN8SBEOcv+9dMYbo84awbsjjdI+HkKVBfTt3Lzlu6IJImw39L6pTDAJ1ZxOUdWO89jcxpyihg==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.3.tgz", + "integrity": "sha512-DqqSWKt9NLWPGloYxZTpzUhgdW8ObMkZmOOF6TyqpJ4IbckEct8ULgskNorTNRlmmjLniaNgvg6JSHuYO3Urxw==", "dev": true, "license": "MIT", "engines": { @@ -712,9 +712,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.2.tgz", - "integrity": "sha512-Z2ndlzVIiXOCBnQby9q+OXcxeddiuCi//pnhO9Jf6Ixgthn+Yg7bwzAnHu+CM1SJaQnZCntGyimdxfojm+WDdA==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.3.tgz", + "integrity": "sha512-yQlVaIsWiax6RRuuacZs++kl6Y9rwH9ZkVlsG9fhdeCJ5Xf3WCW+vmX1chzhhKDzRr8CF9fsvb1uagd/5/bBYA==", "dev": true, "license": "MIT", "dependencies": { @@ -725,9 +725,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.2.tgz", - "integrity": "sha512-Cp4kVxJRyyDRd5RVTASlu+ygWG+dgy6GyH7lzb6P8SOXt1mxzCBK6Q5Dc1XHAsvhRaLrnMziCO/5Pj9/0DKs6w==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.3.tgz", + "integrity": "sha512-CC3nob/Kbuesz5WTW+LjAHnDFXJrA49pW5ckmbufJxNnoAk7EJez/qr7/ELMTf6Fl3A5xZ776Lhq7738Hy/fmQ==", "dev": true, "license": "MIT", "engines": { @@ -735,9 +735,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.2.tgz", - "integrity": "sha512-4kMBhX92p0pchEzYTpyLCoe/bUJ29YYvMINTeHTd//hLQh0ZAyMGY1opDm1tqaXX0qpYmWG60KcvN4fCR0i6lw==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.3.tgz", + "integrity": "sha512-ozgeuSioX9z2wtlargfgdw3LKwDFAfm8gxu+xwNREvXiLsevb+lb7ZlY5/ay+MahqR5Hfs7XzYzBLTKL/ldn9g==", "dev": true, "license": "MIT", "engines": { @@ -776,9 +776,9 @@ } }, "node_modules/@cspell/dict-companies": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.12.tgz", - "integrity": "sha512-99FxBNdLOQc3nVQ663Xh7JqDLbIy/AdqOecQ5bk3HpmXpSkoDvTT7XCUU5nQZvmFBrrQlXFKlRRYjLfTEOUDdA==", + "version": "3.1.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.13.tgz", + "integrity": "sha512-EAaFMxnSG4eQKup9D81EnWAYIzorLWG7b7Zzf+Suu0bVeFBpCYESss/EWtnmb5ZZNfKAGxtoMqfL3vRfyJERIQ==", "dev": true, "license": "MIT" }, @@ -818,9 +818,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-data-science": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.6.tgz", - "integrity": "sha512-gOYKZOg358yhnnQfr1/f232REmjeIymXUHJdrLEMPirluv2rzMWvEBBazqRVQ++jMUNg9IduVI0v096ZWMDekA==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.7.tgz", + "integrity": "sha512-XhAkK+nSW6zmrnWzusmZ1BpYLc62AWYHZc2p17u4nE2Z9XG5DleG55PCZxXQTKz90pmwlhFM9AfpkJsYaBWATA==", "dev": true, "license": "MIT" }, @@ -853,16 +853,16 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.29", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.29.tgz", - "integrity": "sha512-7kHP0sJ271oS5RqakxvhWvHFoCUFCBDV6+cgIRIpKwW0aYVB4F2AwElGsdeE/XEmihhYUje7e/e6X3IEWHrcrQ==", + "version": "4.3.30", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.30.tgz", + "integrity": "sha512-p0G5fByj5fUnMyFUlkN3kaqE3nuQkqpYV47Gn9n8k2TszsdLY55xj9UoFE4YIcjOiyU1bR/YDJ5daiPMYXTJ/A==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.8.tgz", - "integrity": "sha512-l1u/pDjwrPyWwBd1hCkZhdsK8yLbLFPD2xWz+1tFFI7WaV9ckDZoF3woRc/0wFGRy53yrfSAVuwhoYOQnHe/fA==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.9.tgz", + "integrity": "sha512-O/jAr1VNtuyCFckbTmpeEf43ZFWVD9cJFvWaA6rO2IVmLirJViHWJUyBZOuQcesSplzEIw80MAYmnK06/MDWXQ==", "dev": true, "license": "CC BY-SA 4.0" }, @@ -930,9 +930,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-google": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.5.tgz", - "integrity": "sha512-KNrzfUsoFat94slWzo36g601sIGz6KtE4kBMM0gpqwFLK/MXRyaW65IL4SwysY0PEhuRzg9spLLMnUXuVcY2hQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.8.tgz", + "integrity": "sha512-BnMHgcEeaLyloPmBs8phCqprI+4r2Jb8rni011A8hE+7FNk7FmLE3kiwxLFrcZnnb7eqM0agW4zUaNoB0P+z8A==", "dev": true, "license": "MIT" }, @@ -1041,9 +1041,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.22", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.22.tgz", - "integrity": "sha512-fZBTn8QHr8pAv1/I14CmdDWpVkovCfYpSYiGfV1SZkOjrsKLzPxsP84eaP3RijbFtYj3GMplVN27FR3H5oHfiw==", + "version": "5.1.24", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.24.tgz", + "integrity": "sha512-yAyyHetElLR236sqWQkBtiLbzCGexV5zzLMHyQPptKQQK88BTQR5f9wXW2EtSgJw/4gUchpSWQWxMlkIfK/iQQ==", "dev": true, "license": "MIT" }, @@ -1062,20 +1062,20 @@ "license": "MIT" }, "node_modules/@cspell/dict-public-licenses": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.12.tgz", - "integrity": "sha512-obreJMVbz8ZrXyc60PcS/B2FwXaO3AWPO2x50zrI/n4UDuBr/UdPb6M1q++6c08n+151I35GEx52xRFiToSg4g==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.13.tgz", + "integrity": "sha512-1Wdp/XH1ieim7CadXYE7YLnUlW0pULEjVl9WEeziZw3EKCAw8ZI8Ih44m4bEa5VNBLnuP5TfqC4iDautAleQzQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.14.tgz", - "integrity": "sha512-NZ/rsTH5gqTlEwbSg0vn5b1TsyzrUvA6ykwCVCwsVDdlQAS82cyDsF9JqHp8S4d6PFykmkfSxtAXYyOUr0KCbg==", + "version": "4.2.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.15.tgz", + "integrity": "sha512-VNXhj0Eh+hdHN89MgyaoSAexBQKmYtJaMhucbMI7XmBs4pf8fuFFN3xugk51/A4TZJr8+RImdFFsGMOw+I4bDA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-data-science": "^2.0.6" + "@cspell/dict-data-science": "^2.0.7" } }, "node_modules/@cspell/dict-r": { @@ -1114,9 +1114,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.2.tgz", - "integrity": "sha512-cgteXRzx2W/Ug7QSdFJrVxLES7krrZEjZ9J6sXRWOsVYFpgu2Gup8NKmjKOZ8NTnCjHQFrMnbmKdv56q9Kwixw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.4.tgz", + "integrity": "sha512-GRkuaFfjFHPYynyRMuisKyE3gRiVK0REClRWfnH9+5iCs5TKDURsMpWJGNsgQ6N5jAKKrtWXVKjepkDHjMldjQ==", "dev": true, "license": "MIT" }, @@ -1163,13 +1163,13 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.2.tgz", - "integrity": "sha512-n3AVbyBlTn/pLtYK62mqgDfJIuQHUTY/k8SMUCjyjfgoqd3LcKhS1PmbLfDWPMTODK30cSMMTLejjy2bL6ksEw==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.3.tgz", + "integrity": "sha512-Kg6IJhGHPv+9OxpxaXUpcqgnHEOhMLRWHLyx7FADZ+CJyO4AVeWQfhpTRM6KXhzIl7dPlLG1g8JAQxaoy88KTw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.2", + "@cspell/url": "8.17.3", "import-meta-resolve": "^4.1.0" }, "engines": { @@ -1177,9 +1177,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.2.tgz", - "integrity": "sha512-2B+dB4Ls2xiOjg+vEEbAuJTHtMfXSihVzfLGnj9+qUfq47iqrz4ZBvCOfZhYdiVaaZJoZUgIw8ljrUfqFzYDAg==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.3.tgz", + "integrity": "sha512-UFqRmJPccOSo+RYP/jZ4cr0s7ni37GrvnNAg1H/qIIxfmBYsexTAmsNzMqxp1M31NeI1Cx3LL7PspPMT0ms+7w==", "dev": true, "license": "MIT", "engines": { @@ -1187,9 +1187,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.2.tgz", - "integrity": "sha512-LbbhdVwtqyJ71X+O7e2PqpDp7zLiY8jmW2CJFLjZYWTUawgav2bpwECGq6O9Gnwqe+fj7yWxGJFDSpXQcCJQAw==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.3.tgz", + "integrity": "sha512-l/CaFc3CITI/dC+whEBZ05Om0KXR3V2whhVOWOBPIqA5lCjWAyvWWvmFD+CxWd0Hs6Qcb/YDnMyJW14aioXN4g==", "dev": true, "license": "MIT", "engines": { @@ -1197,9 +1197,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.2.tgz", - "integrity": "sha512-yy4eYWNX2iutXmy4Igbn/hL/NYaNt94DylohPtgVr0Zxnn/AAArt9Bv1KXPpjB8VFy2wzzPzWmZ+MWDUVpHCbg==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.3.tgz", + "integrity": "sha512-gcsCz8g0qY94C8RXiAlUH/89n84Q9RSptP91XrvnLOT+Xva9Aibd7ywd5k9ameuf8Nagyl0ezB1MInZ30S9SRw==", "dev": true, "license": "MIT", "engines": { @@ -1591,9 +1591,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", - "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", + "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2584,9 +2584,9 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.13.0.tgz", - "integrity": "sha512-RnO1SaiCFHn666wNz2QfZEFxvmiNRqhzaMXHXxXXKt+MEP7aajlPxUSMIQpKAaJfverpovEYqjBOXDq6dDcaOQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-3.0.1.tgz", + "integrity": "sha512-rQ3tcT5N2cynofJfbjUsnL4seoewTaOVBLyUEwtNldo7iNMPo3h/GUQk+Cl3iHEWwRxjq2wuH6q0FufQrbVL1A==", "dev": true, "license": "MIT", "dependencies": { @@ -2786,9 +2786,9 @@ } }, "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "dev": true, "license": "MIT" }, @@ -3078,9 +3078,9 @@ } }, "node_modules/ansis": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.9.0.tgz", - "integrity": "sha512-PcDrVe15ldexeZMsVLBAzBwF2KhZgaU0R+CHxH+x5kqn/pO+UWVBZJ+NEXMPpEOLUFeNsnNdoWYc2gwO+MVkDg==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.10.0.tgz", + "integrity": "sha512-hxDKLYT7hy3Y4sF3HxI926A3urzPxi73mZBB629m9bCVF+NyKNxbwCqqm+C/YrGPtxLwnl6d8/ZASCsz6SyvJA==", "license": "ISC", "engines": { "node": ">=16" @@ -4250,9 +4250,9 @@ } }, "node_modules/commander": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.0.0.tgz", - "integrity": "sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", "dev": true, "license": "MIT", "engines": { @@ -4448,25 +4448,25 @@ } }, "node_modules/cspell": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.2.tgz", - "integrity": "sha512-y+INkxDa+M9f+gsyyMLjKh1tF20r2g5Gn22peSRJglrNLQtmDuRtDT9vyDHANXZcH5g6pHDnENQu/+P2Tiyu8Q==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.3.tgz", + "integrity": "sha512-fBZg674Dir9y/FWMwm2JyixM/1eB2vnqHJjRxOgGS/ZiZ3QdQ3LkK02Aqvlni8ffWYDZnYnYY9rfWmql9bb42w==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.17.2", - "@cspell/cspell-pipe": "8.17.2", - "@cspell/cspell-types": "8.17.2", - "@cspell/dynamic-import": "8.17.2", - "@cspell/url": "8.17.2", + "@cspell/cspell-json-reporter": "8.17.3", + "@cspell/cspell-pipe": "8.17.3", + "@cspell/cspell-types": "8.17.3", + "@cspell/dynamic-import": "8.17.3", + "@cspell/url": "8.17.3", "chalk": "^5.4.1", "chalk-template": "^1.1.0", - "commander": "^13.0.0", - "cspell-dictionary": "8.17.2", - "cspell-gitignore": "8.17.2", - "cspell-glob": "8.17.2", - "cspell-io": "8.17.2", - "cspell-lib": "8.17.2", + "commander": "^13.1.0", + "cspell-dictionary": "8.17.3", + "cspell-gitignore": "8.17.3", + "cspell-glob": "8.17.3", + "cspell-io": "8.17.3", + "cspell-lib": "8.17.3", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", @@ -4485,13 +4485,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.2.tgz", - "integrity": "sha512-g08lRd/smLk2je0j7HlCjdDa0dSTyI2oRP3gScWlsyXjb4NSr9qO0Wzyn5BfPgrqFdS/z4dXbHe+tnLQZCt9iQ==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.3.tgz", + "integrity": "sha512-+N32Q6xck3D2RqZIFwq8s0TnzHYMpyh4bgNtYqW5DIP3TLDiA4/MJGjwmLKAg/s9dkre6n8/++vVli3MZAOhIg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.17.2", + "@cspell/cspell-types": "8.17.3", "comment-json": "^4.2.5", "yaml": "^2.7.0" }, @@ -4500,15 +4500,15 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.2.tgz", - "integrity": "sha512-2JC9RRsZruCs3AHId/8X63fSxDoF94dleRp8y/dXS9LIX7NruofohUJwzc/3tlgzCWWdaek1RXhO5xaYX74QtA==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.3.tgz", + "integrity": "sha512-89I/lpQKdkX17RCFrUIJnc70Rjfpup/o+ynHZen0hUxGTfLsEJPrK6H2oGvic3Yrv5q8IOtwM1p8vqPqBkBheA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.2", - "@cspell/cspell-types": "8.17.2", - "cspell-trie-lib": "8.17.2", + "@cspell/cspell-pipe": "8.17.3", + "@cspell/cspell-types": "8.17.3", + "cspell-trie-lib": "8.17.3", "fast-equals": "^5.2.2" }, "engines": { @@ -4516,15 +4516,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.2.tgz", - "integrity": "sha512-zCTTN30zV96LkZmUDrLamEHpLLUGohKglKJ4iXoHQC8pDU3xTsV2qzeCQjM9SEmU3VbE1TzWq+vj0fslasv6pA==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.3.tgz", + "integrity": "sha512-rQamjb8R+Nwib/Bpcgf+xv5IdsOHgbP+fe4hCgv0jjgUPkeOR2c4dGwc0WS+2UkJbc+wQohpzBGDLRYGSB/hQw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.2", - "cspell-glob": "8.17.2", - "cspell-io": "8.17.2", + "@cspell/url": "8.17.3", + "cspell-glob": "8.17.3", + "cspell-io": "8.17.3", "find-up-simple": "^1.0.0" }, "bin": { @@ -4535,13 +4535,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.2.tgz", - "integrity": "sha512-MTgrWX12oY8Pq/M3PEYCTHwD6w6l+DPtBWm958nhR4dboUbwi/3KfqCtdorkhnuClqLDQuuZHp0uGBXB4cdQrw==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.3.tgz", + "integrity": "sha512-0ov9A0E6OuOO7KOxlGCxJ09LR/ubZ6xcGwWc5bu+jp/8onUowQfe+9vZdznj/o8/vcf5JkDzyhRSBsdhWKqoAg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.2", + "@cspell/url": "8.17.3", "micromatch": "^4.0.8" }, "engines": { @@ -4549,14 +4549,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.2.tgz", - "integrity": "sha512-Asg5XRvrg2yHCvBwzARBPSwI4P5/unN+bKBlxqFazHgR72WJE+ASeobfUNfGi/RxJA2+m0hO91oYtvq6LfK52w==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.3.tgz", + "integrity": "sha512-wfjkkvHthnKJtEaTgx3cPUPquGRXfgXSCwvMJaDyUi36KBlopXX38PejBTdmuqrvp7bINLSuHErml9wAfL5Fxw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.2", - "@cspell/cspell-types": "8.17.2" + "@cspell/cspell-pipe": "8.17.3", + "@cspell/cspell-types": "8.17.3" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4566,42 +4566,42 @@ } }, "node_modules/cspell-io": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.2.tgz", - "integrity": "sha512-IUdhbO6gsWYiM2dgudFJQTfnFCDYjLOqal3SxH5o8oOWeu5iIZ+s3N8E1odz0L5zF2Go7zDQSKvPr7Y9OOoRfw==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.3.tgz", + "integrity": "sha512-NwEVb3Kr8loV1C8Stz9QSMgUrBkxqf2s7A9H2/RBnfvQBt9CWZS6NgoNxTPwHj3h1sUNl9reDkMQQzkKtgWGBQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.17.2", - "@cspell/url": "8.17.2" + "@cspell/cspell-service-bus": "8.17.3", + "@cspell/url": "8.17.3" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.2.tgz", - "integrity": "sha512-ZgkTvGh9FO+R3v5TaTqlrJEylWyZhNOzbtrQ5W35Hb3tZ9IJJklxjlcGe+gbFsjGi56kLj6c5L2NR7YX/Fdu5Q==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.3.tgz", + "integrity": "sha512-KpwYIj8HwFyTzCCQcyezlmomvyNfPwZQmqTh4V126sFvf9HLoMdfyq8KYDZmZ//4HzwrF/ufJOF3CpuVUiJHfA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.17.2", - "@cspell/cspell-pipe": "8.17.2", - "@cspell/cspell-resolver": "8.17.2", - "@cspell/cspell-types": "8.17.2", - "@cspell/dynamic-import": "8.17.2", - "@cspell/filetypes": "8.17.2", - "@cspell/strong-weak-map": "8.17.2", - "@cspell/url": "8.17.2", + "@cspell/cspell-bundled-dicts": "8.17.3", + "@cspell/cspell-pipe": "8.17.3", + "@cspell/cspell-resolver": "8.17.3", + "@cspell/cspell-types": "8.17.3", + "@cspell/dynamic-import": "8.17.3", + "@cspell/filetypes": "8.17.3", + "@cspell/strong-weak-map": "8.17.3", + "@cspell/url": "8.17.3", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.17.2", - "cspell-dictionary": "8.17.2", - "cspell-glob": "8.17.2", - "cspell-grammar": "8.17.2", - "cspell-io": "8.17.2", - "cspell-trie-lib": "8.17.2", + "cspell-config-lib": "8.17.3", + "cspell-dictionary": "8.17.3", + "cspell-glob": "8.17.3", + "cspell-grammar": "8.17.3", + "cspell-io": "8.17.3", + "cspell-trie-lib": "8.17.3", "env-paths": "^3.0.0", "fast-equals": "^5.2.2", "gensequence": "^7.0.0", @@ -4616,14 +4616,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.17.2", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.2.tgz", - "integrity": "sha512-Bw9q8EWFihkQGo8fNdfkUqYOTsC161+wrQxR7m74K4bKEmQgm0mS0sLHKUwxEOZVGGLmIw9dMQl+8WnTgqOaMQ==", + "version": "8.17.3", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.3.tgz", + "integrity": "sha512-6LE5BeT2Rwv0bkQckpxX0K1fnFCWfeJ8zVPFtYOaix0trtqj0VNuwWzYDnxyW+OwMioCH29yRAMODa+JDFfUrA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.2", - "@cspell/cspell-types": "8.17.2", + "@cspell/cspell-pipe": "8.17.3", + "@cspell/cspell-types": "8.17.3", "gensequence": "^7.0.0" }, "engines": { @@ -5154,9 +5154,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "32.2.8", - "resolved": "https://registry.npmjs.org/electron/-/electron-32.2.8.tgz", - "integrity": "sha512-jaAgBeFKjH6Cd7CnG7XhApZtLz2ewUXLyf1rKh9D+eaFD5XCYQpH77PhmrT5u0IpSP6eSZoHpAQ0sMqOFsh6kA==", + "version": "32.3.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-32.3.0.tgz", + "integrity": "sha512-CyX6K1INQdlgTePmP3wuAueUi5ePqw0IpiGOyyzULGU9gBQI3idwW6apR3W/R1cES2j1gWLrkty3cD40qRV9sg==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5598,9 +5598,9 @@ } }, "node_modules/eslint": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", - "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", + "version": "9.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", + "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -5608,7 +5608,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.18.0", + "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5656,6 +5656,25 @@ } } }, + "node_modules/eslint-fix-utils": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/eslint-fix-utils/-/eslint-fix-utils-0.2.1.tgz", + "integrity": "sha512-vHvLGmqdgPhZgH+cymlAlAqVuV22auB+uk/mgFdg5zotEtMHAHcOzNzhr5XOrDzyKGEQY2uQHoT+tS8P36/2CQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.3.0" + }, + "peerDependencies": { + "@types/estree": ">=1", + "eslint": ">=8" + }, + "peerDependenciesMeta": { + "@types/estree": { + "optional": true + } + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -5785,9 +5804,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.10.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.10.0.tgz", - "integrity": "sha512-hyMWUxkBH99HpXT3p8hc7REbEZK3D+nk8vHXGgpB+XXsi0gO4PxMSP+pjfUzb67GnV9yawV9a53eUmcde1CCZA==", + "version": "28.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.11.0.tgz", + "integrity": "sha512-QAfipLcNCWLVocVbZW8GimKn5p5iiMcgGbRzz8z/P5q7xw+cNEpYqyzFMtIF/ZgF2HLOyy+dYBut+DoYolvqig==", "dev": true, "license": "MIT", "dependencies": { @@ -5811,9 +5830,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.1.tgz", - "integrity": "sha512-UWyaYi6iURdSfdVVqvfOs2vdCVz0J40O/z/HTsv2sFjdjmdlUI/qlKLOTmwbPQ2tAfQnE5F9vqx+B+poF71DBQ==", + "version": "50.6.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.3.tgz", + "integrity": "sha512-NxbJyt1M5zffPcYZ8Nb53/8nnbIScmiLAMdoe0/FAszwb7lcSiX3iYBTsuF7RV84dZZJC8r3NghomrUXsmWvxQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5837,16 +5856,17 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.19.0.tgz", - "integrity": "sha512-L1RCeuEcZHrOC2KJqRctgHrndLufICo4VSHNZEnGEF7PkZXWZrxUBc17I5Cdolarlk+5kIW9IJ+zettXUuELHg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.21.1.tgz", + "integrity": "sha512-nrZyddyLGRxYLBhND17b+IAZYcDJqcOu12Bk/HvGKmWKp36ja/oz7+1YL597/p3mNVhww2SVF8jA9syqYWvgNA==", "dev": true, "license": "MIT", "dependencies": { "@altano/repository-tools": "^0.1.1", "detect-indent": "6.1.0", "detect-newline": "3.1.0", - "package-json-validator": "^0.7.0", + "eslint-fix-utils": "^0.2.0", + "package-json-validator": "^0.8.0", "semver": "^7.5.4", "sort-object-keys": "^1.1.3", "sort-package-json": "^2.12.0", @@ -8943,9 +8963,9 @@ "license": "MIT" }, "node_modules/katex": { - "version": "0.16.20", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.20.tgz", - "integrity": "sha512-jjuLaMGD/7P8jUTpdKhA9IoqnH+yMFB3sdAFtq5QdAqeP2PjiSbnC3EaguKPNtv6dXXanHxp1ckwvF4a86LBig==", + "version": "0.16.21", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz", + "integrity": "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==", "dev": true, "funding": [ "https://opencollective.com/katex", @@ -9077,22 +9097,22 @@ } }, "node_modules/lint-staged": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.3.0.tgz", - "integrity": "sha512-vHFahytLoF2enJklgtOtCtIjZrKD/LoxlaUusd5nh7dWv/dkKQJY74ndFSzxCdv7g0ueGg1ORgTSt4Y9LPZn9A==", + "version": "15.4.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.3.tgz", + "integrity": "sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "~5.4.1", - "commander": "~12.1.0", - "debug": "~4.4.0", - "execa": "~8.0.1", - "lilconfig": "~3.1.3", - "listr2": "~8.2.5", - "micromatch": "~4.0.8", - "pidtree": "~0.6.0", - "string-argv": "~0.3.2", - "yaml": "~2.6.1" + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -9117,16 +9137,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/lint-staged/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/lint-staged/node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -9271,19 +9281,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/listr2": { "version": "8.2.5", "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", @@ -9519,9 +9516,9 @@ } }, "node_modules/markdownlint": { - "version": "0.37.3", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.37.3.tgz", - "integrity": "sha512-eoQqH0291YCCjd+Pe1PUQ9AmWthlVmS0XWgcionkZ8q34ceZyRI+pYvsWksXJJL8OBkWCPwp1h/pnXxrPFC4oA==", + "version": "0.37.4", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.37.4.tgz", + "integrity": "sha512-u00joA/syf3VhWh6/ybVFkib5Zpj2e5KB/cfCei8fkSRuums6nyisTWGqjTWIOFoFwuXoTBQQiqlB4qFKp8ncQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9543,16 +9540,16 @@ } }, "node_modules/markdownlint-cli2": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.17.1.tgz", - "integrity": "sha512-n1Im9lhKJJE12/u2N0GWBwPqeb0HGdylN8XpSFg9hbj35+QalY9Vi6mxwUQdG6wlSrrIq9ZDQ0Q85AQG9V2WOg==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.17.2.tgz", + "integrity": "sha512-XH06ZOi8wCrtOSSj3p8y3yJzwgzYOSa7lglNyS3fP05JPRzRGyjauBb5UvlLUSCGysMmULS1moxdRHHudV+g/Q==", "dev": true, "license": "MIT", "dependencies": { "globby": "14.0.2", "js-yaml": "4.1.0", "jsonc-parser": "3.3.1", - "markdownlint": "0.37.3", + "markdownlint": "0.37.4", "markdownlint-cli2-formatter-default": "0.0.5", "micromatch": "4.0.8" }, @@ -10163,9 +10160,9 @@ } }, "node_modules/micromark-util-subtokenize": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.3.tgz", - "integrity": "sha512-VXJJuNxYWSoYL6AJ6OQECCFGhIU2GGHMw8tahogePBrjkG8aCCas3ibkp7RnVOSTClg2is05/R7maAhF1XyQMg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.4.tgz", + "integrity": "sha512-N6hXjrin2GTJDe3MVjf5FuXpm12PGm80BrUAeub9XFXca8JZbP+oIwY4LJSVwFUCL1IPm/WwSVUN7goFHmSGGQ==", "dev": true, "funding": [ { @@ -10860,16 +10857,16 @@ } }, "node_modules/package-json-validator": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.7.3.tgz", - "integrity": "sha512-QWUV5rMxLe/QNMJ1t+/xYC8xY15lcAfcsKE/JAqTUt0KKhvO0idz4ZQdXvhLzz2Rf3KcEtaI5ZxsvgOrKIYRuA==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.8.0.tgz", + "integrity": "sha512-Tkk4C4gQLSfSOwJLAGvJ1VGq1UN8SFzJszkPOqQXu0aMiZPHZ0iteAc30Ui6cgcdBwY5Z5kKCkLVd8RSJLzGsA==", "dev": true, "license": "MIT", "dependencies": { "yargs": "~17.7.2" }, "bin": { - "pjv": "bin/pjv" + "pjv": "lib/bin/pjv.mjs" }, "engines": { "node": ">=18" @@ -11176,13 +11173,13 @@ } }, "node_modules/playwright": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", - "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", + "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.1" + "playwright-core": "1.50.1" }, "bin": { "playwright": "cli.js" @@ -11195,9 +11192,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", - "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", + "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -11386,9 +11383,9 @@ } }, "node_modules/postcss": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.0.tgz", - "integrity": "sha512-27VKOqrYfPncKA2NrFOVhP5MGAfHKLYn/Q0mz9cNQyRAKYi3VNHwYU2qKKqPCqgBmeeJ0uAFB56NumXZ5ZReXg==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", "dev": true, "funding": [ { @@ -13082,9 +13079,9 @@ } }, "node_modules/stylelint": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.13.1.tgz", - "integrity": "sha512-691JjSIIcP6f9QJFz0J0/AMG3lupE9RqYAgYCON3wiqp5nQiKqDYIsz321GeTOYNznoRPNh0Mf6VjzP1eBVz/Q==", + "version": "16.14.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.14.1.tgz", + "integrity": "sha512-oqCL7AC3786oTax35T/nuLL8p2C3k/8rHKAooezrPGRvUX0wX+qqs5kMWh5YYT4PHQgVDobHT4tw55WgpYG6Sw==", "dev": true, "funding": [ { @@ -13116,7 +13113,7 @@ "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", - "ignore": "^7.0.1", + "ignore": "^7.0.3", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", "known-css-properties": "^0.35.0", @@ -13125,7 +13122,7 @@ "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", - "postcss": "^8.4.49", + "postcss": "^8.5.1", "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.0.0", @@ -13194,9 +13191,9 @@ } }, "node_modules/stylelint-prettier": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.2.tgz", - "integrity": "sha512-qJ+BN+1T2ZcKz9WIrv0x+eFGHzSUnXfXd5gL///T6XoJvr3D8/ztzz2fhtmXef7Vb8P33zBXmLTTveByr0nwBw==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.3.tgz", + "integrity": "sha512-B6V0oa35ekRrKZlf+6+jA+i50C4GXJ7X1PPmoCqSUoXN6BrNF6NhqqhanvkLjqw2qgvrS0wjdpeC+Tn06KN3jw==", "dev": true, "license": "MIT", "dependencies": { @@ -13278,9 +13275,9 @@ } }, "node_modules/stylelint/node_modules/ignore": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.1.tgz", - "integrity": "sha512-D1gVletsbVOoiXF963rgZnfobGAbq7Lb+dz3fcBmlOmZg6hHkpbycLqL8PLNB8f4GVv6dOVYwhPL/r7hwiH0Fw==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", + "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", "dev": true, "license": "MIT", "engines": { @@ -13914,9 +13911,9 @@ } }, "node_modules/undici": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.2.1.tgz", - "integrity": "sha512-U2k0XHLJfaciARRxDcqTk2AZQsGXerHzdvfCZcy1hNhSf5KCAF4jIQQxL+apQviOekhRFPqED6Of5/+LcUSLzQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.3.0.tgz", + "integrity": "sha512-Qy96NND4Dou5jKoSJ2gm8ax8AJM/Ey9o9mz7KN1bb9GP+G0l20Zw8afxTnY2f4b7hmhn/z8aC2kfArVQlAhFBw==", "license": "MIT", "engines": { "node": ">=20.18.1" diff --git a/package.json b/package.json index f7086dd663..d836e7330f 100644 --- a/package.json +++ b/package.json @@ -63,10 +63,10 @@ }, "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.9.0", + "ansis": "^3.10.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.18.0", + "eslint": "^9.19.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -80,30 +80,30 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.2.1" + "undici": "^7.3.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.13.0", - "cspell": "^8.17.2", + "@stylistic/eslint-plugin": "^3.0.1", + "cspell": "^8.17.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^28.10.0", - "eslint-plugin-jsdoc": "^50.6.1", - "eslint-plugin-package-json": "^0.19.0", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-jsdoc": "^50.6.3", + "eslint-plugin-package-json": "^0.21.1", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^26.0.0", - "lint-staged": "^15.3.0", - "markdownlint-cli2": "^0.17.1", - "playwright": "^1.49.1", + "lint-staged": "^15.4.3", + "markdownlint-cli2": "^0.17.2", + "playwright": "^1.50.1", "prettier": "^3.4.2", "sinon": "^19.0.2", - "stylelint": "^16.13.1", + "stylelint": "^16.14.1", "stylelint-config-standard": "^37.0.0", - "stylelint-prettier": "^5.0.2" + "stylelint-prettier": "^5.0.3" }, "optionalDependencies": { - "electron": "^32.2.8" + "electron": "^32.3.0" }, "engines": { "node": ">=20.18.1 <21 || >=22" diff --git a/vendor/package-lock.json b/vendor/package-lock.json index fa4bf8a861..cde3c2c620 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -13,7 +13,7 @@ "animate.css": "^4.1.1", "croner": "^9.0.0", "moment": "^2.30.1", - "moment-timezone": "^0.5.46", + "moment-timezone": "^0.5.47", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" @@ -74,9 +74,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.46", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz", - "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==", + "version": "0.5.47", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.47.tgz", + "integrity": "sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==", "license": "MIT", "dependencies": { "moment": "^2.29.4" diff --git a/vendor/package.json b/vendor/package.json index e4afe0bc09..138be86b23 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -15,7 +15,7 @@ "animate.css": "^4.1.1", "croner": "^9.0.0", "moment": "^2.30.1", - "moment-timezone": "^0.5.46", + "moment-timezone": "^0.5.47", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" From 62c22d785c03fd163058148c6fd7662f38ff13b5 Mon Sep 17 00:00:00 2001 From: DevIncomin <56730075+Developer-Incoming@users.noreply.github.com> Date: Thu, 6 Feb 2025 12:00:41 +0300 Subject: [PATCH 191/418] Arabic Translation (#3719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hello and thank you for wanting to contribute to the MagicMirror² project! **Please make sure that you have followed these 4 rules before submitting your Pull Request:** > 1. Base your pull requests against the `develop` branch. > 2. Include these infos in the description: > > - Does the pull request solve a **related** issue? > - If so, can you reference the issue like this `Fixes #`? > - What does the pull request accomplish? Use a list if needed. > - If it includes major visual changes please add screenshots. > > 3. Please run `npm run lint:prettier` before submitting so that > style issues are fixed. > 4. Don't forget to add an entry about your changes to > the CHANGELOG.md file. **Note**: Sometimes the development moves very fast. It is highly recommended that you update your branch of `develop` before creating a pull request to send us your changes. This makes everyone's lives easier (including yours) and helps us out on the development team. Thanks again and have a nice day! --- CHANGELOG.md | 2 ++ translations/ar.json | 48 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 translations/ar.json diff --git a/CHANGELOG.md b/CHANGELOG.md index de08f18f44..5572806419 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ planned for 2025-04-01 ### Added +- Added Arabic translation. + ### Changed - [core] starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) (#3677) diff --git a/translations/ar.json b/translations/ar.json new file mode 100644 index 0000000000..968d253283 --- /dev/null +++ b/translations/ar.json @@ -0,0 +1,48 @@ +{ + "LOADING": "جار التحميل …", + + "YESTERDAY": "أمس", + "TODAY": "اليوم", + "TOMORROW": "غدًا", + "RUNNING": "ينتهي خلال", + "EMPTY": "لا توجد أحداث قادمة.", + "WEEK": "الأسبوع {weekNumber}", + + "N": "شمال", + "NNE": "شمال شمال شرقي", + "NE": "شمال شرقي", + "ENE": "شرق شمال شرقي", + "E": "شرق", + "ESE": "شرق جنوب شرقي", + "SE": "جنوب شرقي", + "SSE": "جنوب جنوب شرقي", + "S": "جنوب", + "SSW": "جنوب جنوب غربي", + "SW": "جنوب غربي", + "WSW": "غرب جنوب غربي", + "W": "غرب", + "WNW": "غرب شمال غربي", + "NW": "شمال غربي", + "NNW": "شمال شمال غربي", + + "FEELS": "كأنها {DEGREE}", + "PRECIP_POP": "احتمالية الهطول", + "PRECIP_AMOUNT": "كمية الهطول", + + "MODULE_CONFIG_CHANGED": "تم تغيير خيارات التهيئة لوحدة {MODULE_NAME}.\nيرجى مراجعة الوثائق.", + "MODULE_CONFIG_ERROR": "خطأ في وحدة {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "رابط غير صحيح.", + "MODULE_ERROR_NO_CONNECTION": "لا يوجد اتصال بالإنترنت.", + "MODULE_ERROR_UNAUTHORIZED": "فشل التصريح.", + "MODULE_ERROR_UNSPECIFIED": "تحقق من السجلات لمزيد من التفاصيل.", + + "NEWSFEED_NO_ITEMS": "لا توجد أخبار في الوقت الحالي.", + + "UPDATE_NOTIFICATION": "تحديث MagicMirror² متاح.", + "UPDATE_NOTIFICATION_MODULE": "تحديث متاح لوحدة {MODULE_NAME}.", + "UPDATE_INFO_SINGLE": "التثبيت الحالي متخلف عن تحديث واحد على فرع {BRANCH_NAME}.", + "UPDATE_INFO_MULTIPLE": "التثبيت الحالي متخلف عن {COMMIT_COUNT} تحديثات على فرع {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "تم التحديث لوحدة {MODULE_NAME}", + "UPDATE_NOTIFICATION_ERROR": "حدث خطأ أثناء تحديث وحدة {MODULE_NAME}", + "UPDATE_NOTIFICATION_NEED-RESTART": "يتطلب إعادة تشغيل MagicMirror." +} From 28bcee7de6bee1ddb687632c6f8f49a591a41fbd Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 22 Feb 2025 19:12:01 +0100 Subject: [PATCH 192/418] Update ESLint and simplify config (#3724) This does not change the rules of ESLint. It's just a little cosmetic fine-tuning. --- CHANGELOG.md | 3 +- eslint.config.mjs | 14 +- package-lock.json | 447 +++++++++++++++++++++++----------------------- package.json | 10 +- 4 files changed, 235 insertions(+), 239 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5572806419..d25406149a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ planned for 2025-04-01 ### Updated - [core] Update dependencies and formatting (#3693, #3717) +- [core] Update ESLint and simplify config ### Fixed @@ -40,7 +41,7 @@ planned for 2025-04-01 - [weather] Fix wrong weatherCondition name in openmeteo provider which lead to n/a icon (#3691) - [core] Fix wrong port in log message when starting server only (#3696) - [calendar] Fix NewYork event processed on system in Central timezone shows wrong time #3701 -- [weather/yr] The Yr weather provider is now able to recover from bad API resposes instead of freezing (#3296) +- [weather/yr] The Yr weather provider is now able to recover from bad API responses instead of freezing (#3296) ## [2.30.0] - 2025-01-01 diff --git a/eslint.config.mjs b/eslint.config.mjs index c6bd2be9c1..75ea30e0ec 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -6,9 +6,11 @@ import eslintPluginStylistic from "@stylistic/eslint-plugin"; import globals from "globals"; const config = [ - eslintPluginJs.configs.recommended, eslintPluginImport.flatConfigs.recommended, + eslintPluginJest.configs["flat/recommended"], + eslintPluginJs.configs.recommended, eslintPluginPackageJson, + eslintPluginStylistic.configs.all, { files: ["**/*.js"], languageOptions: { @@ -24,13 +26,7 @@ const config = [ moment: "readonly" } }, - plugins: { - ...eslintPluginStylistic.configs["all-flat"].plugins, - ...eslintPluginJest.configs["flat/recommended"].plugins - }, rules: { - ...eslintPluginStylistic.configs["all-flat"].rules, - ...eslintPluginJest.configs["flat/recommended"].rules, "@stylistic/array-element-newline": ["error", "consistent"], "@stylistic/arrow-parens": ["error", "always"], "@stylistic/brace-style": "off", @@ -99,11 +95,7 @@ const config = [ }, sourceType: "module" }, - plugins: { - ...eslintPluginStylistic.configs["all-flat"].plugins - }, rules: { - ...eslintPluginStylistic.configs["all-flat"].rules, "@stylistic/array-element-newline": "off", "@stylistic/indent": ["error", "tab"], "@stylistic/padded-blocks": ["error", "never"], diff --git a/package-lock.json b/package-lock.json index 8ca103da0b..52982c1e1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "ansis": "^3.10.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.19.0", + "eslint": "^9.21.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -31,12 +31,12 @@ "undici": "^7.3.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^3.0.1", + "@stylistic/eslint-plugin": "^4.0.1", "cspell": "^8.17.3", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-jsdoc": "^50.6.3", - "eslint-plugin-package-json": "^0.21.1", + "eslint-plugin-package-json": "^0.26.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", @@ -619,9 +619,9 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.3.tgz", - "integrity": "sha512-6uOF726o3JnExAUKM20OJJXZo+Qf9Jt64nkVwnVXx7Upqr5I9Pb1npYPEAIpUA03SnWYmKwUIqhAmkwrN+bLPA==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.5.tgz", + "integrity": "sha512-b/Ntabar+g4gsRNwOct909cvatO/auHhNvBzJZfyFQzryI1nqHMaSFuDsrrtzbhQkGJ4GiMAKCXZC2EOdHMgmw==", "dev": true, "license": "MIT", "dependencies": { @@ -629,8 +629,8 @@ "@cspell/dict-al": "^1.1.0", "@cspell/dict-aws": "^4.0.9", "@cspell/dict-bash": "^4.2.0", - "@cspell/dict-companies": "^3.1.13", - "@cspell/dict-cpp": "^6.0.3", + "@cspell/dict-companies": "^3.1.14", + "@cspell/dict-cpp": "^6.0.4", "@cspell/dict-cryptocurrencies": "^5.0.4", "@cspell/dict-csharp": "^4.0.6", "@cspell/dict-css": "^4.0.17", @@ -640,14 +640,14 @@ "@cspell/dict-docker": "^1.1.12", "@cspell/dict-dotnet": "^5.0.9", "@cspell/dict-elixir": "^4.0.7", - "@cspell/dict-en_us": "^4.3.30", + "@cspell/dict-en_us": "^4.3.33", "@cspell/dict-en-common-misspellings": "^2.0.9", "@cspell/dict-en-gb": "1.1.33", - "@cspell/dict-filetypes": "^3.0.10", + "@cspell/dict-filetypes": "^3.0.11", "@cspell/dict-flutter": "^1.1.0", "@cspell/dict-fonts": "^4.0.4", "@cspell/dict-fsharp": "^1.1.0", - "@cspell/dict-fullstack": "^3.2.3", + "@cspell/dict-fullstack": "^3.2.5", "@cspell/dict-gaming-terms": "^1.1.0", "@cspell/dict-git": "^3.0.4", "@cspell/dict-golang": "^6.0.18", @@ -666,7 +666,7 @@ "@cspell/dict-markdown": "^2.0.9", "@cspell/dict-monkeyc": "^1.0.10", "@cspell/dict-node": "^5.0.6", - "@cspell/dict-npm": "^5.1.24", + "@cspell/dict-npm": "^5.1.27", "@cspell/dict-php": "^4.0.14", "@cspell/dict-powershell": "^5.0.14", "@cspell/dict-public-licenses": "^2.0.13", @@ -676,7 +676,7 @@ "@cspell/dict-rust": "^4.0.11", "@cspell/dict-scala": "^5.0.7", "@cspell/dict-shell": "^1.1.0", - "@cspell/dict-software-terms": "^4.2.4", + "@cspell/dict-software-terms": "^4.2.5", "@cspell/dict-sql": "^2.2.0", "@cspell/dict-svelte": "^1.0.6", "@cspell/dict-swift": "^2.0.5", @@ -689,22 +689,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.3.tgz", - "integrity": "sha512-RWSfyHOin/d9CqLjz00JMvPkag3yUSsQZr6G9BnCT5cMEO/ws8wQZzA54CNj/LAOccbknTX65SSroPPAtxs56w==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.5.tgz", + "integrity": "sha512-+eVFCdnda74Frv8hguHYwDtxvqDuJJ/luFRl4dC5oknPMRab0JCHM1DDYjp3NzsehTex0HmcxplxqVW6QoDosg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.17.3" + "@cspell/cspell-types": "8.17.5" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.3.tgz", - "integrity": "sha512-DqqSWKt9NLWPGloYxZTpzUhgdW8ObMkZmOOF6TyqpJ4IbckEct8ULgskNorTNRlmmjLniaNgvg6JSHuYO3Urxw==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.5.tgz", + "integrity": "sha512-VOIfFdIo3FYQFcSpIyGkqHupOx0LgfBrWs79IKnTT1II27VUHPF+0oGq0WWf4c2Zpd8tzdHvS3IUhGarWZq69g==", "dev": true, "license": "MIT", "engines": { @@ -712,9 +712,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.3.tgz", - "integrity": "sha512-yQlVaIsWiax6RRuuacZs++kl6Y9rwH9ZkVlsG9fhdeCJ5Xf3WCW+vmX1chzhhKDzRr8CF9fsvb1uagd/5/bBYA==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.5.tgz", + "integrity": "sha512-5MhYInligPbGctWxoklAKxtg+sxvtJCuRKGSQHHA0JlCOLSsducypl780P6zvpjLK59XmdfC+wtFONxSmRbsuA==", "dev": true, "license": "MIT", "dependencies": { @@ -725,9 +725,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.3.tgz", - "integrity": "sha512-CC3nob/Kbuesz5WTW+LjAHnDFXJrA49pW5ckmbufJxNnoAk7EJez/qr7/ELMTf6Fl3A5xZ776Lhq7738Hy/fmQ==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.5.tgz", + "integrity": "sha512-Ur3IK0R92G/2J6roopG9cU/EhoYAMOx2um7KYlq93cdrly8RBAK2NCcGCL7DbjQB6C9RYEAV60ueMUnQ45RrCQ==", "dev": true, "license": "MIT", "engines": { @@ -735,9 +735,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.3.tgz", - "integrity": "sha512-ozgeuSioX9z2wtlargfgdw3LKwDFAfm8gxu+xwNREvXiLsevb+lb7ZlY5/ay+MahqR5Hfs7XzYzBLTKL/ldn9g==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.5.tgz", + "integrity": "sha512-91y2+0teunRSRZj940ORDA3kdjyenrUiM+4j6nQQH24sAIAJdRmQl2LG3eUTmeaSReJGkZIpnToQ6DyU5cC88Q==", "dev": true, "license": "MIT", "engines": { @@ -776,16 +776,16 @@ } }, "node_modules/@cspell/dict-companies": { - "version": "3.1.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.13.tgz", - "integrity": "sha512-EAaFMxnSG4eQKup9D81EnWAYIzorLWG7b7Zzf+Suu0bVeFBpCYESss/EWtnmb5ZZNfKAGxtoMqfL3vRfyJERIQ==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.14.tgz", + "integrity": "sha512-iqo1Ce4L7h0l0GFSicm2wCLtfuymwkvgFGhmu9UHyuIcTbdFkDErH+m6lH3Ed+QuskJlpQ9dM7puMIGqUlVERw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.3.tgz", - "integrity": "sha512-OFrVXdxCeGKnon36Pe3yFjBuY4kzzEwWFf3vDz+cJTodZDkjFkBifQeTtt5YfimgF8cfAJZXkBCsxjipAgmAiw==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.4.tgz", + "integrity": "sha512-IvXx3TlM+OL0CFriapk7ZHmeY89dSSdo/BZ3DGf+WUS+BWd64H+z/xr3xkkqY0Eu6MV/vdzNfkLm5zl45FDMGg==", "dev": true, "license": "MIT" }, @@ -853,9 +853,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.30", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.30.tgz", - "integrity": "sha512-p0G5fByj5fUnMyFUlkN3kaqE3nuQkqpYV47Gn9n8k2TszsdLY55xj9UoFE4YIcjOiyU1bR/YDJ5daiPMYXTJ/A==", + "version": "4.3.33", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.33.tgz", + "integrity": "sha512-HniqQjzPVn24NEkHooBIw1cH+iO3AKMA9oDTwazUYQP1/ldqXsz6ce4+fdHia2nqypmic/lHVkQgIVhP48q/sA==", "dev": true, "license": "MIT" }, @@ -874,9 +874,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.10.tgz", - "integrity": "sha512-JEN3627joBVtpa1yfkdN9vz1Z129PoKGHBKjXCEziJvf2Zt1LeULWYYYg/O6pzRR4yzRa5YbXDTuyrN7vX7DFg==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.11.tgz", + "integrity": "sha512-bBtCHZLo7MiSRUqx5KEiPdGOmXIlDGY+L7SJEtRWZENpAKE+96rT7hj+TUUYWBbCzheqHr0OXZJFEKDgsG/uZg==", "dev": true, "license": "MIT" }, @@ -902,9 +902,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-fullstack": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.3.tgz", - "integrity": "sha512-62PbndIyQPH11mAv0PyiyT0vbwD0AXEocPpHlCHzfb5v9SspzCCbzQ/LIBiFmyRa+q5LMW35CnSVu6OXdT+LKg==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.5.tgz", + "integrity": "sha512-XNmNdovPUS9Vc2JvfBscy8zZfwyxR11sB4fxU2lXh7LzUvOn2/OkKAzj41JTdiWfVnJ/yvsRkspe+b7kr+DIQw==", "dev": true, "license": "MIT" }, @@ -1041,9 +1041,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.24", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.24.tgz", - "integrity": "sha512-yAyyHetElLR236sqWQkBtiLbzCGexV5zzLMHyQPptKQQK88BTQR5f9wXW2EtSgJw/4gUchpSWQWxMlkIfK/iQQ==", + "version": "5.1.27", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.27.tgz", + "integrity": "sha512-LGss1yrjhxSmxL4VfMC+UBDMVHfqHudgC7b39M74EVys+nNC4/lqDHacb6Aw7i6aUn9mzdNIkdTTD+LdDcHvPA==", "dev": true, "license": "MIT" }, @@ -1114,9 +1114,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.4.tgz", - "integrity": "sha512-GRkuaFfjFHPYynyRMuisKyE3gRiVK0REClRWfnH9+5iCs5TKDURsMpWJGNsgQ6N5jAKKrtWXVKjepkDHjMldjQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.5.tgz", + "integrity": "sha512-CaRzkWti3AgcXoxuRcMijaNG7YUk/MH1rHjB8VX34v3UdCxXXeqvRyElRKnxhFeVLB/robb2UdShqh/CpskxRg==", "dev": true, "license": "MIT" }, @@ -1163,13 +1163,13 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.3.tgz", - "integrity": "sha512-Kg6IJhGHPv+9OxpxaXUpcqgnHEOhMLRWHLyx7FADZ+CJyO4AVeWQfhpTRM6KXhzIl7dPlLG1g8JAQxaoy88KTw==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.5.tgz", + "integrity": "sha512-tY+cVkRou+0VKvH+K1NXv8/R7mOlW3BDGSs9fcgvhatj0m00Yf8blFC7tE4VVI9Qh2bkC/KDFqM24IqZbuwXUQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.3", + "@cspell/url": "8.17.5", "import-meta-resolve": "^4.1.0" }, "engines": { @@ -1177,9 +1177,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.3.tgz", - "integrity": "sha512-UFqRmJPccOSo+RYP/jZ4cr0s7ni37GrvnNAg1H/qIIxfmBYsexTAmsNzMqxp1M31NeI1Cx3LL7PspPMT0ms+7w==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.5.tgz", + "integrity": "sha512-Fj6py2Rl+FEnMiXhRQUM1A5QmyeCLxi6dY/vQ0qfH6tp6KSaBiaC8wuPUKhr8hKyTd3+8lkUbobDhUf6xtMEXg==", "dev": true, "license": "MIT", "engines": { @@ -1187,9 +1187,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.3.tgz", - "integrity": "sha512-l/CaFc3CITI/dC+whEBZ05Om0KXR3V2whhVOWOBPIqA5lCjWAyvWWvmFD+CxWd0Hs6Qcb/YDnMyJW14aioXN4g==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.5.tgz", + "integrity": "sha512-Z4eo+rZJr1086wZWycBiIG/n7gGvVoqn28I7ZicS8xedRYu/4yp2loHgLn4NpxG3e46+dNWs4La6vinod+UydQ==", "dev": true, "license": "MIT", "engines": { @@ -1197,9 +1197,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.3.tgz", - "integrity": "sha512-gcsCz8g0qY94C8RXiAlUH/89n84Q9RSptP91XrvnLOT+Xva9Aibd7ywd5k9ameuf8Nagyl0ezB1MInZ30S9SRw==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.5.tgz", + "integrity": "sha512-GNQqST7zI85dAFVyao6oiTeg5rNhO9FH1ZAd397qQhvwfxrrniNfuoewu8gPXyP0R4XBiiaCwhBL7w9S/F5guw==", "dev": true, "license": "MIT", "engines": { @@ -1476,12 +1476,12 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", - "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.5", + "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -1512,9 +1512,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -1524,9 +1524,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", + "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -1591,30 +1591,30 @@ } }, "node_modules/@eslint/js": { - "version": "9.19.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz", - "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==", + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", + "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", - "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", - "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.10.0", + "@eslint/core": "^0.12.0", "levn": "^0.4.1" }, "engines": { @@ -1670,9 +1670,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -2584,13 +2584,13 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-3.0.1.tgz", - "integrity": "sha512-rQ3tcT5N2cynofJfbjUsnL4seoewTaOVBLyUEwtNldo7iNMPo3h/GUQk+Cl3iHEWwRxjq2wuH6q0FufQrbVL1A==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.0.1.tgz", + "integrity": "sha512-RwKkRKiDrF4ptiur54ckDhOByQYKYZ1dEmI5K8BJCmuGpauFJXzVL1UQYTA2zq702CqMFdYiJcVFJWfokIgFxw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.13.0", + "@typescript-eslint/utils": "^8.23.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "estraverse": "^5.3.0", @@ -2600,7 +2600,7 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": ">=8.40.0" + "eslint": ">=9.0.0" } }, "node_modules/@szmarczak/http-timer": { @@ -2853,14 +2853,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.20.0.tgz", - "integrity": "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw==", + "version": "8.24.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.1.tgz", + "integrity": "sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0" + "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/visitor-keys": "8.24.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2871,9 +2871,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", - "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", + "version": "8.24.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.1.tgz", + "integrity": "sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==", "dev": true, "license": "MIT", "engines": { @@ -2885,20 +2885,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.20.0.tgz", - "integrity": "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA==", + "version": "8.24.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.1.tgz", + "integrity": "sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/visitor-keys": "8.20.0", + "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/visitor-keys": "8.24.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2912,16 +2912,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.20.0.tgz", - "integrity": "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA==", + "version": "8.24.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.1.tgz", + "integrity": "sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.20.0", - "@typescript-eslint/types": "8.20.0", - "@typescript-eslint/typescript-estree": "8.20.0" + "@typescript-eslint/scope-manager": "8.24.1", + "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/typescript-estree": "8.24.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2936,13 +2936,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.20.0.tgz", - "integrity": "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA==", + "version": "8.24.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.1.tgz", + "integrity": "sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.20.0", + "@typescript-eslint/types": "8.24.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -4448,30 +4448,30 @@ } }, "node_modules/cspell": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.3.tgz", - "integrity": "sha512-fBZg674Dir9y/FWMwm2JyixM/1eB2vnqHJjRxOgGS/ZiZ3QdQ3LkK02Aqvlni8ffWYDZnYnYY9rfWmql9bb42w==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.5.tgz", + "integrity": "sha512-l3Cfp87d7Yrodem675irdxV6+7+OsdR+jNwYHe33Dgnd6ePEfooYrvmfGdXF9rlQrNLUQp/HqYgHJzSq19UEsg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.17.3", - "@cspell/cspell-pipe": "8.17.3", - "@cspell/cspell-types": "8.17.3", - "@cspell/dynamic-import": "8.17.3", - "@cspell/url": "8.17.3", + "@cspell/cspell-json-reporter": "8.17.5", + "@cspell/cspell-pipe": "8.17.5", + "@cspell/cspell-types": "8.17.5", + "@cspell/dynamic-import": "8.17.5", + "@cspell/url": "8.17.5", "chalk": "^5.4.1", "chalk-template": "^1.1.0", "commander": "^13.1.0", - "cspell-dictionary": "8.17.3", - "cspell-gitignore": "8.17.3", - "cspell-glob": "8.17.3", - "cspell-io": "8.17.3", - "cspell-lib": "8.17.3", + "cspell-dictionary": "8.17.5", + "cspell-gitignore": "8.17.5", + "cspell-glob": "8.17.5", + "cspell-io": "8.17.5", + "cspell-lib": "8.17.5", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", - "semver": "^7.6.3", - "tinyglobby": "^0.2.10" + "semver": "^7.7.1", + "tinyglobby": "^0.2.12" }, "bin": { "cspell": "bin.mjs", @@ -4485,13 +4485,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.3.tgz", - "integrity": "sha512-+N32Q6xck3D2RqZIFwq8s0TnzHYMpyh4bgNtYqW5DIP3TLDiA4/MJGjwmLKAg/s9dkre6n8/++vVli3MZAOhIg==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.5.tgz", + "integrity": "sha512-XDc+UJO5RZ9S9e2Ajz332XjT7dv6Og2UqCiSnAlvHt7t/MacLHSPARZFIivheObNkWZ7E1iWI681RxKoH4o40w==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.17.3", + "@cspell/cspell-types": "8.17.5", "comment-json": "^4.2.5", "yaml": "^2.7.0" }, @@ -4500,15 +4500,15 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.3.tgz", - "integrity": "sha512-89I/lpQKdkX17RCFrUIJnc70Rjfpup/o+ynHZen0hUxGTfLsEJPrK6H2oGvic3Yrv5q8IOtwM1p8vqPqBkBheA==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.5.tgz", + "integrity": "sha512-O/Uuhv1RuDu+5WYQml0surudweaTvr+2YJSmPSdlihByUSiogCbpGqwrRow7wQv/C5p1W1FlFjotvUfoR0fxHA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.3", - "@cspell/cspell-types": "8.17.3", - "cspell-trie-lib": "8.17.3", + "@cspell/cspell-pipe": "8.17.5", + "@cspell/cspell-types": "8.17.5", + "cspell-trie-lib": "8.17.5", "fast-equals": "^5.2.2" }, "engines": { @@ -4516,15 +4516,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.3.tgz", - "integrity": "sha512-rQamjb8R+Nwib/Bpcgf+xv5IdsOHgbP+fe4hCgv0jjgUPkeOR2c4dGwc0WS+2UkJbc+wQohpzBGDLRYGSB/hQw==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.5.tgz", + "integrity": "sha512-I27fgOUZzH14jeIYo65LooB60fZ42f6OJL1lOR9Mk6IrIlDyUtzherGR+xx5KshK2katYkX42Qu4zsVYM6VFPA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.3", - "cspell-glob": "8.17.3", - "cspell-io": "8.17.3", + "@cspell/url": "8.17.5", + "cspell-glob": "8.17.5", + "cspell-io": "8.17.5", "find-up-simple": "^1.0.0" }, "bin": { @@ -4535,13 +4535,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.3.tgz", - "integrity": "sha512-0ov9A0E6OuOO7KOxlGCxJ09LR/ubZ6xcGwWc5bu+jp/8onUowQfe+9vZdznj/o8/vcf5JkDzyhRSBsdhWKqoAg==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.5.tgz", + "integrity": "sha512-OXquou7UykInlGV5et5lNKYYrW0dwa28aEF995x1ocANND7o0bbHmFlbgyci/Lp4uFQai8sifmfFJbuIg2IC/A==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.3", + "@cspell/url": "8.17.5", "micromatch": "^4.0.8" }, "engines": { @@ -4549,14 +4549,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.3.tgz", - "integrity": "sha512-wfjkkvHthnKJtEaTgx3cPUPquGRXfgXSCwvMJaDyUi36KBlopXX38PejBTdmuqrvp7bINLSuHErml9wAfL5Fxw==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.5.tgz", + "integrity": "sha512-st2n+FVw25MvMbsGb3TeJNRr6Oih4g14rjOd/UJN0qn+ceH360SAShUFqSd4kHHu2ADazI/TESFU6FRtMTPNOg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.3", - "@cspell/cspell-types": "8.17.3" + "@cspell/cspell-pipe": "8.17.5", + "@cspell/cspell-types": "8.17.5" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4566,49 +4566,49 @@ } }, "node_modules/cspell-io": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.3.tgz", - "integrity": "sha512-NwEVb3Kr8loV1C8Stz9QSMgUrBkxqf2s7A9H2/RBnfvQBt9CWZS6NgoNxTPwHj3h1sUNl9reDkMQQzkKtgWGBQ==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.5.tgz", + "integrity": "sha512-oevM/8l0s6nc1NCYPqNFumrW50QSHoa6wqUT8cWs09gtZdE2AWG0U6bIE8ZEVz6e6FxS+6IenGKTdUUwP0+3fg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.17.3", - "@cspell/url": "8.17.3" + "@cspell/cspell-service-bus": "8.17.5", + "@cspell/url": "8.17.5" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.3.tgz", - "integrity": "sha512-KpwYIj8HwFyTzCCQcyezlmomvyNfPwZQmqTh4V126sFvf9HLoMdfyq8KYDZmZ//4HzwrF/ufJOF3CpuVUiJHfA==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.5.tgz", + "integrity": "sha512-S3KuOrcST1d2BYmTXA+hnbRdho5n3w5GUvEaCx3QZQBwAPfLpAwJbe2yig1TxBpyEJ5LqP02i/mDg1pUCOP0hQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.17.3", - "@cspell/cspell-pipe": "8.17.3", - "@cspell/cspell-resolver": "8.17.3", - "@cspell/cspell-types": "8.17.3", - "@cspell/dynamic-import": "8.17.3", - "@cspell/filetypes": "8.17.3", - "@cspell/strong-weak-map": "8.17.3", - "@cspell/url": "8.17.3", + "@cspell/cspell-bundled-dicts": "8.17.5", + "@cspell/cspell-pipe": "8.17.5", + "@cspell/cspell-resolver": "8.17.5", + "@cspell/cspell-types": "8.17.5", + "@cspell/dynamic-import": "8.17.5", + "@cspell/filetypes": "8.17.5", + "@cspell/strong-weak-map": "8.17.5", + "@cspell/url": "8.17.5", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.17.3", - "cspell-dictionary": "8.17.3", - "cspell-glob": "8.17.3", - "cspell-grammar": "8.17.3", - "cspell-io": "8.17.3", - "cspell-trie-lib": "8.17.3", + "cspell-config-lib": "8.17.5", + "cspell-dictionary": "8.17.5", + "cspell-glob": "8.17.5", + "cspell-grammar": "8.17.5", + "cspell-io": "8.17.5", + "cspell-trie-lib": "8.17.5", "env-paths": "^3.0.0", "fast-equals": "^5.2.2", "gensequence": "^7.0.0", - "import-fresh": "^3.3.0", + "import-fresh": "^3.3.1", "resolve-from": "^5.0.0", "vscode-languageserver-textdocument": "^1.0.12", - "vscode-uri": "^3.0.8", + "vscode-uri": "^3.1.0", "xdg-basedir": "^5.1.0" }, "engines": { @@ -4616,14 +4616,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.17.3", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.3.tgz", - "integrity": "sha512-6LE5BeT2Rwv0bkQckpxX0K1fnFCWfeJ8zVPFtYOaix0trtqj0VNuwWzYDnxyW+OwMioCH29yRAMODa+JDFfUrA==", + "version": "8.17.5", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.5.tgz", + "integrity": "sha512-9hjI3nRQxtGEua6CgnLbK3sGHLx9dXR/BHwI/csRL4dN5GGRkE5X3CCoy1RJVL7iGFLIzi43+L10xeFRmWniKw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.3", - "@cspell/cspell-types": "8.17.3", + "@cspell/cspell-pipe": "8.17.5", + "@cspell/cspell-types": "8.17.5", "gensequence": "^7.0.0" }, "engines": { @@ -5598,21 +5598,21 @@ } }, "node_modules/eslint": { - "version": "9.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", - "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", + "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.10.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.19.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/config-array": "^0.19.2", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.0", + "@eslint/js": "9.21.0", + "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -5856,9 +5856,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.21.1.tgz", - "integrity": "sha512-nrZyddyLGRxYLBhND17b+IAZYcDJqcOu12Bk/HvGKmWKp36ja/oz7+1YL597/p3mNVhww2SVF8jA9syqYWvgNA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.26.0.tgz", + "integrity": "sha512-plYuuP7RyL532yHLPvKtQNzK6ncXRmzWPji5EUlV0tXhhfFc84TDWiwJ+OYvv4pDA9AfV+gKYVUwhojaDameNw==", "dev": true, "license": "MIT", "dependencies": { @@ -5866,7 +5866,7 @@ "detect-indent": "6.1.0", "detect-newline": "3.1.0", "eslint-fix-utils": "^0.2.0", - "package-json-validator": "^0.8.0", + "package-json-validator": "^0.10.0", "semver": "^7.5.4", "sort-object-keys": "^1.1.3", "sort-package-json": "^2.12.0", @@ -6384,9 +6384,9 @@ } }, "node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -7413,9 +7413,9 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "license": "MIT", "dependencies": { "parent-module": "^1.0.0", @@ -10857,9 +10857,9 @@ } }, "node_modules/package-json-validator": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.8.0.tgz", - "integrity": "sha512-Tkk4C4gQLSfSOwJLAGvJ1VGq1UN8SFzJszkPOqQXu0aMiZPHZ0iteAc30Ui6cgcdBwY5Z5kKCkLVd8RSJLzGsA==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.10.0.tgz", + "integrity": "sha512-zaPt4x0ZIxA4KYWpPMkbOEhkEDfQdtkCCC1xhnbnYrQV+Kry3zMAxENujgdT6aPA5BJ+FfpncKoNULWc/qjloQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11476,9 +11476,9 @@ } }, "node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", + "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", "dev": true, "license": "MIT", "bin": { @@ -12225,9 +12225,9 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -13565,17 +13565,20 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", - "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.2", + "fdir": "^6.4.3", "picomatch": "^4.0.2" }, "engines": { "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tldts": { @@ -13653,9 +13656,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", "dev": true, "license": "MIT", "engines": { @@ -14098,9 +14101,9 @@ "license": "MIT" }, "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index d836e7330f..7e612610e9 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier", "install-vendor": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix", - "lint:js": "eslint . --fix", + "lint:js": "eslint --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", "postinstall": "npm run install-vendor && npm run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"", @@ -50,7 +50,7 @@ "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json", "test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit", "test:electron": "NODE_ENV=test jest --selectProjects electron -i --forceExit", - "test:js": "eslint .", + "test:js": "eslint", "test:markdown": "markdownlint-cli2 .", "test:prettier": "prettier . --check", "test:spelling": "cspell . --gitignore", @@ -66,7 +66,7 @@ "ansis": "^3.10.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.19.0", + "eslint": "^9.21.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -83,12 +83,12 @@ "undici": "^7.3.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^3.0.1", + "@stylistic/eslint-plugin": "^4.0.1", "cspell": "^8.17.3", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-jsdoc": "^50.6.3", - "eslint-plugin-package-json": "^0.21.1", + "eslint-plugin-package-json": "^0.26.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", From 4a398f03eb43c781e19037ad7314797681c6d763 Mon Sep 17 00:00:00 2001 From: Veeck Date: Thu, 27 Feb 2025 19:31:00 +0100 Subject: [PATCH 193/418] Fix empty part-of-day logic (#3726) Fixes #3727 --------- Co-authored-by: veeck --- CHANGELOG.md | 1 + modules/default/compliments/compliments.js | 17 +++++++++----- package-lock.json | 22 +++++++++---------- package.json | 8 +++---- .../compliments/compliments_evening.js | 22 +++++++++++++++++++ tests/electron/helpers/global-setup.js | 6 ++--- tests/electron/modules/compliments_spec.js | 11 +++++++--- 7 files changed, 60 insertions(+), 27 deletions(-) create mode 100644 tests/configs/modules/compliments/compliments_evening.js diff --git a/CHANGELOG.md b/CHANGELOG.md index d25406149a..7ecf856309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ planned for 2025-04-01 - [core] Fix wrong port in log message when starting server only (#3696) - [calendar] Fix NewYork event processed on system in Central timezone shows wrong time #3701 - [weather/yr] The Yr weather provider is now able to recover from bad API responses instead of freezing (#3296) +- [compliments] Fix evening events being shown during the day (#3727) ## [2.30.0] - 2025-01-01 diff --git a/modules/default/compliments/compliments.js b/modules/default/compliments/compliments.js index b7dc1295b0..8bfcd1332d 100644 --- a/modules/default/compliments/compliments.js +++ b/modules/default/compliments/compliments.js @@ -139,12 +139,17 @@ Module.register("compliments", { let compliments = []; // Add time of day compliments - if (hour >= this.config.morningStartTime && hour < this.config.morningEndTime && this.config.compliments.hasOwnProperty("morning")) { - compliments = [...this.config.compliments.morning]; - } else if (hour >= this.config.afternoonStartTime && hour < this.config.afternoonEndTime && this.config.compliments.hasOwnProperty("afternoon")) { - compliments = [...this.config.compliments.afternoon]; - } else if (this.config.compliments.hasOwnProperty("evening")) { - compliments = [...this.config.compliments.evening]; + let timeOfDay; + if (hour >= this.config.morningStartTime && hour < this.config.morningEndTime) { + timeOfDay = "morning"; + } else if (hour >= this.config.afternoonStartTime && hour < this.config.afternoonEndTime) { + timeOfDay = "afternoon"; + } else { + timeOfDay = "evening"; + } + + if (timeOfDay && this.config.compliments.hasOwnProperty(timeOfDay)) { + compliments = [...this.config.compliments[timeOfDay]]; } // Add compliments based on weather diff --git a/package-lock.json b/package-lock.json index 52982c1e1a..cb0c82cd83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.10.0", + "ansis": "^3.16.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^9.21.0", @@ -31,8 +31,8 @@ "undici": "^7.3.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^4.0.1", - "cspell": "^8.17.3", + "@stylistic/eslint-plugin": "^4.1.0", + "cspell": "^8.17.5", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-jsdoc": "^50.6.3", @@ -44,7 +44,7 @@ "lint-staged": "^15.4.3", "markdownlint-cli2": "^0.17.2", "playwright": "^1.50.1", - "prettier": "^3.4.2", + "prettier": "^3.5.2", "sinon": "^19.0.2", "stylelint": "^16.14.1", "stylelint-config-standard": "^37.0.0", @@ -2584,9 +2584,9 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.0.1.tgz", - "integrity": "sha512-RwKkRKiDrF4ptiur54ckDhOByQYKYZ1dEmI5K8BJCmuGpauFJXzVL1UQYTA2zq702CqMFdYiJcVFJWfokIgFxw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.1.0.tgz", + "integrity": "sha512-bytbL7qiici7yPyEiId0fGPK9kjQbzcPMj2aftPfzTCyJ/CRSKdtI+iVjM0LSGzGxfunflI+MDDU9vyIIeIpoQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3078,12 +3078,12 @@ } }, "node_modules/ansis": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.10.0.tgz", - "integrity": "sha512-hxDKLYT7hy3Y4sF3HxI926A3urzPxi73mZBB629m9bCVF+NyKNxbwCqqm+C/YrGPtxLwnl6d8/ZASCsz6SyvJA==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.16.0.tgz", + "integrity": "sha512-sU7d/tfZiYrsIAXbdL/CNZld5bCkruzwT5KmqmadCJYxuLxHAOBjidxD5+iLmN/6xEfjcQq1l7OpsiCBlc4LzA==", "license": "ISC", "engines": { - "node": ">=16" + "node": ">=14" } }, "node_modules/anymatch": { diff --git a/package.json b/package.json index 7e612610e9..4f7f0803bb 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ }, "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.10.0", + "ansis": "^3.16.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^9.21.0", @@ -83,8 +83,8 @@ "undici": "^7.3.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^4.0.1", - "cspell": "^8.17.3", + "@stylistic/eslint-plugin": "^4.1.0", + "cspell": "^8.17.5", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-jsdoc": "^50.6.3", @@ -96,7 +96,7 @@ "lint-staged": "^15.4.3", "markdownlint-cli2": "^0.17.2", "playwright": "^1.50.1", - "prettier": "^3.4.2", + "prettier": "^3.5.2", "sinon": "^19.0.2", "stylelint": "^16.14.1", "stylelint-config-standard": "^37.0.0", diff --git a/tests/configs/modules/compliments/compliments_evening.js b/tests/configs/modules/compliments/compliments_evening.js new file mode 100644 index 0000000000..d7bf2242f2 --- /dev/null +++ b/tests/configs/modules/compliments/compliments_evening.js @@ -0,0 +1,22 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 12, + + modules: [ + { + module: "compliments", + position: "middle_center", + config: { + compliments: { + evening: ["Evening here"] + } + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/electron/helpers/global-setup.js b/tests/electron/helpers/global-setup.js index b95ad5217d..9e96fc36c0 100644 --- a/tests/electron/helpers/global-setup.js +++ b/tests/electron/helpers/global-setup.js @@ -49,10 +49,10 @@ exports.stopApplication = async () => { process.env.MOCK_DATE = undefined; }; -exports.getElement = async (selector) => { +exports.getElement = async (selector, state = "visible") => { expect(global.page).not.toBeNull(); - let elem = global.page.locator(selector); - await elem.waitFor(); + const elem = global.page.locator(selector); + await elem.waitFor({ state: state }); expect(elem).not.toBeNull(); return elem; }; diff --git a/tests/electron/modules/compliments_spec.js b/tests/electron/modules/compliments_spec.js index 4555ffcbf7..1cb23914fd 100644 --- a/tests/electron/modules/compliments_spec.js +++ b/tests/electron/modules/compliments_spec.js @@ -7,9 +7,9 @@ describe("Compliments module", () => { * @param {Array} complimentsArray The array of compliments. * @returns {boolean} result */ - const doTest = async (complimentsArray) => { - await helpers.getElement(".compliments"); - const elem = await helpers.getElement(".module-content"); + const doTest = async (complimentsArray, state = "visible") => { + await helpers.getElement(".compliments", state); + const elem = await helpers.getElement(".module-content", state); expect(elem).not.toBeNull(); expect(complimentsArray).toContain(await elem.textContent()); return true; @@ -34,6 +34,11 @@ describe("Compliments module", () => { await helpers.startApplication("tests/configs/modules/compliments/compliments_parts_day.js", "01 Oct 2022 20:00:00 GMT"); await expect(doTest(["Hello There", "Good Evening", "Evening test"])).resolves.toBe(true); }); + + it("doesnt show evening compliments during the day when the other parts of day are not set", async () => { + await helpers.startApplication("tests/configs/modules/compliments/compliments_evening.js", "01 Oct 2022 08:00:00 GMT"); + await expect(doTest([""], "attached")).resolves.toBe(true); + }); }); describe("Feature date in compliments module", () => { From 66b86565958272493e11db4f62b778a6f81ad5ad Mon Sep 17 00:00:00 2001 From: Nathan Date: Sat, 1 Mar 2025 02:34:02 -0700 Subject: [PATCH 194/418] Fix icons, add hourly support, add other weatherflow changes (#3729) I have updated weatherflow.js to implement the following changes (as described in #3728) - Fixed: Weather icons now show up properly - Added: Location Name support - Added: Hourly weather forecast support - Added to current conditions: - "Feels like" temp - Fixed icon for current conditions to be sourced from current conditions (rather than daily forecast) - UV index - Added to daily forecast - Precipitation amount and UV index (via hourly forecast data) Before: ![image](https://github.com/user-attachments/assets/cfef043c-75ef-4571-8bdc-462e75d3ed81) After: ![image](https://github.com/user-attachments/assets/e36118bb-a508-4ab1-a7ad-a775bd7a9bb3) --- CHANGELOG.md | 1 + .../default/weather/providers/weatherflow.js | 85 ++++++++++++++++++- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ecf856309..a584e3a199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ planned for 2025-04-01 - [core] Add issue templates for feature requests and bug reports (#3695) - [core] Adapt `start:x11:dev` script - [weather/yr] The Yr weather provider now enforces a minimum `updateInterval` of 600 000 ms (10 minutes) to comply with the terms of service. If a lower value is set, it will be automatically increased to this minimum. +- [weather/weatherflow] Fixed icons and added hourly support as well as UV, precipitation, and location name support. - [workflow] Run `sudo apt-get update` before installing packages to avoid install errors ### Removed diff --git a/modules/default/weather/providers/weatherflow.js b/modules/default/weather/providers/weatherflow.js index 6ffd5b669b..ae8d43dc6c 100644 --- a/modules/default/weather/providers/weatherflow.js +++ b/modules/default/weather/providers/weatherflow.js @@ -25,14 +25,20 @@ WeatherProvider.register("weatherflow", { const currentWeather = new WeatherObject(); currentWeather.date = moment(); + // Other available values: air_density, brightness, delta_t, dew_point, + // pressure_trend (i.e. rising/falling), sea_level_pressure, wind gust, and more. + currentWeather.humidity = data.current_conditions.relative_humidity; currentWeather.temperature = data.current_conditions.air_temperature; + currentWeather.feelsLikeTemp = data.current_conditions.feels_like; currentWeather.windSpeed = WeatherUtils.convertWindToMs(data.current_conditions.wind_avg); currentWeather.windFromDirection = data.current_conditions.wind_direction; - currentWeather.weatherType = data.forecast.daily[0].icon; + currentWeather.weatherType = this.convertWeatherType(data.current_conditions.icon); + currentWeather.uv_index = data.current_conditions.uv; currentWeather.sunrise = moment.unix(data.forecast.daily[0].sunrise); currentWeather.sunset = moment.unix(data.forecast.daily[0].sunset); this.setCurrentWeather(currentWeather); + this.fetchedLocationName = data.location_name; }) .catch(function (request) { Log.error("Could not load data ... ", request); @@ -52,13 +58,27 @@ WeatherProvider.register("weatherflow", { weather.minTemperature = forecast.air_temp_low; weather.maxTemperature = forecast.air_temp_high; weather.precipitationProbability = forecast.precip_probability; - weather.weatherType = forecast.icon; - weather.snow = 0; + weather.weatherType = this.convertWeatherType(forecast.icon); + + // Must manually build UV and Precipitation from hourly + weather.precipitationAmount = 0.0; // This will sum up rain and snow + weather.precipitationUnits = "mm"; + weather.uv_index = 0; + for (const hour of data.forecast.hourly) { + const hour_time = moment.unix(hour.time); + if (hour_time.day() === weather.date.day()) { // Iterate though until day is reached + // Get data from today + weather.uv_index = Math.max(weather.uv_index, hour.uv); + weather.precipitationAmount += (hour.precip ?? 0); + } else if (hour_time.diff(weather.date) >= 86400) { + break; // No more data to be found + } + } days.push(weather); } - this.setWeatherForecast(days); + this.fetchedLocationName = data.location_name; }) .catch(function (request) { Log.error("Could not load data ... ", request); @@ -66,6 +86,63 @@ WeatherProvider.register("weatherflow", { .finally(() => this.updateAvailable()); }, + fetchWeatherHourly () { + this.fetchData(this.getUrl()) + .then((data) => { + const hours = []; + for (const hour of data.forecast.hourly) { + const weather = new WeatherObject(); + + weather.date = moment.unix(hour.time); + weather.temperature = hour.air_temperature; + weather.feelsLikeTemp = hour.feels_like; + weather.humidity = hour.relative_humidity; + weather.windSpeed = hour.wind_avg; + weather.windFromDirection = hour.wind_direction; + weather.weatherType = this.convertWeatherType(hour.icon); + weather.precipitationProbability = hour.precip_probability; + weather.precipitationAmount = hour.precip; // NOTE: precipitation type is available + weather.precipitationUnits = "mm"; // Hardcoded via request, TODO: Add conversion + weather.uv_index = hour.uv; + + hours.push(weather); + if (hours.length >= 48) break; // 10 days of hours are available, best to trim down. + } + this.setWeatherHourly(hours); + this.fetchedLocationName = data.location_name; + }) + .catch(function (request) { + Log.error("Could not load data ... ", request); + }) + .finally(() => this.updateAvailable()); + }, + + convertWeatherType (weatherType) { + const weatherTypes = { + "clear-day": "day-sunny", + "clear-night": "night-clear", + cloudy: "cloudy", + foggy: "fog", + "partly-cloudy-day": "day-cloudy", + "partly-cloudy-night": "night-alt-cloudy", + "possibly-rainy-day": "day-rain", + "possibly-rainy-night": "night-alt-rain", + "possibly-sleet-day": "day-sleet", + "possibly-sleet-night": "night-alt-sleet", + "possibly-snow-day": "day-snow", + "possibly-snow-night": "night-alt-snow", + "possibly-thunderstorm-day": "day-thunderstorm", + "possibly-thunderstorm-night": "night-alt-thunderstorm", + rainy: "rain", + sleet: "sleet", + snow: "snow", + thunderstorm: "thunderstorm", + windy: "strong-wind" + }; + + return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; + }, + // Create a URL from the config and base URL. getUrl () { return `${this.config.apiBase}better_forecast?station_id=${this.config.stationid}&units_temp=c&units_wind=kph&units_pressure=mb&units_precip=mm&units_distance=km&token=${this.config.token}`; From 1fcc028e49ffc74bad7af5fd1ac66641634891bb Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 5 Mar 2025 12:28:25 +0100 Subject: [PATCH 195/418] update dependencies incl. electron to v35 (#3733) --- CHANGELOG.md | 2 +- fonts/package-lock.json | 18 +- fonts/package.json | 4 +- package-lock.json | 627 ++++++++++++++++++++-------------------- package.json | 6 +- 5 files changed, 335 insertions(+), 322 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a584e3a199..e6655233df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ planned for 2025-04-01 ### Updated -- [core] Update dependencies and formatting (#3693, #3717) +- [core] Update dependencies incl. electron to v35 and formatting (#3593, #3693, #3717) - [core] Update ESLint and simplify config ### Fixed diff --git a/fonts/package-lock.json b/fonts/package-lock.json index 96614a92b2..084c98099e 100644 --- a/fonts/package-lock.json +++ b/fonts/package-lock.json @@ -9,19 +9,21 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.1.1", - "@fontsource/roboto-condensed": "^5.1.1" + "@fontsource/roboto": "^5.2.0", + "@fontsource/roboto-condensed": "^5.2.0" } }, "node_modules/@fontsource/roboto": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.1.1.tgz", - "integrity": "sha512-XwVVXtERDQIM7HPUIbyDe0FP4SRovpjF7zMI8M7pbqFp3ahLJsJTd18h+E6pkar6UbV3btbwkKjYARr5M+SQow==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.0.tgz", + "integrity": "sha512-RgDVfXtRZlMRBkzcVMETP0m5Xy8VaKAEnqTD2NFe34B6Qc2Xvn01Hxu3mdrF2My0YM0n4Iae5XWM7yzEsm4OZg==", + "license": "OFL-1.1" }, "node_modules/@fontsource/roboto-condensed": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.1.1.tgz", - "integrity": "sha512-0SYkGnWPsvyCI3TAqBYAglfVUqVu/fsdgsyl5u396oK8ZgyamWHdQMFHDqCWrb4H4hNiewJT1l2ShDCA/cu6Ug==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.2.0.tgz", + "integrity": "sha512-j4e8QCvz4J14nVYONSZI8X7M9uiMH8vxt3DT37IendV8FTtSvwvvok1oTpRXrWT0YHQ0mUTbl2XUmBsCTiX4Lg==", + "license": "OFL-1.1" } } } diff --git a/fonts/package.json b/fonts/package.json index f10f3088bb..fe497bc160 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.1.1", - "@fontsource/roboto-condensed": "^5.1.1" + "@fontsource/roboto": "^5.2.0", + "@fontsource/roboto-condensed": "^5.2.0" } } diff --git a/package-lock.json b/package-lock.json index cb0c82cd83..520836a1a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.3.0" + "undici": "^7.4.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.1.0", @@ -46,7 +46,7 @@ "playwright": "^1.50.1", "prettier": "^3.5.2", "sinon": "^19.0.2", - "stylelint": "^16.14.1", + "stylelint": "^16.15.0", "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.3" }, @@ -54,7 +54,7 @@ "node": ">=20.18.1 <21 || >=22" }, "optionalDependencies": { - "electron": "^32.3.0" + "electron": "^35.0.0" } }, "node_modules/@altano/repository-tools": { @@ -79,9 +79,9 @@ } }, "node_modules/@asamuzakjp/css-color": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.2.tgz", - "integrity": "sha512-RtWv9jFN2/bLExuZgFFZ0I3pWWeezAHGgrmjqGGWclATl1aDe3yhCUaI0Ilkp6OCk9zX7+FjvDasEX8Q9Rxc5w==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.3.tgz", + "integrity": "sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==", "dev": true, "license": "MIT", "dependencies": { @@ -89,18 +89,15 @@ "@csstools/css-color-parser": "^3.0.7", "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^11.0.2" + "lru-cache": "^10.4.3" } }, "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", - "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } + "license": "ISC" }, "node_modules/@babel/code-frame": { "version": "7.26.2", @@ -118,9 +115,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", - "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "dev": true, "license": "MIT", "engines": { @@ -128,22 +125,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", + "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", + "@babel/helpers": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.9", + "@babel/types": "^7.26.9", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -169,14 +166,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", - "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", + "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.5", - "@babel/types": "^7.26.5", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -285,27 +282,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", + "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", - "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", + "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.5" + "@babel/types": "^7.26.9" }, "bin": { "parser": "bin/babel-parser.js" @@ -554,32 +551,32 @@ } }, "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.5.tgz", - "integrity": "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", + "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.5", - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.5", + "@babel/generator": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -598,9 +595,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", - "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", + "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", "dev": true, "license": "MIT", "dependencies": { @@ -783,9 +780,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.4.tgz", - "integrity": "sha512-IvXx3TlM+OL0CFriapk7ZHmeY89dSSdo/BZ3DGf+WUS+BWd64H+z/xr3xkkqY0Eu6MV/vdzNfkLm5zl45FDMGg==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.5.tgz", + "integrity": "sha512-OrWqPuLf5EV+H/2sIYUSDF4UyiyCR4/+Q2n+xRx09CBg7YBx16h61V9892TKWCUr9FiJfAkKY24aWW3WRU9Nqg==", "dev": true, "license": "MIT" }, @@ -853,9 +850,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.33", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.33.tgz", - "integrity": "sha512-HniqQjzPVn24NEkHooBIw1cH+iO3AKMA9oDTwazUYQP1/ldqXsz6ce4+fdHia2nqypmic/lHVkQgIVhP48q/sA==", + "version": "4.3.34", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.34.tgz", + "integrity": "sha512-ewJXNV7Nk5vxbGvHvxYLDGoXN0Lq5sfSgX8SAlcYL+2bZ7r25nNOLHou5hdFlNgvviGTx/SFPlVKjdjVJlblgA==", "dev": true, "license": "MIT" }, @@ -902,9 +899,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-fullstack": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.5.tgz", - "integrity": "sha512-XNmNdovPUS9Vc2JvfBscy8zZfwyxR11sB4fxU2lXh7LzUvOn2/OkKAzj41JTdiWfVnJ/yvsRkspe+b7kr+DIQw==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.6.tgz", + "integrity": "sha512-cSaq9rz5RIU9j+0jcF2vnKPTQjxGXclntmoNp4XB7yFX2621PxJcekGjwf/lN5heJwVxGLL9toR0CBlGKwQBgA==", "dev": true, "license": "MIT" }, @@ -1041,9 +1038,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.27", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.27.tgz", - "integrity": "sha512-LGss1yrjhxSmxL4VfMC+UBDMVHfqHudgC7b39M74EVys+nNC4/lqDHacb6Aw7i6aUn9mzdNIkdTTD+LdDcHvPA==", + "version": "5.1.29", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.29.tgz", + "integrity": "sha512-FPCE9MpO42WGc9u/lx3J6CZSfPVO5kMUaOQkTVqXo3sTDX6+o5ulb+9W/MD33kiA0AvXr1Lk8knhA6koW9t/Yw==", "dev": true, "license": "MIT" }, @@ -1142,9 +1139,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-terraform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.1.0.tgz", - "integrity": "sha512-G55pcUUxeXAhejstmD35B47SkFd4uqCQimc+CMgq8Nx0dr03guL2iMsz8faRWQGkCnGimX8S91rbOhDv9p/heg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.1.1.tgz", + "integrity": "sha512-07KFDwCU7EnKl4hOZLsLKlj6Zceq/IsQ3LRWUyIjvGFfZHdoGtFdCp3ZPVgnFaAcd/DKv+WVkrOzUBSYqHopQQ==", "dev": true, "license": "MIT" }, @@ -1207,9 +1204,9 @@ } }, "node_modules/@csstools/color-helpers": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz", - "integrity": "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", + "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", "dev": true, "funding": [ { @@ -1227,9 +1224,9 @@ } }, "node_modules/@csstools/css-calc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.1.tgz", - "integrity": "sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz", + "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==", "dev": true, "funding": [ { @@ -1251,9 +1248,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz", - "integrity": "sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz", + "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==", "dev": true, "funding": [ { @@ -1267,8 +1264,8 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.0.1", - "@csstools/css-calc": "^2.1.1" + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.2" }, "engines": { "node": ">=18" @@ -2142,9 +2139,9 @@ } }, "node_modules/@keyv/serialize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz", - "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz", + "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==", "dev": true, "license": "MIT", "dependencies": { @@ -2584,9 +2581,9 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.1.0.tgz", - "integrity": "sha512-bytbL7qiici7yPyEiId0fGPK9kjQbzcPMj2aftPfzTCyJ/CRSKdtI+iVjM0LSGzGxfunflI+MDDU9vyIIeIpoQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.2.0.tgz", + "integrity": "sha512-8hXezgz7jexGHdo5WN6JBEIPHCSFyyU4vgbxevu4YLVS5vl+sxqAAGyXSzfNDyR6xMNSH5H1x67nsXcYMOHtZA==", "dev": true, "license": "MIT", "dependencies": { @@ -2680,12 +2677,6 @@ "@types/responselike": "^1.0.0" } }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "license": "MIT" - }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", @@ -2793,12 +2784,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.17.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.12.tgz", - "integrity": "sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==", + "version": "22.13.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz", + "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==", "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.20.0" } }, "node_modules/@types/responselike": { @@ -2853,14 +2844,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.1.tgz", - "integrity": "sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz", + "integrity": "sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1" + "@typescript-eslint/types": "8.26.0", + "@typescript-eslint/visitor-keys": "8.26.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2871,9 +2862,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.1.tgz", - "integrity": "sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.0.tgz", + "integrity": "sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==", "dev": true, "license": "MIT", "engines": { @@ -2885,14 +2876,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.1.tgz", - "integrity": "sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz", + "integrity": "sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/visitor-keys": "8.24.1", + "@typescript-eslint/types": "8.26.0", + "@typescript-eslint/visitor-keys": "8.26.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2908,20 +2899,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.1.tgz", - "integrity": "sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.0.tgz", + "integrity": "sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.24.1", - "@typescript-eslint/types": "8.24.1", - "@typescript-eslint/typescript-estree": "8.24.1" + "@typescript-eslint/scope-manager": "8.26.0", + "@typescript-eslint/types": "8.26.0", + "@typescript-eslint/typescript-estree": "8.26.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2932,17 +2923,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.24.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.1.tgz", - "integrity": "sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==", + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz", + "integrity": "sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.24.1", + "@typescript-eslint/types": "8.26.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3078,9 +3069,9 @@ } }, "node_modules/ansis": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.16.0.tgz", - "integrity": "sha512-sU7d/tfZiYrsIAXbdL/CNZld5bCkruzwT5KmqmadCJYxuLxHAOBjidxD5+iLmN/6xEfjcQq1l7OpsiCBlc4LzA==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", "license": "ISC", "engines": { "node": ">=14" @@ -3301,6 +3292,15 @@ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "license": "MIT" }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3323,9 +3323,9 @@ } }, "node_modules/axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz", + "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3735,14 +3735,14 @@ } }, "node_modules/cacheable": { - "version": "1.8.7", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.7.tgz", - "integrity": "sha512-AbfG7dAuYNjYxFUtL1lAqmlWdxczCJ47w7cFjhGcnGnUdwSo6VgmSojfoW3tUI12HUkgTJ5kqj78yyq6TsFtlg==", + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.9.tgz", + "integrity": "sha512-FicwAUyWnrtnd4QqYAoRlNs44/a1jTL7XDKqm5gJ90wz1DQPlC7U2Rd1Tydpv+E7WAr4sQHuw8Q8M3nZMAyecQ==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.6.0", - "keyv": "^5.2.3" + "hookified": "^1.7.1", + "keyv": "^5.3.1" } }, "node_modules/cacheable-lookup": { @@ -3775,13 +3775,13 @@ } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.2.3.tgz", - "integrity": "sha512-AGKecUfzrowabUv0bH1RIR5Vf7w+l4S3xtQAypKaUpTdIR1EbrAcTxHCrpo9Q+IWeUlFE2palRtgIQcgm+PQJw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.1.tgz", + "integrity": "sha512-13hQT2q2VIwOoaJdJa7nY3J8UVbYtMTJFHnwm9LI+SaQRfUiM6Em9KZeOVTCKbMnGcRIL3NSUFpAdjZCq24nLQ==", "dev": true, "license": "MIT", "dependencies": { - "@keyv/serialize": "^1.0.2" + "@keyv/serialize": "^1.0.3" } }, "node_modules/call-bind": { @@ -3803,9 +3803,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -3816,13 +3816,13 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -3851,9 +3851,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001692", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", - "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", + "version": "1.0.30001702", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001702.tgz", + "integrity": "sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==", "dev": true, "funding": [ { @@ -4018,9 +4018,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", - "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true, "license": "MIT" }, @@ -4807,9 +4807,9 @@ } }, "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", "dev": true, "license": "MIT" }, @@ -5154,15 +5154,15 @@ "license": "MIT" }, "node_modules/electron": { - "version": "32.3.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-32.3.0.tgz", - "integrity": "sha512-CyX6K1INQdlgTePmP3wuAueUi5ePqw0IpiGOyyzULGU9gBQI3idwW6apR3W/R1cES2j1gWLrkty3cD40qRV9sg==", + "version": "35.0.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-35.0.0.tgz", + "integrity": "sha512-mwNQNktYLPnUWZVR8iNkfWCBjmM5e2/CmB1rhACwE9ASDbVU7CYPgp/jLUB3bj/LyQsfSuubD82OUite6SN8Uw==", "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { "@electron/get": "^2.0.0", - "@types/node": "^20.9.0", + "@types/node": "^22.7.7", "extract-zip": "^2.0.1" }, "bin": { @@ -5173,9 +5173,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.80", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.80.tgz", - "integrity": "sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==", + "version": "1.5.112", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.112.tgz", + "integrity": "sha512-oen93kVyqSb3l+ziUgzIOlWt/oOuy4zRmpwestMn4rhFWAoFJeFuCVte9F2fASjeZZo7l/Cif9TiyrdW4CwEMA==", "dev": true, "license": "ISC" }, @@ -5219,12 +5219,11 @@ } }, "node_modules/engine.io": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", - "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", "license": "MIT", "dependencies": { - "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", @@ -5488,9 +5487,9 @@ "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -5515,13 +5514,16 @@ } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { @@ -5856,9 +5858,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.26.0.tgz", - "integrity": "sha512-plYuuP7RyL532yHLPvKtQNzK6ncXRmzWPji5EUlV0tXhhfFc84TDWiwJ+OYvv4pDA9AfV+gKYVUwhojaDameNw==", + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.26.2.tgz", + "integrity": "sha512-H7bANaQjMv6KiikiIUhn5t+YMPR2id0fXOiRTAj/pPAmajmBN2f3BwZKIrqkGDff29vwvhD/imADOfslPGen+w==", "dev": true, "license": "MIT", "dependencies": { @@ -6322,9 +6324,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", "funding": [ { "type": "github", @@ -6348,9 +6350,9 @@ } }, "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { @@ -6486,9 +6488,9 @@ } }, "node_modules/find-up-simple": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", - "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", "dev": true, "license": "MIT", "engines": { @@ -6513,9 +6515,9 @@ } }, "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "license": "ISC" }, "node_modules/follow-redirects": { @@ -6539,22 +6541,29 @@ } }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { @@ -6697,17 +6706,17 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -6804,9 +6813,9 @@ } }, "node_modules/git-hooks-list": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.1.0.tgz", - "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz", + "integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==", "dev": true, "license": "MIT", "funding": { @@ -7207,9 +7216,9 @@ } }, "node_modules/hookified": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.6.0.tgz", - "integrity": "sha512-se7cpwTA+iA/eY548Bu03JJqBiEZAqU2jnyKdj5B5qurtBg64CZGHTgqCv4Yh7NWu6FGI09W61MCq+NoPj9GXA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.7.1.tgz", + "integrity": "sha512-OXcdHsXeOiD7OJ5zvWj8Oy/6RCdLwntAX+wUrfemNcMGn6sux4xbEHi2QXwqePYhjQ/yvxxq2MvCRirdlHscBw==", "dev": true, "license": "MIT" }, @@ -7625,11 +7634,12 @@ "license": "MIT" }, "node_modules/is-async-function": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz", - "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "license": "MIT", "dependencies": { + "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", @@ -7670,12 +7680,12 @@ } }, "node_modules/is-boolean-object": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", - "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", + "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" }, "engines": { @@ -8030,12 +8040,12 @@ } }, "node_modules/is-weakref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", - "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -9324,6 +9334,7 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", "dev": true, "license": "MIT" }, @@ -10160,9 +10171,9 @@ } }, "node_modules/micromark-util-subtokenize": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.4.tgz", - "integrity": "sha512-N6hXjrin2GTJDe3MVjf5FuXpm12PGm80BrUAeub9XFXca8JZbP+oIwY4LJSVwFUCL1IPm/WwSVUN7goFHmSGGQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", "dev": true, "funding": [ { @@ -10368,9 +10379,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.46", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.46.tgz", - "integrity": "sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==", + "version": "0.5.47", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.47.tgz", + "integrity": "sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -10593,9 +10604,9 @@ "license": "MIT" }, "node_modules/nwsapi": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", - "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", + "version": "2.2.18", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.18.tgz", + "integrity": "sha512-p1TRH/edngVEHVbwqWnxUViEmq5znDvyB+Sik5cmuLpGOIfDf/39zLiq3swPF8Vakqn+gvNiOQAZu8djYlQILA==", "dev": true, "license": "MIT" }, @@ -10609,9 +10620,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -10825,9 +10836,9 @@ } }, "node_modules/pac-proxy-agent": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", - "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", @@ -11374,18 +11385,18 @@ } }, "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", - "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "dev": true, "funding": [ { @@ -11446,9 +11457,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "dev": true, "license": "MIT", "dependencies": { @@ -11476,9 +11487,9 @@ } }, "node_modules/prettier": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", - "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { @@ -12014,9 +12025,9 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -12709,9 +12720,9 @@ } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", "license": "MIT", "dependencies": { "ip-address": "^9.0.5", @@ -12744,9 +12755,9 @@ "license": "MIT" }, "node_modules/sort-package-json": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.13.0.tgz", - "integrity": "sha512-y1iCgJ+ZrOSgkzuhtpaxxsCLeUPZbEbIxcMDBde6JwpkZ3e9vVQhZ46iCD97GYImdgBLtXSPxxS9LqZbL6Th2Q==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz", + "integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==", "dev": true, "license": "MIT", "dependencies": { @@ -12835,9 +12846,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "dev": true, "license": "CC0-1.0" }, @@ -13079,9 +13090,9 @@ } }, "node_modules/stylelint": { - "version": "16.14.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.14.1.tgz", - "integrity": "sha512-oqCL7AC3786oTax35T/nuLL8p2C3k/8rHKAooezrPGRvUX0wX+qqs5kMWh5YYT4PHQgVDobHT4tw55WgpYG6Sw==", + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.15.0.tgz", + "integrity": "sha512-OK6Rs7EPdcdmjqiDycadZY4fw3f5/TC1X6/tGjnF3OosbwCeNs7nG+79MCAtjEg7ckwqTJTsku08e0Rmaz5nUw==", "dev": true, "funding": [ { @@ -13108,7 +13119,7 @@ "debug": "^4.3.7", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.0.5", + "file-entry-cache": "^10.0.6", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -13122,14 +13133,14 @@ "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", - "postcss": "^8.5.1", + "postcss": "^8.5.3", "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^7.0.0", + "postcss-selector-parser": "^7.1.0", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", - "supports-hyperlinks": "^3.1.0", + "supports-hyperlinks": "^3.2.0", "svg-tags": "^1.0.0", "table": "^6.9.0", "write-file-atomic": "^5.0.1" @@ -13222,25 +13233,25 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.5.tgz", - "integrity": "sha512-umpQsJrBNsdMDgreSryMEXvJh66XeLtZUwA8Gj7rHGearGufUFv6rB/bcXRFsiGWw/VeSUgUofF4Rf2UKEOrTA==", + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.7.tgz", + "integrity": "sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.5" + "flat-cache": "^6.1.7" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.5.tgz", - "integrity": "sha512-QR+2kN38f8nMfiIQ1LHYjuDEmZNZVjxuxY+HufbS3BW0EX01Q5OnH7iduOYRutmgiXb797HAKcXUeXrvRjjgSQ==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.7.tgz", + "integrity": "sha512-qwZ4xf1v1m7Rc9XiORly31YaChvKt6oNVHuqqZcoED/7O+ToyNVGobKsIAopY9ODcWpEDKEBAbrSOCBHtNQvew==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.8.7", - "flatted": "^3.3.2", - "hookified": "^1.6.0" + "cacheable": "^1.8.9", + "flatted": "^3.3.3", + "hookified": "^1.7.1" } }, "node_modules/stylelint/node_modules/globby": { @@ -13367,9 +13378,9 @@ } }, "node_modules/supports-hyperlinks": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", - "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", "dev": true, "license": "MIT", "dependencies": { @@ -13380,7 +13391,7 @@ "node": ">=14.18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -13582,22 +13593,22 @@ } }, "node_modules/tldts": { - "version": "6.1.71", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.71.tgz", - "integrity": "sha512-LQIHmHnuzfZgZWAf2HzL83TIIrD8NhhI0DVxqo9/FdOd4ilec+NTNZOlDZf7EwrTNoutccbsHjvWHYXLAtvxjw==", + "version": "6.1.82", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.82.tgz", + "integrity": "sha512-KCTjNL9F7j8MzxgfTgjT+v21oYH38OidFty7dH00maWANAI2IsLw2AnThtTJi9HKALHZKQQWnNebYheadacD+g==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.71" + "tldts-core": "^6.1.82" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.71", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.71.tgz", - "integrity": "sha512-LRbChn2YRpic1KxY+ldL1pGXN/oVvKfCVufwfVzEQdFYNo39uF7AJa/WXdo+gYO7PTvdfkCPCed6Hkvz/kR7jg==", + "version": "6.1.82", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.82.tgz", + "integrity": "sha512-Jabl32m21tt/d/PbDO88R43F8aY98Piiz6BVH9ShUlOAiiAELhEqwrAmBocjAqnCfoUeIsRU+h3IEzZd318F3w==", "dev": true, "license": "MIT" }, @@ -13630,9 +13641,9 @@ } }, "node_modules/tough-cookie": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.0.tgz", - "integrity": "sha512-rvZUv+7MoBYTiDmFPBrhL7Ujx9Sk+q9wwm22x8c8T5IJaR+Wsyc7TNxbVxo84kZoRJZZMazowFLqpankBEQrGg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -13861,9 +13872,9 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -13914,18 +13925,18 @@ } }, "node_modules/undici": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.3.0.tgz", - "integrity": "sha512-Qy96NND4Dou5jKoSJ2gm8ax8AJM/Ey9o9mz7KN1bb9GP+G0l20Zw8afxTnY2f4b7hmhn/z8aC2kfArVQlAhFBw==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.4.0.tgz", + "integrity": "sha512-PUQM3/es3noM24oUn10u3kNNap0AbxESOmnssmW+dOi9yGwlUSi5nTNYl3bNbTkWOF8YZDkx2tCmj9OtQ3iGGw==", "license": "MIT", "engines": { "node": ">=20.18.1" } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "license": "MIT" }, "node_modules/unicorn-magic": { @@ -13961,9 +13972,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -14164,9 +14175,9 @@ } }, "node_modules/whatwg-url": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", - "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.1.tgz", + "integrity": "sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14373,9 +14384,9 @@ } }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 4f7f0803bb..11484b25d0 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.3.0" + "undici": "^7.4.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.1.0", @@ -98,12 +98,12 @@ "playwright": "^1.50.1", "prettier": "^3.5.2", "sinon": "^19.0.2", - "stylelint": "^16.14.1", + "stylelint": "^16.15.0", "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.3" }, "optionalDependencies": { - "electron": "^32.3.0" + "electron": "^35.0.0" }, "engines": { "node": ">=20.18.1 <21 || >=22" From 2adf341fef819bdf66d43a0a7fd88f73689c3ed4 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 13 Mar 2025 13:02:02 +0100 Subject: [PATCH 196/418] Add Esperanto translation (#3740) I've had this on my agenda for a long time :slightly_smiling_face: --- CHANGELOG.md | 2 +- modules/default/alert/alert.js | 1 + modules/default/alert/translations/eo.json | 4 ++ translations/eo.json | 50 ++++++++++++++++++++++ translations/translations.js | 1 + 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 modules/default/alert/translations/eo.json create mode 100644 translations/eo.json diff --git a/CHANGELOG.md b/CHANGELOG.md index e6655233df..82a3084bb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ planned for 2025-04-01 ### Added -- Added Arabic translation. +- Add Arabic (#3719) and Esperanto translation. ### Changed diff --git a/modules/default/alert/alert.js b/modules/default/alert/alert.js index a436a74c7b..5e70cd7c7b 100644 --- a/modules/default/alert/alert.js +++ b/modules/default/alert/alert.js @@ -25,6 +25,7 @@ Module.register("alert", { da: "translations/da.json", de: "translations/de.json", en: "translations/en.json", + eo: "translations/eo.json", es: "translations/es.json", fr: "translations/fr.json", hu: "translations/hu.json", diff --git a/modules/default/alert/translations/eo.json b/modules/default/alert/translations/eo.json new file mode 100644 index 0000000000..3c7a23fc1b --- /dev/null +++ b/modules/default/alert/translations/eo.json @@ -0,0 +1,4 @@ +{ + "sysTitle": "MagicMirror²-sciigo", + "welcome": "Bonvenon, lanĉo sukcesis!" +} diff --git a/translations/eo.json b/translations/eo.json new file mode 100644 index 0000000000..d4579b60b6 --- /dev/null +++ b/translations/eo.json @@ -0,0 +1,50 @@ +{ + "LOADING": "Ŝarĝas …", + + "DAYBEFOREYESTERDAY": "antaŭhieraŭ", + "YESTERDAY": "hieraŭ", + "TODAY": "hodiaŭ", + "TOMORROW": "morgaŭ", + "DAYAFTERTOMORROW": "postmorgaŭ", + "RUNNING": "ankoraŭ", + "EMPTY": "Neniu evento.", + "WEEK": "{weekNumber}a kalendara semajno", + + "N": "N", + "NNE": "NNOr", + "NE": "NOr", + "ENE": "OrNOr", + "E": "Or", + "ESE": "OrSOr", + "SE": "SOr", + "SSE": "SSOr", + "S": "S", + "SSW": "SSOk", + "SW": "SOk", + "WSW": "OkSOk", + "W": "Ok", + "WNW": "OkNOk", + "NW": "NOk", + "NNW": "NNOk", + + "FEELS": "Perceptite kiel {DEGREE}", + "PRECIP_POP": "Ŝanco de pluvado", + "PRECIP_AMOUNT": "Kvanto de pluvo", + + "MODULE_CONFIG_CHANGED": "La agordaj opcioj por la modulo „{MODULE_NAME}“ ŝanĝiĝis. \nBonvolu kontroli la dokumentadon.", + "MODULE_CONFIG_ERROR": "Eraro en la modulo „{MODULE_NAME}“. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Malĝusta URL.", + "MODULE_ERROR_NO_CONNECTION": "Neniu interreta konekto.", + "MODULE_ERROR_UNAUTHORIZED": "Aŭtorigo malsukcesis.", + "MODULE_ERROR_UNSPECIFIED": "Kontrolu la protokolajn dosierojn por pli da detaloj.", + + "NEWSFEED_NO_ITEMS": "Momente neniu novaĵoj.", + + "UPDATE_NOTIFICATION": "Ĝisdatigo por MagicMirror² disponebla.", + "UPDATE_NOTIFICATION_MODULE": "Ĝisdatigo por la modulo „{MODULE_NAME}“ disponebla.", + "UPDATE_INFO_SINGLE": "La nuna instalado estas unu komito malantaŭ la {BRANCH_NAME}-branĉo.", + "UPDATE_INFO_MULTIPLE": "La nuna instalado estas {COMMIT_COUNT} komitoj malantaŭ la {BRANCH_NAME}-branĉo.", + "UPDATE_NOTIFICATION_DONE": "Ĝisdatigo por la modulo {MODULE_NAME} finita.", + "UPDATE_NOTIFICATION_ERROR": "Eraro dum la ĝisdatigo de la modulo {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror devas esti restartigita." +} diff --git a/translations/translations.js b/translations/translations.js index 69d1591dfa..d76c8da8ee 100644 --- a/translations/translations.js +++ b/translations/translations.js @@ -2,6 +2,7 @@ let translations = { en: "translations/en.json", // English nl: "translations/nl.json", // Dutch de: "translations/de.json", // German + eo: "translations/eo.json", // Esperanto fi: "translations/fi.json", // Suomi fr: "translations/fr.json", // French fy: "translations/fy.json", // Frysk From 0afc1ed58dfd2b8059d796602522867036a05d5d Mon Sep 17 00:00:00 2001 From: mixasgr Date: Sat, 15 Mar 2025 22:54:20 +0200 Subject: [PATCH 197/418] Updated Greek Translations (#3741) Hello, we have updated the core Greek translation and added Greek translation to Alerts module. Thank you! --------- Co-authored-by: Savvas Adamtziloglou Co-authored-by: Konstantinos Co-authored-by: Veeck --- CHANGELOG.md | 2 ++ modules/default/alert/translations/el.json | 4 ++++ translations/el.json | 27 +++++++++++++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 modules/default/alert/translations/el.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 82a3084bb8..1e5e5477ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ planned for 2025-04-01 ### Added - Add Arabic (#3719) and Esperanto translation. +- Add Greek translation to Alerts module. ### Changed @@ -33,6 +34,7 @@ planned for 2025-04-01 - [core] Update dependencies incl. electron to v35 and formatting (#3593, #3693, #3717) - [core] Update ESLint and simplify config +- Update Greek translation ### Fixed diff --git a/modules/default/alert/translations/el.json b/modules/default/alert/translations/el.json new file mode 100644 index 0000000000..f259bcfb0c --- /dev/null +++ b/modules/default/alert/translations/el.json @@ -0,0 +1,4 @@ +{ + "sysTitle": "MagicMirror² Ειδοποίηση", + "welcome": "Καλώς ήρθατε, η εκκίνηση ήταν επιτυχής!" +} diff --git a/translations/el.json b/translations/el.json index cf10b32106..dd8d007cdf 100644 --- a/translations/el.json +++ b/translations/el.json @@ -1,8 +1,8 @@ { - "LOADING": "Φόρτωση …", + "LOADING": "Φόρτωση ...", "DAYBEFOREYESTERDAY": "Προχθές", - "YESTERDAY": "Εχθές", + "YESTERDAY": "Χθες", "TODAY": "Σήμερα", "TOMORROW": "Αύριο", "RUNNING": "Λήγει σε", @@ -23,5 +23,26 @@ "W": "Δ", "WNW": "ΔΒΔ", "NW": "ΒΔ", - "NNW": "ΒΒΔ" + "NNW": "ΒΒΔ", + + "FEELS": "Αίσθηση {DEGREE}", + "PRECIP_POP": "Πιθ. υετού", + "PRECIP_AMOUNT": "Ποσότητα υετού", + + "MODULE_CONFIG_CHANGED": "Οι επιλογές διαμόρφωσης για το module {MODULE_NAME} έχουν αλλάξει.\nΕλέγξτε την τεκμηρίωση.", + "MODULE_CONFIG_ERROR": "Σφάλμα στο module {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Λανθασμένη μορφή url.", + "MODULE_ERROR_NO_CONNECTION": "Δεν υπάρχει σύνδεση στο διαδίκτυο.", + "MODULE_ERROR_UNAUTHORIZED": "Η εξουσιοδότηση απέτυχε.", + "MODULE_ERROR_UNSPECIFIED": "Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες.", + + "NEWSFEED_NO_ITEMS": "Δεν υπάρχουν ειδήσεις αυτή τη στιγμή.", + + "UPDATE_NOTIFICATION": "Διατίθεται ενημέρωση MagicMirror².", + "UPDATE_NOTIFICATION_MODULE": "Διατίθεται ενημέρωση για το module {MODULE_NAME}.", + "UPDATE_INFO_SINGLE": "Η τρέχουσα εγκατάσταση είναι {COMMIT_COUNT} commit πίσω στο branch {BRANCH_NAME}.", + "UPDATE_INFO_MULTIPLE": "Η τρέχουσα εγκατάσταση είναι {COMMIT_COUNT} commit πίσω στο branch {BRANCH_NAME}", + "UPDATE_NOTIFICATION_DONE": "Η ενημέρωση ολοκληρώθηκε για το module {MODULE_NAME}", + "UPDATE_NOTIFICATION_ERROR": "Η ενημέρωση απέτυχε για το module {MODULE_NAME}", + "UPDATE_NOTIFICATION_NEED-RESTART": "Απαιτείται επανεκκίνηση του MagicMirror." } From 51d11bf26c5bcb2d1496c615ca9853b951b8deb3 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sun, 16 Mar 2025 07:33:27 -0700 Subject: [PATCH 198/418] add support for digital clock time color (#3737) see https://forum.magicmirror.builders/topic/19440/digital-clock-minutes-darker changelog added question.. we have a config parm for seconds color, but not hour/minute I have used css here.. is that too inconsistent? --------- Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Co-authored-by: Veeck --- CHANGELOG.md | 2 ++ js/app.js | 16 ++++++++-- js/deprecated.js | 3 +- modules/default/clock/clock.js | 41 ++++++++++++++------------ modules/default/clock/clock_styles.css | 19 +++++++++++- tests/e2e/modules/clock_spec.js | 7 +++++ 6 files changed, 65 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e5e5477ad..b539cc83e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,9 @@ planned for 2025-04-01 ### Added +- Add CSS support to the digital clock hour/minute/second through the use of the classes `clock-hour-digital`, `clock-minute-digital`, and `clock-second-digital`. - Add Arabic (#3719) and Esperanto translation. +- Mark option `secondsColor` as deprecated in clock module. - Add Greek translation to Alerts module. ### Changed diff --git a/js/app.js b/js/app.js index ffe3616df8..20bc856cf3 100644 --- a/js/app.js +++ b/js/app.js @@ -153,11 +153,23 @@ function App () { */ function checkDeprecatedOptions (userConfig) { const deprecated = require(`${global.root_path}/js/deprecated`); - const deprecatedOptions = deprecated.configs; + // check for deprecated core options + const deprecatedOptions = deprecated.configs; const usedDeprecated = deprecatedOptions.filter((option) => userConfig.hasOwnProperty(option)); if (usedDeprecated.length > 0) { - Log.warn(`WARNING! Your config is using deprecated options: ${usedDeprecated.join(", ")}. Check README and CHANGELOG for more up-to-date ways of getting the same functionality.`); + Log.warn(`WARNING! Your config is using deprecated option(s): ${usedDeprecated.join(", ")}. Check README and CHANGELOG for more up-to-date ways of getting the same functionality.`); + } + + // check for deprecated module options + for (const element of userConfig.modules) { + if (deprecated[element.module] !== undefined && element.config !== undefined) { + const deprecatedModuleOptions = deprecated[element.module]; + const usedDeprecatedModuleOptions = deprecatedModuleOptions.filter((option) => element.config.hasOwnProperty(option)); + if (usedDeprecatedModuleOptions.length > 0) { + Log.warn(`WARNING! Your config for module ${element.module} is using deprecated option(s): ${usedDeprecatedModuleOptions.join(", ")}. Check README and CHANGELOG for more up-to-date ways of getting the same functionality.`); + } + } } } diff --git a/js/deprecated.js b/js/deprecated.js index b0aca56ca0..10cf7ae044 100644 --- a/js/deprecated.js +++ b/js/deprecated.js @@ -1,3 +1,4 @@ module.exports = { - configs: ["kioskmode"] + configs: ["kioskmode"], + clock: ["secondsColor"] }; diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 5d2a17c87d..14667d0227 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -23,7 +23,7 @@ Module.register("clock", { analogFace: "simple", // options: 'none', 'simple', 'face-###' (where ### is 001 to 012 inclusive) analogPlacement: "bottom", // options: 'top', 'bottom', 'left', 'right' analogShowDate: "top", // OBSOLETE, can be replaced with analogPlacement and showTime, options: false, 'top', or 'bottom' - secondsColor: "#888888", + secondsColor: "#888888", // DEPRECATED, use CSS instead. Class "clock-second-digital" for digital clock, "clock-second" for analog clock. showSunTimes: false, showMoonTimes: false, // options: false, 'times' (rise/set), 'percent' (lit percent), 'phase' (current phase), or 'both' (percent & phase) @@ -105,6 +105,8 @@ Module.register("clock", { */ const dateWrapper = document.createElement("div"); const timeWrapper = document.createElement("div"); + const hoursWrapper = document.createElement("span"); + const minutesWrapper = document.createElement("span"); const secondsWrapper = document.createElement("sup"); const periodWrapper = document.createElement("span"); const sunWrapper = document.createElement("div"); @@ -114,39 +116,40 @@ Module.register("clock", { // Style Wrappers dateWrapper.className = "date normal medium"; timeWrapper.className = "time bright large light"; - secondsWrapper.className = "seconds dimmed"; + hoursWrapper.className = "clock-hour-digital"; + minutesWrapper.className = "clock-minute-digital"; + secondsWrapper.className = "clock-second-digital dimmed"; sunWrapper.className = "sun dimmed small"; moonWrapper.className = "moon dimmed small"; weekWrapper.className = "week dimmed medium"; // Set content of wrappers. - // The moment().format("h") method has a bug on the Raspberry Pi. - // So we need to generate the timestring manually. - // See issue: https://github.com/MagicMirrorOrg/MagicMirror/issues/181 - let timeString; const now = moment(); if (this.config.timezone) { now.tz(this.config.timezone); } - let hourSymbol = "HH"; - if (this.config.timeFormat !== 24) { - hourSymbol = "h"; - } - - if (this.config.clockBold) { - timeString = now.format(`${hourSymbol}[]mm[]`); - } else { - timeString = now.format(`${hourSymbol}:mm`); - } - if (this.config.showDate) { dateWrapper.innerHTML = now.format(this.config.dateFormat); digitalWrapper.appendChild(dateWrapper); } if (this.config.displayType !== "analog" && this.config.showTime) { - timeWrapper.innerHTML = timeString; + let hourSymbol = "HH"; + if (this.config.timeFormat !== 24) { + hourSymbol = "h"; + } + + hoursWrapper.innerHTML = now.format(hourSymbol); + minutesWrapper.innerHTML = now.format("mm"); + + timeWrapper.appendChild(hoursWrapper); + if (this.config.clockBold) { + minutesWrapper.classList.add("bold"); + } else { + timeWrapper.innerHTML += ":"; + } + timeWrapper.appendChild(minutesWrapper); secondsWrapper.innerHTML = now.format("ss"); if (this.config.showPeriodUpper) { periodWrapper.innerHTML = now.format("A"); @@ -267,7 +270,7 @@ Module.register("clock", { clockSecond.id = "clock-second"; clockSecond.style.transform = `rotate(${second}deg)`; clockSecond.className = "clock-second"; - clockSecond.style.backgroundColor = this.config.secondsColor; + clockSecond.style.backgroundColor = this.config.secondsColor; /* DEPRECATED, to be removed in a future version , use CSS instead */ clockFace.appendChild(clockSecond); } analogWrapper.appendChild(clockFace); diff --git a/modules/default/clock/clock_styles.css b/modules/default/clock/clock_styles.css index e938dd2e8e..a6751e3da5 100644 --- a/modules/default/clock/clock_styles.css +++ b/modules/default/clock/clock_styles.css @@ -78,7 +78,12 @@ left: 50%; margin: -38% -1px 0 0; /* numbers must match negative length & thickness */ padding: 38% 1px 0 0; /* indicator length & thickness */ - background: var(--color-text); + + /* background: #888888 !important; */ + + /* use this instead of secondsColor */ + + /* have to use !important, because the code explicitly sets the color currently */ transform-origin: 50% 100%; } @@ -91,3 +96,15 @@ .module.clock .moon > * { flex: 1; } + +.module.clock .clock-hour-digital { + color: var(--color-text-bright); +} + +.module.clock .clock-minute-digital { + color: var(--color-text-bright); +} + +.module.clock .clock-second-digital { + color: var(--color-text-dimmed); +} diff --git a/tests/e2e/modules/clock_spec.js b/tests/e2e/modules/clock_spec.js index 651b20de66..a5a6d2e0ca 100644 --- a/tests/e2e/modules/clock_spec.js +++ b/tests/e2e/modules/clock_spec.js @@ -38,6 +38,13 @@ describe("Clock module", () => { const timeRegex = /^(?:1[0-2]|[1-9]):[0-5]\d[0-5]\d[ap]m$/; await expect(helpers.testMatch(".clock .time", timeRegex)).resolves.toBe(true); }); + + it("check for discreet elements of clock", async () => { + let elemClock = helpers.waitForElement(".clock-hour-digital"); + await expect(elemClock).not.toBeNull(); + elemClock = helpers.waitForElement(".clock-minute-digital"); + await expect(elemClock).not.toBeNull(); + }); }); describe("with showPeriodUpper config enabled", () => { From 0cfe2730ea57079757b8b912993c0d58b7b8444b Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 18 Mar 2025 10:19:05 +0100 Subject: [PATCH 199/418] newsfeed: add specific ignoreOlderThan value (override) per feed (#3742) fixes #3360 superseeds https://github.com/MagicMirrorOrg/MagicMirror/pull/3429 had to open a new PR because getting `permission denied` when trying to push to the old one. --- CHANGELOG.md | 1 + modules/default/newsfeed/newsfeed.js | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b539cc83e3..0a3197ca0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ planned for 2025-04-01 - Add Arabic (#3719) and Esperanto translation. - Mark option `secondsColor` as deprecated in clock module. - Add Greek translation to Alerts module. +- [newsfeed] Add specific ignoreOlderThan value (override) per feed (#3360) ### Changed diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 34f040a508..2907439d00 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -177,6 +177,18 @@ Module.register("newsfeed", { } }, + /** + * Gets a feed property by name + * @param {object} feed A feed object. + * @param {string} property The name of the property. + */ + getFeedProperty (feed, property) { + let res = this.config[property]; + const f = this.config.feeds.find((feedItem) => feedItem.url === feed); + if (f && f[property]) res = f[property]; + return res; + }, + /** * Generate an ordered list of items for this configured module. * @param {object} feeds An object with feeds returned by the node helper. @@ -188,7 +200,7 @@ Module.register("newsfeed", { if (this.subscribedToFeed(feed)) { for (let item of feedItems) { item.sourceTitle = this.titleForFeed(feed); - if (!(this.config.ignoreOldItems && Date.now() - new Date(item.pubdate) > this.config.ignoreOlderThan)) { + if (!(this.getFeedProperty(feed, "ignoreOldItems") && Date.now() - new Date(item.pubdate) > this.getFeedProperty(feed, "ignoreOlderThan"))) { newsItems.push(item); } } From 68ec696c25073b92e7093fbb18377b9973c8c014 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 18 Mar 2025 22:30:20 +0100 Subject: [PATCH 200/418] Update ESLint and prettier (#3746) This will fix #3745. --- CHANGELOG.md | 2 +- eslint.config.mjs | 4 +- package-lock.json | 396 ++++++++++++++++++++++++---------------------- package.json | 12 +- 4 files changed, 213 insertions(+), 201 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a3197ca0a..902f35ba0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,7 @@ planned for 2025-04-01 ### Updated - [core] Update dependencies incl. electron to v35 and formatting (#3593, #3693, #3717) -- [core] Update ESLint and simplify config +- [core] Update prettier, ESLint and simplify config - Update Greek translation ### Fixed diff --git a/eslint.config.mjs b/eslint.config.mjs index 75ea30e0ec..1f69ae342a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,7 +1,7 @@ import eslintPluginImport from "eslint-plugin-import"; import eslintPluginJest from "eslint-plugin-jest"; import eslintPluginJs from "@eslint/js"; -import eslintPluginPackageJson from "eslint-plugin-package-json/configs/recommended"; +import eslintPluginPackageJson from "eslint-plugin-package-json"; import eslintPluginStylistic from "@stylistic/eslint-plugin"; import globals from "globals"; @@ -9,7 +9,7 @@ const config = [ eslintPluginImport.flatConfigs.recommended, eslintPluginJest.configs["flat/recommended"], eslintPluginJs.configs.recommended, - eslintPluginPackageJson, + eslintPluginPackageJson.configs.recommended, eslintPluginStylistic.configs.all, { files: ["**/*.js"], diff --git a/package-lock.json b/package-lock.json index 520836a1a1..cf24adbc9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "ansis": "^3.16.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.21.0", + "eslint": "^9.22.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -31,12 +31,12 @@ "undici": "^7.4.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^4.1.0", + "@stylistic/eslint-plugin": "^4.2.0", "cspell": "^8.17.5", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.3", - "eslint-plugin-package-json": "^0.26.0", + "eslint-plugin-jsdoc": "^50.6.8", + "eslint-plugin-package-json": "^0.29.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", @@ -44,9 +44,9 @@ "lint-staged": "^15.4.3", "markdownlint-cli2": "^0.17.2", "playwright": "^1.50.1", - "prettier": "^3.5.2", + "prettier": "^3.5.3", "sinon": "^19.0.2", - "stylelint": "^16.15.0", + "stylelint": "^16.16.0", "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.3" }, @@ -79,14 +79,14 @@ } }, "node_modules/@asamuzakjp/css-color": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.3.tgz", - "integrity": "sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.1.tgz", + "integrity": "sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.1", - "@csstools/css-color-parser": "^3.0.7", + "@csstools/css-calc": "^2.1.2", + "@csstools/css-color-parser": "^3.0.8", "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", "lru-cache": "^10.4.3" @@ -125,22 +125,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", - "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", + "@babel/generator": "^7.26.10", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.9", - "@babel/parser": "^7.26.9", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -166,14 +166,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", - "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", + "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/parser": "^7.26.10", + "@babel/types": "^7.26.10", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -282,27 +282,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/types": "^7.26.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.9" + "@babel/types": "^7.26.10" }, "bin": { "parser": "bin/babel-parser.js" @@ -566,17 +566,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", - "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", + "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", - "@babel/parser": "^7.26.9", + "@babel/generator": "^7.26.10", + "@babel/parser": "^7.26.10", "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/types": "^7.26.10", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -595,9 +595,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "dev": true, "license": "MIT", "dependencies": { @@ -780,9 +780,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.5.tgz", - "integrity": "sha512-OrWqPuLf5EV+H/2sIYUSDF4UyiyCR4/+Q2n+xRx09CBg7YBx16h61V9892TKWCUr9FiJfAkKY24aWW3WRU9Nqg==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.6.tgz", + "integrity": "sha512-HMV1chsExuZt5IL9rYBW7GmhNZDVdQJEd1WtFgOO6jqiNxbpTG3Is3Pkldl7FpusBQQZr4BdjMit5bnPpVRy3A==", "dev": true, "license": "MIT" }, @@ -857,9 +857,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.9.tgz", - "integrity": "sha512-O/jAr1VNtuyCFckbTmpeEf43ZFWVD9cJFvWaA6rO2IVmLirJViHWJUyBZOuQcesSplzEIw80MAYmnK06/MDWXQ==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.10.tgz", + "integrity": "sha512-80mXJLtr0tVEtzowrI7ycVae/ULAYImZUlr0kUTpa8i57AUk7Zy3pYBs44EYIKW7ZC9AHu4Qjjfq4vriAtyTDQ==", "dev": true, "license": "CC BY-SA 4.0" }, @@ -920,9 +920,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-golang": { - "version": "6.0.18", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.18.tgz", - "integrity": "sha512-Mt+7NwfodDwUk7423DdaQa0YaA+4UoV3XSxQwZioqjpFBCuxfvvv4l80MxCTAAbK6duGj0uHbGTwpv8fyKYPKg==", + "version": "6.0.19", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.19.tgz", + "integrity": "sha512-VS+oinB2/CbgmHE06kMJlj52OVMZM0S2EEXph3oaroNTgTuclSwdFylQmOEjquZi55kW+n3FM9MyWXiitB7Dtg==", "dev": true, "license": "MIT" }, @@ -1038,9 +1038,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.29", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.29.tgz", - "integrity": "sha512-FPCE9MpO42WGc9u/lx3J6CZSfPVO5kMUaOQkTVqXo3sTDX6+o5ulb+9W/MD33kiA0AvXr1Lk8knhA6koW9t/Yw==", + "version": "5.1.30", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.30.tgz", + "integrity": "sha512-qRMJZFz4FBPECH5rGQN9p2Ld6nfpSaPFQvlG6V2RowWcrJQqF4RFmLUNuRQpvndpSeIUo32yX1hxb7AT45ARCQ==", "dev": true, "license": "MIT" }, @@ -1066,9 +1066,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.15", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.15.tgz", - "integrity": "sha512-VNXhj0Eh+hdHN89MgyaoSAexBQKmYtJaMhucbMI7XmBs4pf8fuFFN3xugk51/A4TZJr8+RImdFFsGMOw+I4bDA==", + "version": "4.2.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.16.tgz", + "integrity": "sha512-LkQssFt1hPOWXIQiD8ScTkz/41RL7Ti0V/2ytUzEW82dc0atIEksrBg8MuOjWXktp0Dk5tDwRLgmIvhV3CFFOA==", "dev": true, "license": "MIT", "dependencies": { @@ -1083,9 +1083,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-ruby": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.7.tgz", - "integrity": "sha512-4/d0hcoPzi5Alk0FmcyqlzFW9lQnZh9j07MJzPcyVO62nYJJAGKaPZL2o4qHeCS/od/ctJC5AHRdoUm0ktsw6Q==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.8.tgz", + "integrity": "sha512-ixuTneU0aH1cPQRbWJvtvOntMFfeQR2KxT8LuAv5jBKqQWIHSxzGlp+zX3SVyoeR0kOWiu64/O5Yn836A5yMcQ==", "dev": true, "license": "MIT" }, @@ -1434,9 +1434,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", + "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -1508,6 +1508,15 @@ "node": "*" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", + "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", @@ -1588,9 +1597,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", - "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", + "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2784,9 +2793,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz", - "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==", + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -2844,14 +2853,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz", - "integrity": "sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==", + "version": "8.26.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz", + "integrity": "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.0", - "@typescript-eslint/visitor-keys": "8.26.0" + "@typescript-eslint/types": "8.26.1", + "@typescript-eslint/visitor-keys": "8.26.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2862,9 +2871,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.0.tgz", - "integrity": "sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==", + "version": "8.26.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.1.tgz", + "integrity": "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==", "dev": true, "license": "MIT", "engines": { @@ -2876,14 +2885,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz", - "integrity": "sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==", + "version": "8.26.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz", + "integrity": "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.0", - "@typescript-eslint/visitor-keys": "8.26.0", + "@typescript-eslint/types": "8.26.1", + "@typescript-eslint/visitor-keys": "8.26.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2903,16 +2912,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.0.tgz", - "integrity": "sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==", + "version": "8.26.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.1.tgz", + "integrity": "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.26.0", - "@typescript-eslint/types": "8.26.0", - "@typescript-eslint/typescript-estree": "8.26.0" + "@typescript-eslint/scope-manager": "8.26.1", + "@typescript-eslint/types": "8.26.1", + "@typescript-eslint/typescript-estree": "8.26.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2927,13 +2936,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.26.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz", - "integrity": "sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==", + "version": "8.26.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz", + "integrity": "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.0", + "@typescript-eslint/types": "8.26.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2958,9 +2967,9 @@ } }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3179,18 +3188,19 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3323,9 +3333,9 @@ } }, "node_modules/axios": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz", - "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3775,9 +3785,9 @@ } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.1.tgz", - "integrity": "sha512-13hQT2q2VIwOoaJdJa7nY3J8UVbYtMTJFHnwm9LI+SaQRfUiM6Em9KZeOVTCKbMnGcRIL3NSUFpAdjZCq24nLQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.2.tgz", + "integrity": "sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3851,9 +3861,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001702", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001702.tgz", - "integrity": "sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==", + "version": "1.0.30001706", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", + "integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==", "dev": true, "funding": [ { @@ -4681,13 +4691,13 @@ } }, "node_modules/cssstyle": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz", - "integrity": "sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz", + "integrity": "sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^2.8.2", + "@asamuzakjp/css-color": "^3.1.1", "rrweb-cssom": "^0.8.0" }, "engines": { @@ -4814,9 +4824,9 @@ "license": "MIT" }, "node_modules/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", + "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", "dev": true, "license": "MIT", "dependencies": { @@ -5154,9 +5164,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "35.0.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-35.0.0.tgz", - "integrity": "sha512-mwNQNktYLPnUWZVR8iNkfWCBjmM5e2/CmB1rhACwE9ASDbVU7CYPgp/jLUB3bj/LyQsfSuubD82OUite6SN8Uw==", + "version": "35.0.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-35.0.2.tgz", + "integrity": "sha512-jo8S4GfBpVIBDGitUrv+Vo/I/ZEEs6IvWprG2KJlxayYIKpufulbQaxDt78cC/79FwFo8MA0JOIwx/b9r5NRag==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5173,9 +5183,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.112", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.112.tgz", - "integrity": "sha512-oen93kVyqSb3l+ziUgzIOlWt/oOuy4zRmpwestMn4rhFWAoFJeFuCVte9F2fASjeZZo7l/Cif9TiyrdW4CwEMA==", + "version": "1.5.120", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.120.tgz", + "integrity": "sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ==", "dev": true, "license": "ISC" }, @@ -5600,17 +5610,18 @@ } }, "node_modules/eslint": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", - "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", + "version": "9.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", + "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", + "@eslint/config-helpers": "^0.1.0", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.0", - "@eslint/js": "9.21.0", + "@eslint/js": "9.22.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5622,7 +5633,7 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", + "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", @@ -5832,9 +5843,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.3.tgz", - "integrity": "sha512-NxbJyt1M5zffPcYZ8Nb53/8nnbIScmiLAMdoe0/FAszwb7lcSiX3iYBTsuF7RV84dZZJC8r3NghomrUXsmWvxQ==", + "version": "50.6.8", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.8.tgz", + "integrity": "sha512-PPZVqhoXaalMQwDGzcQrJtPSPIPOYsSMtvkjYAdsIazOW20yhYtVX4+jLL+XznD4zYTXyZbPWPRKkNev4D4lyw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5858,9 +5869,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.26.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.26.2.tgz", - "integrity": "sha512-H7bANaQjMv6KiikiIUhn5t+YMPR2id0fXOiRTAj/pPAmajmBN2f3BwZKIrqkGDff29vwvhD/imADOfslPGen+w==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.29.0.tgz", + "integrity": "sha512-S2YjWLMb+vaI0QbvkSrM6F2lEulaehGWEgHAXSoJI0F2eDw4udp5gtdFyKMLP2GSrfJB5cnKPnSJiOO5RGuaKg==", "dev": true, "license": "MIT", "dependencies": { @@ -5871,7 +5882,7 @@ "package-json-validator": "^0.10.0", "semver": "^7.5.4", "sort-object-keys": "^1.1.3", - "sort-package-json": "^2.12.0", + "sort-package-json": "^3.0.0", "validate-npm-package-name": "^6.0.0" }, "engines": { @@ -5883,9 +5894,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -7207,18 +7218,18 @@ } }, "node_modules/helmet": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.0.0.tgz", - "integrity": "sha512-VyusHLEIIO5mjQPUI1wpOAEu+wl6Q0998jzTxqUYGE45xCIcAxy3MsbEK/yyJUJ3ADeMoB6MornPH6GMWAf+Pw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz", + "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==", "license": "MIT", "engines": { "node": ">=18.0.0" } }, "node_modules/hookified": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.7.1.tgz", - "integrity": "sha512-OXcdHsXeOiD7OJ5zvWj8Oy/6RCdLwntAX+wUrfemNcMGn6sux4xbEHi2QXwqePYhjQ/yvxxq2MvCRirdlHscBw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.8.1.tgz", + "integrity": "sha512-GrO2l93P8xCWBSTBX9l2BxI78VU/MAAYag+pG8curS3aBGy0++ZlxrQ7PdUOUVMbn5BwkGb6+eRrnf43ipnFEA==", "dev": true, "license": "MIT" }, @@ -9107,9 +9118,9 @@ } }, "node_modules/lint-staged": { - "version": "15.4.3", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.3.tgz", - "integrity": "sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==", + "version": "15.5.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.0.tgz", + "integrity": "sha512-WyCzSbfYGhK7cU+UuDDkzUiytbfbi0ZdPy2orwtM75P3WTtQBzmG40cCxIa8Ii2+XjfxzLH6Be46tUfWS85Xfg==", "dev": true, "license": "MIT", "dependencies": { @@ -10403,9 +10414,9 @@ "license": "ISC" }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", + "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", "dev": true, "funding": [ { @@ -10604,9 +10615,9 @@ "license": "MIT" }, "node_modules/nwsapi": { - "version": "2.2.18", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.18.tgz", - "integrity": "sha512-p1TRH/edngVEHVbwqWnxUViEmq5znDvyB+Sik5cmuLpGOIfDf/39zLiq3swPF8Vakqn+gvNiOQAZu8djYlQILA==", + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.19.tgz", + "integrity": "sha512-94bcyI3RsqiZufXjkr3ltkI86iEl+I7uiHVDtcq9wJUTwYQJ5odHDeSzkkrRzi80jJ8MaeZgqKjH1bAWAFw9bA==", "dev": true, "license": "MIT" }, @@ -11184,13 +11195,13 @@ } }, "node_modules/playwright": { - "version": "1.50.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", - "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz", + "integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.50.1" + "playwright-core": "1.51.1" }, "bin": { "playwright": "cli.js" @@ -11203,9 +11214,9 @@ } }, "node_modules/playwright-core": { - "version": "1.50.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", - "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", + "version": "1.51.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz", + "integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -12755,20 +12766,20 @@ "license": "MIT" }, "node_modules/sort-package-json": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz", - "integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.0.0.tgz", + "integrity": "sha512-vfZWx4DnFNB8R9Vg4Dnx21s20auNzWH15ZaCBfADAiyrCwemRmhWstTgvLjMek1DW3+MHcNaqkp86giCF24rMA==", "dev": true, "license": "MIT", "dependencies": { "detect-indent": "^7.0.1", - "detect-newline": "^4.0.0", + "detect-newline": "^4.0.1", "get-stdin": "^9.0.0", "git-hooks-list": "^3.0.0", "is-plain-obj": "^4.1.0", - "semver": "^7.6.0", + "semver": "^7.7.1", "sort-object-keys": "^1.1.3", - "tinyglobby": "^0.2.9" + "tinyglobby": "^0.2.12" }, "bin": { "sort-package-json": "cli.js" @@ -13090,9 +13101,9 @@ } }, "node_modules/stylelint": { - "version": "16.15.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.15.0.tgz", - "integrity": "sha512-OK6Rs7EPdcdmjqiDycadZY4fw3f5/TC1X6/tGjnF3OosbwCeNs7nG+79MCAtjEg7ckwqTJTsku08e0Rmaz5nUw==", + "version": "16.16.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.16.0.tgz", + "integrity": "sha512-40X5UOb/0CEFnZVEHyN260HlSSUxPES+arrUphOumGWgXERHfwCD0kNBVILgQSij8iliYVwlc0V7M5bcLP9vPg==", "dev": true, "funding": [ { @@ -13119,7 +13130,7 @@ "debug": "^4.3.7", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.0.6", + "file-entry-cache": "^10.0.7", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -13593,22 +13604,22 @@ } }, "node_modules/tldts": { - "version": "6.1.82", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.82.tgz", - "integrity": "sha512-KCTjNL9F7j8MzxgfTgjT+v21oYH38OidFty7dH00maWANAI2IsLw2AnThtTJi9HKALHZKQQWnNebYheadacD+g==", + "version": "6.1.84", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.84.tgz", + "integrity": "sha512-aRGIbCIF3teodtUFAYSdQONVmDRy21REM3o6JnqWn5ZkQBJJ4gHxhw6OfwQ+WkSAi3ASamrS4N4nyazWx6uTYg==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.82" + "tldts-core": "^6.1.84" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.82", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.82.tgz", - "integrity": "sha512-Jabl32m21tt/d/PbDO88R43F8aY98Piiz6BVH9ShUlOAiiAELhEqwrAmBocjAqnCfoUeIsRU+h3IEzZd318F3w==", + "version": "6.1.84", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.84.tgz", + "integrity": "sha512-NaQa1W76W2aCGjXybvnMYzGSM4x8fvG2AN/pla7qxcg0ZHbooOPhA8kctmOZUDfZyhDL27OGNbwAeig8P4p1vg==", "dev": true, "license": "MIT" }, @@ -13654,9 +13665,9 @@ } }, "node_modules/tr46": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", + "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", "dev": true, "license": "MIT", "dependencies": { @@ -13925,9 +13936,9 @@ } }, "node_modules/undici": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.4.0.tgz", - "integrity": "sha512-PUQM3/es3noM24oUn10u3kNNap0AbxESOmnssmW+dOi9yGwlUSi5nTNYl3bNbTkWOF8YZDkx2tCmj9OtQ3iGGw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.5.0.tgz", + "integrity": "sha512-NFQG741e8mJ0fLQk90xKxFdaSM7z4+IQpAgsFI36bCDY9Z2+aXXZjVy2uUksMouWfMI9+w5ejOq5zYYTBCQJDQ==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -14175,13 +14186,13 @@ } }, "node_modules/whatwg-url": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.1.tgz", - "integrity": "sha512-mDGf9diDad/giZ/Sm9Xi2YcyzaFpbdLpJPr+E9fSkyQ7KpQD4SdFcugkRQYzhmfI4KeV4Qpnn2sKPdo+kmsgRQ==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "^5.0.0", + "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" }, "engines": { @@ -14268,15 +14279,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "for-each": "^0.3.3", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, diff --git a/package.json b/package.json index 11484b25d0..29f2428c2e 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "ansis": "^3.16.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.21.0", + "eslint": "^9.22.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -83,12 +83,12 @@ "undici": "^7.4.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^4.1.0", + "@stylistic/eslint-plugin": "^4.2.0", "cspell": "^8.17.5", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.3", - "eslint-plugin-package-json": "^0.26.0", + "eslint-plugin-jsdoc": "^50.6.8", + "eslint-plugin-package-json": "^0.29.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", @@ -96,9 +96,9 @@ "lint-staged": "^15.4.3", "markdownlint-cli2": "^0.17.2", "playwright": "^1.50.1", - "prettier": "^3.5.2", + "prettier": "^3.5.3", "sinon": "^19.0.2", - "stylelint": "^16.15.0", + "stylelint": "^16.16.0", "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.3" }, From 46d64abb4b122415f1a89ec9a22ba9fd46e481dd Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 21 Mar 2025 12:30:08 +0100 Subject: [PATCH 201/418] update required node version and dependencies (#3747) see discussion in https://github.com/MagicMirrorOrg/MagicMirror/pull/3746 As [electron v35 requires node js v22.14.0](https://www.electronjs.org/blog/electron-35-0) we should update this here too. --- .github/workflows/automated-tests.yaml | 2 +- .github/workflows/electron-rebuild.yaml | 2 +- CHANGELOG.md | 4 +- Collaboration.md | 2 +- fonts/package-lock.json | 26 ++++-- fonts/package.json | 4 +- package-lock.json | 118 ++++++++++++------------ package.json | 16 ++-- 8 files changed, 90 insertions(+), 84 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index f10850123f..f27439f634 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -38,7 +38,7 @@ jobs: timeout-minutes: 30 strategy: matrix: - node-version: [20.18.1, 20.x, 22.x, 23.x] + node-version: [22.14.0, 22.x, 23.x] steps: - name: Install electron dependencies and labwc run: | diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index fa3aec7106..30c03e4a86 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.18.1, 20.x, 22.x, 23.x] + node-version: [22.14.0, 22.x, 23.x] steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 902f35ba0e..779ac8f7c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 planned for 2025-04-01 -> ⚠️ This release needs nodejs version `v20` or `v22 or higher`, minimum version is `v20.18.1` +> ⚠️ This release needs nodejs version `v22.14.0 or higher` ### Added @@ -35,7 +35,7 @@ planned for 2025-04-01 ### Updated -- [core] Update dependencies incl. electron to v35 and formatting (#3593, #3693, #3717) +- [core] Update requirements and dependencies incl. electron to v35 and formatting (#3593, #3693, #3717) - [core] Update prettier, ESLint and simplify config - Update Greek translation diff --git a/Collaboration.md b/Collaboration.md index ddf18ef723..31dd855dcc 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -34,7 +34,7 @@ Are done by - [ ] test `develop` branch - [ ] update `CHANGELOG.md` - [ ] add all contributor names: `...` - - [ ] add min. node version: > ⚠️ This release needs nodejs version `v20` or `v22`, minimum version is `v20.9.0` + - [ ] add min. node version: > ⚠️ This release needs nodejs version `v22.14.0` or higher - [ ] check release link at the bottom of the file - [ ] commit and push all changes - [ ] after successful test run via github actions: merge pull request to `develop` diff --git a/fonts/package-lock.json b/fonts/package-lock.json index 084c98099e..0e5c7452a0 100644 --- a/fonts/package-lock.json +++ b/fonts/package-lock.json @@ -9,21 +9,27 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.2.0", - "@fontsource/roboto-condensed": "^5.2.0" + "@fontsource/roboto": "^5.2.5", + "@fontsource/roboto-condensed": "^5.2.5" } }, "node_modules/@fontsource/roboto": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.0.tgz", - "integrity": "sha512-RgDVfXtRZlMRBkzcVMETP0m5Xy8VaKAEnqTD2NFe34B6Qc2Xvn01Hxu3mdrF2My0YM0n4Iae5XWM7yzEsm4OZg==", - "license": "OFL-1.1" + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.5.tgz", + "integrity": "sha512-70r2UZ0raqLn5W+sPeKhqlf8wGvUXFWlofaDlcbt/S3d06+17gXKr3VNqDODB0I1ASme3dGT5OJj9NABt7OTZQ==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } }, "node_modules/@fontsource/roboto-condensed": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.2.0.tgz", - "integrity": "sha512-j4e8QCvz4J14nVYONSZI8X7M9uiMH8vxt3DT37IendV8FTtSvwvvok1oTpRXrWT0YHQ0mUTbl2XUmBsCTiX4Lg==", - "license": "OFL-1.1" + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.2.5.tgz", + "integrity": "sha512-FVubmVJpZ2js2+nCBEA3IOHhAgWmZ2/YKvTae0X25jlxbd85umOOvUIY6FL6OMpUvIgvwOImS9l0GJjzEPk+mg==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } } } } diff --git a/fonts/package.json b/fonts/package.json index fe497bc160..62d73e1546 100644 --- a/fonts/package.json +++ b/fonts/package.json @@ -11,7 +11,7 @@ }, "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.2.0", - "@fontsource/roboto-condensed": "^5.2.0" + "@fontsource/roboto": "^5.2.5", + "@fontsource/roboto-condensed": "^5.2.5" } } diff --git a/package-lock.json b/package-lock.json index cf24adbc9a..213dc4773d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,14 +11,14 @@ "license": "MIT", "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.16.0", + "ansis": "^3.17.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^9.22.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", - "helmet": "^8.0.0", + "helmet": "^8.1.0", "html-to-text": "^9.0.5", "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", @@ -28,7 +28,7 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.4.0" + "undici": "^7.5.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", @@ -41,20 +41,20 @@ "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^26.0.0", - "lint-staged": "^15.4.3", + "lint-staged": "^15.5.0", "markdownlint-cli2": "^0.17.2", - "playwright": "^1.50.1", + "playwright": "^1.51.1", "prettier": "^3.5.3", - "sinon": "^19.0.2", + "sinon": "^19.0.4", "stylelint": "^16.16.0", "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.3" }, "engines": { - "node": ">=20.18.1 <21 || >=22" + "node": ">=22.14.0" }, "optionalDependencies": { - "electron": "^35.0.0" + "electron": "^35.0.3" } }, "node_modules/@altano/repository-tools": { @@ -850,9 +850,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.34", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.34.tgz", - "integrity": "sha512-ewJXNV7Nk5vxbGvHvxYLDGoXN0Lq5sfSgX8SAlcYL+2bZ7r25nNOLHou5hdFlNgvviGTx/SFPlVKjdjVJlblgA==", + "version": "4.3.35", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.35.tgz", + "integrity": "sha512-HF6QNyPHkxeo/SosaZXRQlnKDUTjIzrGKyqfbw/fPPlPYrXefAZZ40ofheb5HnbUicR7xqV/lsc/HQfqYshGIw==", "dev": true, "license": "MIT" }, @@ -1038,9 +1038,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.30", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.30.tgz", - "integrity": "sha512-qRMJZFz4FBPECH5rGQN9p2Ld6nfpSaPFQvlG6V2RowWcrJQqF4RFmLUNuRQpvndpSeIUo32yX1hxb7AT45ARCQ==", + "version": "5.1.31", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.31.tgz", + "integrity": "sha512-Oh9nrhgNV4UD1hlbgO3TFQqQRKziwc7qXKoQiC4oqOYIhMs2WL9Ezozku7FY1e7o5XbCIZX9nRH0ymNx/Rwj6w==", "dev": true, "license": "MIT" }, @@ -2196,9 +2196,9 @@ } }, "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz", + "integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==", "dev": true, "license": "MIT", "engines": { @@ -2853,14 +2853,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz", - "integrity": "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", + "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.1", - "@typescript-eslint/visitor-keys": "8.26.1" + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2871,9 +2871,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.1.tgz", - "integrity": "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz", + "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", "dev": true, "license": "MIT", "engines": { @@ -2885,14 +2885,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz", - "integrity": "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", + "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.1", - "@typescript-eslint/visitor-keys": "8.26.1", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/visitor-keys": "8.27.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2912,16 +2912,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.1.tgz", - "integrity": "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz", + "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.26.1", - "@typescript-eslint/types": "8.26.1", - "@typescript-eslint/typescript-estree": "8.26.1" + "@typescript-eslint/scope-manager": "8.27.0", + "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/typescript-estree": "8.27.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2936,13 +2936,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz", - "integrity": "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==", + "version": "8.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", + "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.1", + "@typescript-eslint/types": "8.27.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3333,9 +3333,9 @@ } }, "node_modules/axios": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", - "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -5164,9 +5164,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "35.0.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-35.0.2.tgz", - "integrity": "sha512-jo8S4GfBpVIBDGitUrv+Vo/I/ZEEs6IvWprG2KJlxayYIKpufulbQaxDt78cC/79FwFo8MA0JOIwx/b9r5NRag==", + "version": "35.0.3", + "resolved": "https://registry.npmjs.org/electron/-/electron-35.0.3.tgz", + "integrity": "sha512-kjQAYEWXSr2TyK19IZoF85dzFIBaYuX7Yp/C+34b5Y/jmI2z270CGie+RjmEGMMitsy0G8YJKftukhYMuWlK6g==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5183,9 +5183,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.120", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.120.tgz", - "integrity": "sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ==", + "version": "1.5.123", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz", + "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==", "dev": true, "license": "ISC" }, @@ -10414,9 +10414,9 @@ "license": "ISC" }, "node_modules/nanoid": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", - "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -12515,14 +12515,14 @@ "license": "ISC" }, "node_modules/sinon": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", - "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.4.tgz", + "integrity": "sha512-myidFob7fjmYHJb+CHNLtAYScxn3sngGq4t75L2rCGGpE/k4OQVkN3KE5FsN+XkO2+fcDZ65PGvq3KHrlLAm7g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.2", + "@sinonjs/fake-timers": "^13.0.5", "@sinonjs/samsam": "^8.0.1", "diff": "^7.0.0", "nise": "^6.1.1", @@ -13678,9 +13678,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 29f2428c2e..4c7d43ddc2 100644 --- a/package.json +++ b/package.json @@ -63,14 +63,14 @@ }, "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.16.0", + "ansis": "^3.17.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^9.22.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", - "helmet": "^8.0.0", + "helmet": "^8.1.0", "html-to-text": "^9.0.5", "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", @@ -80,7 +80,7 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.4.0" + "undici": "^7.5.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", @@ -93,20 +93,20 @@ "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^26.0.0", - "lint-staged": "^15.4.3", + "lint-staged": "^15.5.0", "markdownlint-cli2": "^0.17.2", - "playwright": "^1.50.1", + "playwright": "^1.51.1", "prettier": "^3.5.3", - "sinon": "^19.0.2", + "sinon": "^19.0.4", "stylelint": "^16.16.0", "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.3" }, "optionalDependencies": { - "electron": "^35.0.0" + "electron": "^35.0.3" }, "engines": { - "node": ">=20.18.1 <21 || >=22" + "node": ">=22.14.0" }, "_moduleAliases": { "node_helper": "js/node_helper.js", From 791f77105a0873a124da70a7de048343bdaa3c9e Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 22 Mar 2025 21:23:10 +0100 Subject: [PATCH 202/418] fix stale job (#3751) exclude issues with label `ready (coming with next release)` from stale job --- .github/workflows/stale.yaml | 2 +- CHANGELOG.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index fd73269c86..800684df0a 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -19,4 +19,4 @@ jobs: days-before-issue-close: 7 operations-per-run: 100 stale-issue-label: "wontfix" - exempt-issue-labels: "pinned,security,under investigation,pr welcome" + exempt-issue-labels: "pinned,security,under investigation,pr welcome,ready (coming with next release)" diff --git a/CHANGELOG.md b/CHANGELOG.md index 779ac8f7c1..782f19fe9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ planned for 2025-04-01 - [weather/yr] The Yr weather provider now enforces a minimum `updateInterval` of 600 000 ms (10 minutes) to comply with the terms of service. If a lower value is set, it will be automatically increased to this minimum. - [weather/weatherflow] Fixed icons and added hourly support as well as UV, precipitation, and location name support. - [workflow] Run `sudo apt-get update` before installing packages to avoid install errors +- [workflow] Exclude issues with label `ready (coming with next release)` from stale job ### Removed From 2ddb7859f647ea2520cfdf36e7699143250d5487 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 27 Mar 2025 11:59:59 +0100 Subject: [PATCH 203/418] Fix command to run spellcheck (#3753) The command wasn't correct. --- .github/workflows/spellcheck.yaml | 2 +- CHANGELOG.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml index 78a13cdbe8..8e3b915d07 100644 --- a/.github/workflows/spellcheck.yaml +++ b/.github/workflows/spellcheck.yaml @@ -28,4 +28,4 @@ jobs: run: | npm run install-mm:dev - name: Run Spellcheck - run: npm run test:spellcheck + run: npm run test:spelling diff --git a/CHANGELOG.md b/CHANGELOG.md index 782f19fe9d..d1b8077b17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ planned for 2025-04-01 - [calendar] Fix NewYork event processed on system in Central timezone shows wrong time #3701 - [weather/yr] The Yr weather provider is now able to recover from bad API responses instead of freezing (#3296) - [compliments] Fix evening events being shown during the day (#3727) +- [workflow] Fix command to run spellcheck ## [2.30.0] - 2025-01-01 From 6d909d24e9125bb98861f920f2b054b83dfd762f Mon Sep 17 00:00:00 2001 From: OWL4C <124401812+OWL4C@users.noreply.github.com> Date: Thu, 27 Mar 2025 20:23:17 +0000 Subject: [PATCH 204/418] [weather] add humidity to hourly view, fix spacing error when using UV Index, add config option to hide precipitation entries that are zero [Rebased Version of PR #3526] (#3748) Fixed Version of PR #3526 since that was against the wrong branch and had issues. Original PR Text: Basically the title. Just some existing weather data included into hourly, some config option ("hideZeroes") to hide precipitation when it is zero (this actually shrinks the entire table, removing columns that are completely empty), and add a spacing column to fix the UV Index column. --------- Co-authored-by: Veeck --- CHANGELOG.md | 3 +++ modules/default/weather/hourly.njk | 18 ++++++++++++++---- modules/default/weather/weather.css | 1 + modules/default/weather/weather.js | 3 ++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1b8077b17..ec8349ac34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ planned for 2025-04-01 - Mark option `secondsColor` as deprecated in clock module. - Add Greek translation to Alerts module. - [newsfeed] Add specific ignoreOlderThan value (override) per feed (#3360) +- [weather] Added option Humidity to hourly View +- [weather] Added option to hide hourly entries that are Zero, hiding the entire column if empty. ### Changed @@ -50,6 +52,7 @@ planned for 2025-04-01 - [calendar] Fix NewYork event processed on system in Central timezone shows wrong time #3701 - [weather/yr] The Yr weather provider is now able to recover from bad API responses instead of freezing (#3296) - [compliments] Fix evening events being shown during the day (#3727) +- [weather] Fixed minor spacing issues when using UV Index in Hourly - [workflow] Fix command to run spellcheck ## [2.30.0] - 2025-01-01 diff --git a/modules/default/weather/hourly.njk b/modules/default/weather/hourly.njk index 0e464f77e6..4223390b30 100644 --- a/modules/default/weather/hourly.njk +++ b/modules/default/weather/hourly.njk @@ -21,15 +21,25 @@ {% endif %} {% endif %} + {% if config.showHumidity != "none" %} + + {{ hour.humidity }} + + + {% endif %} {% if config.showPrecipitationAmount %} - - {{ hour.precipitationAmount | unit("precip", hour.precipitationUnits) }} - + {% if (not config.hideZeroes or hour.precipitationAmount>0) %} + + {{ hour.precipitationAmount | unit("precip", hour.precipitationUnits) }} + + {% endif %} {% endif %} {% if config.showPrecipitationProbability %} + {% if (not config.hideZeroes or hour.precipitationAmount>0) %} - {{ hour.precipitationProbability | unit('precip', '%') }} + {{ hour.precipitationProbability | unit('precip', '%') }} + {% endif %} {% endif %} {% set currentStep = currentStep + 1 %} diff --git a/modules/default/weather/weather.css b/modules/default/weather/weather.css index 816f0a9b74..4618be9f94 100644 --- a/modules/default/weather/weather.css +++ b/modules/default/weather/weather.css @@ -31,6 +31,7 @@ .weather .precipitation-amount, .weather .precipitation-prob, +.weather .humidity-hourly, .weather .uv-index { padding-left: 20px; padding-right: 0; diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index 369a720101..448a905cf9 100644 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -14,7 +14,8 @@ Module.register("weather", { updateInterval: 10 * 60 * 1000, // every 10 minutes animationSpeed: 1000, showFeelsLike: true, - showHumidity: "none", // this is now a string; see current.njk + showHumidity: "none", // possible options for "current" weather are "none", "wind", "temp", "feelslike" or "below", for "hourly" weather "none" or "true" + hideZeroes: false, // hide zeroes (and empty columns) in hourly, currently only for precipitation showIndoorHumidity: false, showIndoorTemperature: false, allowOverrideNotification: false, From 2e57d785acf3dc205dcb7c025c7999a3d26266d3 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 28 Mar 2025 07:31:36 +0100 Subject: [PATCH 205/418] update dependencies (#3754) --- CHANGELOG.md | 2 +- package-lock.json | 525 ++++++++++++++++++++-------------------------- package.json | 14 +- 3 files changed, 239 insertions(+), 302 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec8349ac34..59c208695b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,7 @@ planned for 2025-04-01 ### Updated -- [core] Update requirements and dependencies incl. electron to v35 and formatting (#3593, #3693, #3717) +- [core] Update requirements and dependencies including electron to v35 and formatting (#3593, #3693, #3717) - [core] Update prettier, ESLint and simplify config - Update Greek translation diff --git a/package-lock.json b/package-lock.json index 213dc4773d..e890958688 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "ansis": "^3.17.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.22.0", + "eslint": "^9.23.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -28,14 +28,14 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.5.0" + "undici": "^7.6.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "cspell": "^8.17.5", + "cspell": "^8.18.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.8", + "eslint-plugin-jsdoc": "^50.6.9", "eslint-plugin-package-json": "^0.29.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", @@ -45,8 +45,8 @@ "markdownlint-cli2": "^0.17.2", "playwright": "^1.51.1", "prettier": "^3.5.3", - "sinon": "^19.0.4", - "stylelint": "^16.16.0", + "sinon": "^20.0.0", + "stylelint": "^16.17.0", "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.3" }, @@ -54,7 +54,7 @@ "node": ">=22.14.0" }, "optionalDependencies": { - "electron": "^35.0.3" + "electron": "^35.1.2" } }, "node_modules/@altano/repository-tools": { @@ -166,14 +166,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", - "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -183,13 +183,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.5", + "@babel/compat-data": "^7.26.8", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -282,27 +282,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", - "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10" + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", - "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.10" + "@babel/types": "^7.27.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -551,32 +551,32 @@ } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", - "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -595,9 +595,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", - "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, "license": "MIT", "dependencies": { @@ -616,9 +616,9 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.5.tgz", - "integrity": "sha512-b/Ntabar+g4gsRNwOct909cvatO/auHhNvBzJZfyFQzryI1nqHMaSFuDsrrtzbhQkGJ4GiMAKCXZC2EOdHMgmw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.18.0.tgz", + "integrity": "sha512-c7OkDgtYYg0rvj49YS/QzjKeGg/l/d+DjMDqP8BProhKDhAghCsvc6l3SHCGnvyw42+YSTVdL5uLBIaA1OKBlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -627,7 +627,7 @@ "@cspell/dict-aws": "^4.0.9", "@cspell/dict-bash": "^4.2.0", "@cspell/dict-companies": "^3.1.14", - "@cspell/dict-cpp": "^6.0.4", + "@cspell/dict-cpp": "^6.0.6", "@cspell/dict-cryptocurrencies": "^5.0.4", "@cspell/dict-csharp": "^4.0.6", "@cspell/dict-css": "^4.0.17", @@ -637,17 +637,17 @@ "@cspell/dict-docker": "^1.1.12", "@cspell/dict-dotnet": "^5.0.9", "@cspell/dict-elixir": "^4.0.7", - "@cspell/dict-en_us": "^4.3.33", - "@cspell/dict-en-common-misspellings": "^2.0.9", + "@cspell/dict-en_us": "^4.3.35", + "@cspell/dict-en-common-misspellings": "^2.0.10", "@cspell/dict-en-gb": "1.1.33", "@cspell/dict-filetypes": "^3.0.11", "@cspell/dict-flutter": "^1.1.0", "@cspell/dict-fonts": "^4.0.4", "@cspell/dict-fsharp": "^1.1.0", - "@cspell/dict-fullstack": "^3.2.5", + "@cspell/dict-fullstack": "^3.2.6", "@cspell/dict-gaming-terms": "^1.1.0", "@cspell/dict-git": "^3.0.4", - "@cspell/dict-golang": "^6.0.18", + "@cspell/dict-golang": "^6.0.19", "@cspell/dict-google": "^1.0.8", "@cspell/dict-haskell": "^4.0.5", "@cspell/dict-html": "^4.0.11", @@ -663,21 +663,21 @@ "@cspell/dict-markdown": "^2.0.9", "@cspell/dict-monkeyc": "^1.0.10", "@cspell/dict-node": "^5.0.6", - "@cspell/dict-npm": "^5.1.27", + "@cspell/dict-npm": "^5.1.31", "@cspell/dict-php": "^4.0.14", "@cspell/dict-powershell": "^5.0.14", "@cspell/dict-public-licenses": "^2.0.13", - "@cspell/dict-python": "^4.2.15", + "@cspell/dict-python": "^4.2.16", "@cspell/dict-r": "^2.1.0", - "@cspell/dict-ruby": "^5.0.7", + "@cspell/dict-ruby": "^5.0.8", "@cspell/dict-rust": "^4.0.11", "@cspell/dict-scala": "^5.0.7", "@cspell/dict-shell": "^1.1.0", - "@cspell/dict-software-terms": "^4.2.5", + "@cspell/dict-software-terms": "^5.0.2", "@cspell/dict-sql": "^2.2.0", "@cspell/dict-svelte": "^1.0.6", "@cspell/dict-swift": "^2.0.5", - "@cspell/dict-terraform": "^1.1.0", + "@cspell/dict-terraform": "^1.1.1", "@cspell/dict-typescript": "^3.2.0", "@cspell/dict-vue": "^3.0.4" }, @@ -686,22 +686,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.5.tgz", - "integrity": "sha512-+eVFCdnda74Frv8hguHYwDtxvqDuJJ/luFRl4dC5oknPMRab0JCHM1DDYjp3NzsehTex0HmcxplxqVW6QoDosg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.18.0.tgz", + "integrity": "sha512-glUYtRJ/xIgvCvFqgcF04RJiTFhL95wl1uirP+Qa+oqxvg/zP9zxsZupLD3aeMFhyDpgYwtBiebUmhSqrLDyaw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.17.5" + "@cspell/cspell-types": "8.18.0" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.5.tgz", - "integrity": "sha512-VOIfFdIo3FYQFcSpIyGkqHupOx0LgfBrWs79IKnTT1II27VUHPF+0oGq0WWf4c2Zpd8tzdHvS3IUhGarWZq69g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.18.0.tgz", + "integrity": "sha512-bSFncsV16B9nhHJdSMTCzdC0Su/TKs+JGTuCq2UiNi6vWxvsL/S1ueiRb+HT0WYKROwtAeHEKnjlw0G3OBBuFw==", "dev": true, "license": "MIT", "engines": { @@ -709,9 +709,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.5.tgz", - "integrity": "sha512-5MhYInligPbGctWxoklAKxtg+sxvtJCuRKGSQHHA0JlCOLSsducypl780P6zvpjLK59XmdfC+wtFONxSmRbsuA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.18.0.tgz", + "integrity": "sha512-kNQJtYYJg6WpLoDUZW8VodovOtKLiDrb+GXmcee01qQmrEPCuub9gwoiRuka0sHI2logz0S8l9eAittClpxReg==", "dev": true, "license": "MIT", "dependencies": { @@ -722,9 +722,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.5.tgz", - "integrity": "sha512-Ur3IK0R92G/2J6roopG9cU/EhoYAMOx2um7KYlq93cdrly8RBAK2NCcGCL7DbjQB6C9RYEAV60ueMUnQ45RrCQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.18.0.tgz", + "integrity": "sha512-yGnb59tUadd1q9dSIvg+Q8yZc7N2ZloZ8Sc5lAfxKOJWUh91ugu2UizmL4lm82vDrOevL3kryiauVTsjoS+UOg==", "dev": true, "license": "MIT", "engines": { @@ -732,9 +732,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.5.tgz", - "integrity": "sha512-91y2+0teunRSRZj940ORDA3kdjyenrUiM+4j6nQQH24sAIAJdRmQl2LG3eUTmeaSReJGkZIpnToQ6DyU5cC88Q==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.18.0.tgz", + "integrity": "sha512-z7ETwulTCAHpSNBqwD5d3Uoui4ClD+tfREoD0cKd9uMbLtN9W/WMVQAGDWJpOCUFrWsGYYM3/3/ob2oZhwdQag==", "dev": true, "license": "MIT", "engines": { @@ -1111,9 +1111,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.5.tgz", - "integrity": "sha512-CaRzkWti3AgcXoxuRcMijaNG7YUk/MH1rHjB8VX34v3UdCxXXeqvRyElRKnxhFeVLB/robb2UdShqh/CpskxRg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.0.2.tgz", + "integrity": "sha512-aCzP+M0WXRLYXTriDMZygUe5s4jKyau/nCA6gBGt4EoHfXn+Ua/+DrW766oXOkkESIlqTBtRgb9gWwQvUdOXSQ==", "dev": true, "license": "MIT" }, @@ -1160,13 +1160,13 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.5.tgz", - "integrity": "sha512-tY+cVkRou+0VKvH+K1NXv8/R7mOlW3BDGSs9fcgvhatj0m00Yf8blFC7tE4VVI9Qh2bkC/KDFqM24IqZbuwXUQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.18.0.tgz", + "integrity": "sha512-TPdY/x9l0DAWCSI8iXDEQSl0xlB9qSbEqIv3UYVpWqbQYCY7MdA15bmai8uKt08sZ8F9L6nYHPtbOGFExHvoSw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.5", + "@cspell/url": "8.18.0", "import-meta-resolve": "^4.1.0" }, "engines": { @@ -1174,9 +1174,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.5.tgz", - "integrity": "sha512-Fj6py2Rl+FEnMiXhRQUM1A5QmyeCLxi6dY/vQ0qfH6tp6KSaBiaC8wuPUKhr8hKyTd3+8lkUbobDhUf6xtMEXg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.18.0.tgz", + "integrity": "sha512-Qd+Fc9CfkCm4Kufe/H8jCLe5px3PwiKmJgdiZ6FJ0i06MU+0XHZGmzWayrL+EoTqfbQA3jLkvnSgWwF0C6Ci6Q==", "dev": true, "license": "MIT", "engines": { @@ -1184,9 +1184,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.5.tgz", - "integrity": "sha512-Z4eo+rZJr1086wZWycBiIG/n7gGvVoqn28I7ZicS8xedRYu/4yp2loHgLn4NpxG3e46+dNWs4La6vinod+UydQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.18.0.tgz", + "integrity": "sha512-u8j+1JsnzJv10c7KaGzCdp8mJ3IL0tJ601+ySdebqVL4VNVKE1OcEV+sYxMjrXbeXkPGlpSwr+yDKMW1WHaC7A==", "dev": true, "license": "MIT", "engines": { @@ -1194,9 +1194,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.5.tgz", - "integrity": "sha512-GNQqST7zI85dAFVyao6oiTeg5rNhO9FH1ZAd397qQhvwfxrrniNfuoewu8gPXyP0R4XBiiaCwhBL7w9S/F5guw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.18.0.tgz", + "integrity": "sha512-jbo66L7Y5WImty4o2s5sL6LwTSHS6XjZDKEUayqxILyNb5XHKRUinyII1/EpglFRi9n7G5w4t714/Aeg1Y90Vg==", "dev": true, "license": "MIT", "engines": { @@ -1509,9 +1509,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", - "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", + "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1530,9 +1530,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", - "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -1597,9 +1597,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.22.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", - "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", + "version": "9.23.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", + "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2576,13 +2576,6 @@ "node": ">=4" } }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" - }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -2664,9 +2657,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", "dev": true, "license": "MIT", "dependencies": { @@ -2706,9 +2699,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "license": "MIT" }, "node_modules/@types/graceful-fs": { @@ -2793,9 +2786,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", - "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "version": "22.13.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", + "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -2853,14 +2846,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", - "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz", + "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0" + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2871,9 +2864,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz", - "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz", + "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==", "dev": true, "license": "MIT", "engines": { @@ -2885,14 +2878,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", - "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz", + "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0", + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2912,16 +2905,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz", - "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz", + "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.27.0", - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/typescript-estree": "8.27.0" + "@typescript-eslint/scope-manager": "8.28.0", + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/typescript-estree": "8.28.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2936,13 +2929,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", - "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz", + "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/types": "8.28.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3861,9 +3854,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001706", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", - "integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==", + "version": "1.0.30001707", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", + "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", "dev": true, "funding": [ { @@ -4458,25 +4451,25 @@ } }, "node_modules/cspell": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.5.tgz", - "integrity": "sha512-l3Cfp87d7Yrodem675irdxV6+7+OsdR+jNwYHe33Dgnd6ePEfooYrvmfGdXF9rlQrNLUQp/HqYgHJzSq19UEsg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.18.0.tgz", + "integrity": "sha512-+6lJaR4zI/250vAR3qXwRj9O80Q4dHUuJWVXCZQV2L6HdF+s5ThS7+HYmE5zdf1YpPCtYJJ/6stkKsdUCQtkTA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.17.5", - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-types": "8.17.5", - "@cspell/dynamic-import": "8.17.5", - "@cspell/url": "8.17.5", + "@cspell/cspell-json-reporter": "8.18.0", + "@cspell/cspell-pipe": "8.18.0", + "@cspell/cspell-types": "8.18.0", + "@cspell/dynamic-import": "8.18.0", + "@cspell/url": "8.18.0", "chalk": "^5.4.1", "chalk-template": "^1.1.0", "commander": "^13.1.0", - "cspell-dictionary": "8.17.5", - "cspell-gitignore": "8.17.5", - "cspell-glob": "8.17.5", - "cspell-io": "8.17.5", - "cspell-lib": "8.17.5", + "cspell-dictionary": "8.18.0", + "cspell-gitignore": "8.18.0", + "cspell-glob": "8.18.0", + "cspell-io": "8.18.0", + "cspell-lib": "8.18.0", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", @@ -4495,13 +4488,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.5.tgz", - "integrity": "sha512-XDc+UJO5RZ9S9e2Ajz332XjT7dv6Og2UqCiSnAlvHt7t/MacLHSPARZFIivheObNkWZ7E1iWI681RxKoH4o40w==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.18.0.tgz", + "integrity": "sha512-Y0hos8IS1rzmU9lTl6v1q6MBr6v9nhJy5IacZXSJhBSTHRYemsvICTnn+PtksUFgrEEqWusOdAsgBhYV0nlSuw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.17.5", + "@cspell/cspell-types": "8.18.0", "comment-json": "^4.2.5", "yaml": "^2.7.0" }, @@ -4510,15 +4503,15 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.5.tgz", - "integrity": "sha512-O/Uuhv1RuDu+5WYQml0surudweaTvr+2YJSmPSdlihByUSiogCbpGqwrRow7wQv/C5p1W1FlFjotvUfoR0fxHA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.18.0.tgz", + "integrity": "sha512-yf7anUDHYFPuQ53619BILYswm4E08NzyNPO1cF0GyqGe5ZTTHf/rCNYcuZHtQ7yKmQuC/K8/y2kEeLsqNa0p6A==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-types": "8.17.5", - "cspell-trie-lib": "8.17.5", + "@cspell/cspell-pipe": "8.18.0", + "@cspell/cspell-types": "8.18.0", + "cspell-trie-lib": "8.18.0", "fast-equals": "^5.2.2" }, "engines": { @@ -4526,16 +4519,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.5.tgz", - "integrity": "sha512-I27fgOUZzH14jeIYo65LooB60fZ42f6OJL1lOR9Mk6IrIlDyUtzherGR+xx5KshK2katYkX42Qu4zsVYM6VFPA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.18.0.tgz", + "integrity": "sha512-HYWAK7282o9CkcMwqC3w1wNjgae1v4CMgzF3ptpyBonjISkj1GdFGMno4Gu2uW43aKGTmyj4Fi9J94UZvzZa4w==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.5", - "cspell-glob": "8.17.5", - "cspell-io": "8.17.5", - "find-up-simple": "^1.0.0" + "@cspell/url": "8.18.0", + "cspell-glob": "8.18.0", + "cspell-io": "8.18.0" }, "bin": { "cspell-gitignore": "bin.mjs" @@ -4545,13 +4537,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.5.tgz", - "integrity": "sha512-OXquou7UykInlGV5et5lNKYYrW0dwa28aEF995x1ocANND7o0bbHmFlbgyci/Lp4uFQai8sifmfFJbuIg2IC/A==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.18.0.tgz", + "integrity": "sha512-ox3ygu5+3tXR3+XRbYJy/z+YK1zo4TFQFkvUEr+aV8Ogyvgm7qE9uTaFz6krkkMLNG6l8EZ7mJtdn0ZsXF/WKQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.17.5", + "@cspell/url": "8.18.0", "micromatch": "^4.0.8" }, "engines": { @@ -4559,14 +4551,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.5.tgz", - "integrity": "sha512-st2n+FVw25MvMbsGb3TeJNRr6Oih4g14rjOd/UJN0qn+ceH360SAShUFqSd4kHHu2ADazI/TESFU6FRtMTPNOg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.18.0.tgz", + "integrity": "sha512-/h8gLULvH+P+8N/cmIx8M85sqlER6AyO/RoCVudfq7lTkFneXXKmCoHSA2YQbod9ZSjL+voivBokN2yjMR+XEA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-types": "8.17.5" + "@cspell/cspell-pipe": "8.18.0", + "@cspell/cspell-types": "8.18.0" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4576,42 +4568,42 @@ } }, "node_modules/cspell-io": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.5.tgz", - "integrity": "sha512-oevM/8l0s6nc1NCYPqNFumrW50QSHoa6wqUT8cWs09gtZdE2AWG0U6bIE8ZEVz6e6FxS+6IenGKTdUUwP0+3fg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.18.0.tgz", + "integrity": "sha512-W6CfXY5dlGTd6XWgHl4B2qLD/gla9TXDVdSo3ViCMJoVu82UQD8b4mir5RfHqXiMrz7ItDeUy9BxFN42VB2YcA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.17.5", - "@cspell/url": "8.17.5" + "@cspell/cspell-service-bus": "8.18.0", + "@cspell/url": "8.18.0" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.5.tgz", - "integrity": "sha512-S3KuOrcST1d2BYmTXA+hnbRdho5n3w5GUvEaCx3QZQBwAPfLpAwJbe2yig1TxBpyEJ5LqP02i/mDg1pUCOP0hQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.18.0.tgz", + "integrity": "sha512-346CAY12pVk40FWnfPOwajKug61EeawW3QMtJE/f6rMYGAjGxGExhZnl6eR/KuCMt/w60kqQMSjGDw2zJjJqUw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.17.5", - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-resolver": "8.17.5", - "@cspell/cspell-types": "8.17.5", - "@cspell/dynamic-import": "8.17.5", - "@cspell/filetypes": "8.17.5", - "@cspell/strong-weak-map": "8.17.5", - "@cspell/url": "8.17.5", + "@cspell/cspell-bundled-dicts": "8.18.0", + "@cspell/cspell-pipe": "8.18.0", + "@cspell/cspell-resolver": "8.18.0", + "@cspell/cspell-types": "8.18.0", + "@cspell/dynamic-import": "8.18.0", + "@cspell/filetypes": "8.18.0", + "@cspell/strong-weak-map": "8.18.0", + "@cspell/url": "8.18.0", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.17.5", - "cspell-dictionary": "8.17.5", - "cspell-glob": "8.17.5", - "cspell-grammar": "8.17.5", - "cspell-io": "8.17.5", - "cspell-trie-lib": "8.17.5", + "cspell-config-lib": "8.18.0", + "cspell-dictionary": "8.18.0", + "cspell-glob": "8.18.0", + "cspell-grammar": "8.18.0", + "cspell-io": "8.18.0", + "cspell-trie-lib": "8.18.0", "env-paths": "^3.0.0", "fast-equals": "^5.2.2", "gensequence": "^7.0.0", @@ -4626,14 +4618,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.5.tgz", - "integrity": "sha512-9hjI3nRQxtGEua6CgnLbK3sGHLx9dXR/BHwI/csRL4dN5GGRkE5X3CCoy1RJVL7iGFLIzi43+L10xeFRmWniKw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.18.0.tgz", + "integrity": "sha512-zhrCAHyQ2uiGpFdp6E336/L2oDTh/0fM22VpGbkBS4uYKqG9jMy4eUZdSKS8Lg3St4YdGK14J7dv/PiMLqqxlw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-types": "8.17.5", + "@cspell/cspell-pipe": "8.18.0", + "@cspell/cspell-types": "8.18.0", "gensequence": "^7.0.0" }, "engines": { @@ -5164,9 +5156,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "35.0.3", - "resolved": "https://registry.npmjs.org/electron/-/electron-35.0.3.tgz", - "integrity": "sha512-kjQAYEWXSr2TyK19IZoF85dzFIBaYuX7Yp/C+34b5Y/jmI2z270CGie+RjmEGMMitsy0G8YJKftukhYMuWlK6g==", + "version": "35.1.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-35.1.2.tgz", + "integrity": "sha512-ipYSDZEV3+PpHfJ8/oWlpMCvxwutX6xLvBz2HRPgEzSFzgLmGO7YXTjEow4DhDtCpGE+b95NTGoJaRAVQi5n7A==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5183,9 +5175,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.123", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz", - "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==", + "version": "1.5.127", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.127.tgz", + "integrity": "sha512-Ke5OggqOtEqzCzcUyV+9jgO6L6sv1gQVKGtSExXHjD/FK0p4qzPZbrDsrCdy0DptcQprD0V80RCBYSWLMhTTgQ==", "dev": true, "license": "ISC" }, @@ -5610,18 +5602,18 @@ } }, "node_modules/eslint": { - "version": "9.22.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", - "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", + "version": "9.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", + "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", - "@eslint/config-helpers": "^0.1.0", + "@eslint/config-helpers": "^0.2.0", "@eslint/core": "^0.12.0", - "@eslint/eslintrc": "^3.3.0", - "@eslint/js": "9.22.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.23.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5843,9 +5835,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.8.tgz", - "integrity": "sha512-PPZVqhoXaalMQwDGzcQrJtPSPIPOYsSMtvkjYAdsIazOW20yhYtVX4+jLL+XznD4zYTXyZbPWPRKkNev4D4lyw==", + "version": "50.6.9", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.9.tgz", + "integrity": "sha512-7/nHu3FWD4QRG8tCVqcv+BfFtctUtEDWc29oeDXB4bwmDM2/r1ndl14AG/2DUntdqH7qmpvdemJKwb3R97/QEw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -6498,19 +6490,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up-simple": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", - "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/flat-cache": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", @@ -8976,13 +8955,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/just-extend": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true, - "license": "MIT" - }, "node_modules/katex": { "version": "0.16.21", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz", @@ -10390,9 +10362,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.47", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.47.tgz", - "integrity": "sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==", + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -10500,40 +10472,6 @@ "node": ">= 0.4.0" } }, - "node_modules/nise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", - "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.1", - "@sinonjs/text-encoding": "^0.7.3", - "just-extend": "^6.2.0", - "path-to-regexp": "^8.1.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, "node_modules/node-ical": { "version": "0.20.1", "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.20.1.tgz", @@ -11116,9 +11054,9 @@ } }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, "license": "MIT", "engines": { @@ -12515,9 +12453,9 @@ "license": "ISC" }, "node_modules/sinon": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.4.tgz", - "integrity": "sha512-myidFob7fjmYHJb+CHNLtAYScxn3sngGq4t75L2rCGGpE/k4OQVkN3KE5FsN+XkO2+fcDZ65PGvq3KHrlLAm7g==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-20.0.0.tgz", + "integrity": "sha512-+FXOAbdnj94AQIxH0w1v8gzNxkawVvNqE3jUzRLptR71Oykeu2RrQXXl/VQjKay+Qnh73fDt/oDfMo6xMeDQbQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -12525,7 +12463,6 @@ "@sinonjs/fake-timers": "^13.0.5", "@sinonjs/samsam": "^8.0.1", "diff": "^7.0.0", - "nise": "^6.1.1", "supports-color": "^7.2.0" }, "funding": { @@ -13101,9 +13038,9 @@ } }, "node_modules/stylelint": { - "version": "16.16.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.16.0.tgz", - "integrity": "sha512-40X5UOb/0CEFnZVEHyN260HlSSUxPES+arrUphOumGWgXERHfwCD0kNBVILgQSij8iliYVwlc0V7M5bcLP9vPg==", + "version": "16.17.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.17.0.tgz", + "integrity": "sha512-I9OwVIWRMqVm2Br5iTbrfSqGRPWQUlvm6oXO1xZuYYu0Gpduy67N8wXOZv15p6E/JdlZiAtQaIoLKZEWk5hrjw==", "dev": true, "funding": [ { @@ -13604,22 +13541,22 @@ } }, "node_modules/tldts": { - "version": "6.1.84", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.84.tgz", - "integrity": "sha512-aRGIbCIF3teodtUFAYSdQONVmDRy21REM3o6JnqWn5ZkQBJJ4gHxhw6OfwQ+WkSAi3ASamrS4N4nyazWx6uTYg==", + "version": "6.1.85", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.85.tgz", + "integrity": "sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.84" + "tldts-core": "^6.1.85" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.84", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.84.tgz", - "integrity": "sha512-NaQa1W76W2aCGjXybvnMYzGSM4x8fvG2AN/pla7qxcg0ZHbooOPhA8kctmOZUDfZyhDL27OGNbwAeig8P4p1vg==", + "version": "6.1.85", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz", + "integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==", "dev": true, "license": "MIT" }, @@ -13936,9 +13873,9 @@ } }, "node_modules/undici": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.5.0.tgz", - "integrity": "sha512-NFQG741e8mJ0fLQk90xKxFdaSM7z4+IQpAgsFI36bCDY9Z2+aXXZjVy2uUksMouWfMI9+w5ejOq5zYYTBCQJDQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.6.0.tgz", + "integrity": "sha512-gaFsbThjrDGvAaD670r81RZro/s6H2PVZF640Qn0p5kZK+/rim7/mmyfp2W7VB5vOMaFM8vuFBJUaMlaZTYHlA==", "license": "MIT", "engines": { "node": ">=20.18.1" diff --git a/package.json b/package.json index 4c7d43ddc2..68e613c5d0 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "ansis": "^3.17.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.22.0", + "eslint": "^9.23.0", "express": "^4.21.2", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -80,14 +80,14 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.5.0" + "undici": "^7.6.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "cspell": "^8.17.5", + "cspell": "^8.18.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.8", + "eslint-plugin-jsdoc": "^50.6.9", "eslint-plugin-package-json": "^0.29.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", @@ -97,13 +97,13 @@ "markdownlint-cli2": "^0.17.2", "playwright": "^1.51.1", "prettier": "^3.5.3", - "sinon": "^19.0.4", - "stylelint": "^16.16.0", + "sinon": "^20.0.0", + "stylelint": "^16.17.0", "stylelint-config-standard": "^37.0.0", "stylelint-prettier": "^5.0.3" }, "optionalDependencies": { - "electron": "^35.0.3" + "electron": "^35.1.2" }, "engines": { "node": ">=22.14.0" From e546fedeb13d1af5a0e59497a4bc4d9a610bc369 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 31 Mar 2025 17:57:42 +0200 Subject: [PATCH 206/418] =?UTF-8?q?updatenotification:=20add=20param=20to?= =?UTF-8?q?=20get=20modules=20from=20modules-dir=20instead=E2=80=A6=20(#37?= =?UTF-8?q?55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … from config implements #3739 --- CHANGELOG.md | 1 + .../default/updatenotification/node_helper.js | 19 ++++++++++++++++++- .../updatenotification/updatenotification.js | 3 ++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59c208695b..348fcc107b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ planned for 2025-04-01 - [newsfeed] Add specific ignoreOlderThan value (override) per feed (#3360) - [weather] Added option Humidity to hourly View - [weather] Added option to hide hourly entries that are Zero, hiding the entire column if empty. +- [updatenotification] Added option to iterate over modules directory instead using modules defined in `config.js` (#3739) ### Changed diff --git a/modules/default/updatenotification/node_helper.js b/modules/default/updatenotification/node_helper.js index c78f413dc9..88264f7c36 100644 --- a/modules/default/updatenotification/node_helper.js +++ b/modules/default/updatenotification/node_helper.js @@ -1,3 +1,5 @@ +const fs = require("node:fs"); +const path = require("node:path"); const NodeHelper = require("node_helper"); const defaultModules = require("../defaultmodules"); const GitHelper = require("./git_helper"); @@ -14,8 +16,23 @@ module.exports = NodeHelper.create({ gitHelper: new GitHelper(), updateHelper: null, + getModules (modules) { + if (this.config.useModulesFromConfig) { + return modules; + } else { + // get modules from modules-directory + const moduleDir = path.normalize(`${__dirname}/../../`); + const getDirectories = (source) => { + return fs.readdirSync(source, { withFileTypes: true }) + .filter((dirent) => dirent.isDirectory() && dirent.name !== "default") + .map((dirent) => dirent.name); + }; + return getDirectories(moduleDir); + } + }, + async configureModules (modules) { - for (const moduleName of modules) { + for (const moduleName of this.getModules(modules)) { if (!this.ignoreUpdateChecking(moduleName)) { await this.gitHelper.add(moduleName); } diff --git a/modules/default/updatenotification/updatenotification.js b/modules/default/updatenotification/updatenotification.js index a18bc4db0e..f3d661fc58 100644 --- a/modules/default/updatenotification/updatenotification.js +++ b/modules/default/updatenotification/updatenotification.js @@ -6,7 +6,8 @@ Module.register("updatenotification", { sendUpdatesNotifications: false, updates: [], updateTimeout: 2 * 60 * 1000, // max update duration - updateAutorestart: false // autoRestart MM when update done ? + updateAutorestart: false, // autoRestart MM when update done ? + useModulesFromConfig: true // if `false` iterate over modules directory }, suspended: false, From f80b1f1321843f4a0fde9531bfffcc15bf72bd14 Mon Sep 17 00:00:00 2001 From: Veeck Date: Tue, 1 Apr 2025 08:33:31 +0200 Subject: [PATCH 207/418] Update deps before release (#3756) Co-authored-by: veeck --- CHANGELOG.md | 2 +- package-lock.json | 196 +++++++++++++++++++-------------------- package.json | 2 +- vendor/package-lock.json | 8 +- vendor/package.json | 2 +- 5 files changed, 105 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 348fcc107b..52d0d2708a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -216,7 +216,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T ### Updated -- Update updatenotification (update_helper.js): Recode with pm2 library (#3332) +- [updatenotification] Recode update_helper.js with pm2 library (#3332) - Removing lodash dependency by replacing merge by spread operator (#3339) - Use node prefix for build-in modules (#3340) - Rework logging colors (#3350) diff --git a/package-lock.json b/package-lock.json index e890958688..da455afb3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,7 +32,7 @@ }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "cspell": "^8.18.0", + "cspell": "^8.18.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-jsdoc": "^50.6.9", @@ -616,9 +616,9 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.18.0.tgz", - "integrity": "sha512-c7OkDgtYYg0rvj49YS/QzjKeGg/l/d+DjMDqP8BProhKDhAghCsvc6l3SHCGnvyw42+YSTVdL5uLBIaA1OKBlQ==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.18.1.tgz", + "integrity": "sha512-gxciVVfQqCVXYH0p2Q5D7x7/SgaW3Wv5UjRwO+TCme0P2lVLl/IcfjkujZX+6UQkT7X4QRglXo1QN141UcCRCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -686,22 +686,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.18.0.tgz", - "integrity": "sha512-glUYtRJ/xIgvCvFqgcF04RJiTFhL95wl1uirP+Qa+oqxvg/zP9zxsZupLD3aeMFhyDpgYwtBiebUmhSqrLDyaw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.18.1.tgz", + "integrity": "sha512-/U3/8bcOL5O35fI9F7nN7Mhic0K01ZRxRV/+5jj7atltBbqgFSxViHCZBX0lDZJM96gUHn+3r6q6/8VEJahpDA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.18.0" + "@cspell/cspell-types": "8.18.1" }, "engines": { "node": ">=18" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.18.0.tgz", - "integrity": "sha512-bSFncsV16B9nhHJdSMTCzdC0Su/TKs+JGTuCq2UiNi6vWxvsL/S1ueiRb+HT0WYKROwtAeHEKnjlw0G3OBBuFw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.18.1.tgz", + "integrity": "sha512-QHndTQPkR1c02pvvQ7UKFtLjCXgY0OcX8zjTLrCkynmcQxJFjAZAh9cJ7NMOAxab+ciSnkaVf4KWaRSEG17z8Q==", "dev": true, "license": "MIT", "engines": { @@ -709,9 +709,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.18.0.tgz", - "integrity": "sha512-kNQJtYYJg6WpLoDUZW8VodovOtKLiDrb+GXmcee01qQmrEPCuub9gwoiRuka0sHI2logz0S8l9eAittClpxReg==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.18.1.tgz", + "integrity": "sha512-T2sUBv0p9Hnfyg1xT1u3ESKuIWaaIDo0I8idh5DSlTpHgLjdIeAwasmFjEJ28qZv8OKSGawcSQKgJbStfbZASQ==", "dev": true, "license": "MIT", "dependencies": { @@ -722,9 +722,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.18.0.tgz", - "integrity": "sha512-yGnb59tUadd1q9dSIvg+Q8yZc7N2ZloZ8Sc5lAfxKOJWUh91ugu2UizmL4lm82vDrOevL3kryiauVTsjoS+UOg==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.18.1.tgz", + "integrity": "sha512-PwWl7EyhGIu4wHEhvBJb6xVlqMtFwQk0qLDArBvugL6nA+MX9NfG/w7PTgS7tCkFjVF1ku2sDzDLTDWwEk+MLw==", "dev": true, "license": "MIT", "engines": { @@ -732,9 +732,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.18.0.tgz", - "integrity": "sha512-z7ETwulTCAHpSNBqwD5d3Uoui4ClD+tfREoD0cKd9uMbLtN9W/WMVQAGDWJpOCUFrWsGYYM3/3/ob2oZhwdQag==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.18.1.tgz", + "integrity": "sha512-d/nMG+qnMbI/1JPm+lD0KcKpgtEHMRsHxkdtGyNCDgvHL/JOGaSHc5ERS3IUgBW0Dfya/3z9wPdaMcHEzt7YCQ==", "dev": true, "license": "MIT", "engines": { @@ -1160,13 +1160,13 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.18.0.tgz", - "integrity": "sha512-TPdY/x9l0DAWCSI8iXDEQSl0xlB9qSbEqIv3UYVpWqbQYCY7MdA15bmai8uKt08sZ8F9L6nYHPtbOGFExHvoSw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.18.1.tgz", + "integrity": "sha512-VJHfS/Iv0Rx7wn1pjPmwgsaw6r72N5Cx2gL0slWk8Cogc8YiK7/6jsGnsvxJZVkHntJoiT8PrkIvhNKb3awD3g==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.18.0", + "@cspell/url": "8.18.1", "import-meta-resolve": "^4.1.0" }, "engines": { @@ -1174,9 +1174,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.18.0.tgz", - "integrity": "sha512-Qd+Fc9CfkCm4Kufe/H8jCLe5px3PwiKmJgdiZ6FJ0i06MU+0XHZGmzWayrL+EoTqfbQA3jLkvnSgWwF0C6Ci6Q==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.18.1.tgz", + "integrity": "sha512-vTOb2itP0pjrccvt8wcKiTGyw0pFMTPI85H12T6n8ZhqXTktPgQH2gEf/SU/5tkPNnBKr4GJ+FdU5hJ27HzgXQ==", "dev": true, "license": "MIT", "engines": { @@ -1184,9 +1184,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.18.0.tgz", - "integrity": "sha512-u8j+1JsnzJv10c7KaGzCdp8mJ3IL0tJ601+ySdebqVL4VNVKE1OcEV+sYxMjrXbeXkPGlpSwr+yDKMW1WHaC7A==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.18.1.tgz", + "integrity": "sha512-gsgv+5ZQD4aHNHDdfNGoafVYkqRynyYgaodt9Dp/3o0YKYcxGf2jrX8SJ35MfZ61qln0n7P4Djrg+bFV2zNH5w==", "dev": true, "license": "MIT", "engines": { @@ -1194,9 +1194,9 @@ } }, "node_modules/@cspell/url": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.18.0.tgz", - "integrity": "sha512-jbo66L7Y5WImty4o2s5sL6LwTSHS6XjZDKEUayqxILyNb5XHKRUinyII1/EpglFRi9n7G5w4t714/Aeg1Y90Vg==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.18.1.tgz", + "integrity": "sha512-FRJbLYDC9ucpTOzbF6MohP2u5X3NU5L0RoVuoYCynqm/QOI38XP6WOEaI4H58CAn857bOIKZk0LZRPTGzi6Qlg==", "dev": true, "license": "MIT", "engines": { @@ -4451,25 +4451,25 @@ } }, "node_modules/cspell": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.18.0.tgz", - "integrity": "sha512-+6lJaR4zI/250vAR3qXwRj9O80Q4dHUuJWVXCZQV2L6HdF+s5ThS7+HYmE5zdf1YpPCtYJJ/6stkKsdUCQtkTA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.18.1.tgz", + "integrity": "sha512-RE3LIgN9NAVcYBNX2NQVhLergok8EPymOuCUhu1vBR8cjRmioksn3CJeCoQgD8rPjalM+S9thYkMtOZc5Jjv2A==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.18.0", - "@cspell/cspell-pipe": "8.18.0", - "@cspell/cspell-types": "8.18.0", - "@cspell/dynamic-import": "8.18.0", - "@cspell/url": "8.18.0", + "@cspell/cspell-json-reporter": "8.18.1", + "@cspell/cspell-pipe": "8.18.1", + "@cspell/cspell-types": "8.18.1", + "@cspell/dynamic-import": "8.18.1", + "@cspell/url": "8.18.1", "chalk": "^5.4.1", "chalk-template": "^1.1.0", "commander": "^13.1.0", - "cspell-dictionary": "8.18.0", - "cspell-gitignore": "8.18.0", - "cspell-glob": "8.18.0", - "cspell-io": "8.18.0", - "cspell-lib": "8.18.0", + "cspell-dictionary": "8.18.1", + "cspell-gitignore": "8.18.1", + "cspell-glob": "8.18.1", + "cspell-io": "8.18.1", + "cspell-lib": "8.18.1", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", "get-stdin": "^9.0.0", @@ -4488,13 +4488,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.18.0.tgz", - "integrity": "sha512-Y0hos8IS1rzmU9lTl6v1q6MBr6v9nhJy5IacZXSJhBSTHRYemsvICTnn+PtksUFgrEEqWusOdAsgBhYV0nlSuw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.18.1.tgz", + "integrity": "sha512-zdJ0uhLROSUrHoibysPw+AkxKPUmiG95hDtiL7s8smewkuaS1hpjqwsDBx981nHYs3xW3qDUfVATrAkSzb0VMw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.18.0", + "@cspell/cspell-types": "8.18.1", "comment-json": "^4.2.5", "yaml": "^2.7.0" }, @@ -4503,15 +4503,15 @@ } }, "node_modules/cspell-dictionary": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.18.0.tgz", - "integrity": "sha512-yf7anUDHYFPuQ53619BILYswm4E08NzyNPO1cF0GyqGe5ZTTHf/rCNYcuZHtQ7yKmQuC/K8/y2kEeLsqNa0p6A==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.18.1.tgz", + "integrity": "sha512-vKHEPSfkMKMR4S4tk6K2vHC+f3kdJK8Kdh/C0jDh6RRDjDsyAPxshtbremxOgAX6X8GaRUCROoMZ7FhB92+Y9w==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.18.0", - "@cspell/cspell-types": "8.18.0", - "cspell-trie-lib": "8.18.0", + "@cspell/cspell-pipe": "8.18.1", + "@cspell/cspell-types": "8.18.1", + "cspell-trie-lib": "8.18.1", "fast-equals": "^5.2.2" }, "engines": { @@ -4519,15 +4519,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.18.0.tgz", - "integrity": "sha512-HYWAK7282o9CkcMwqC3w1wNjgae1v4CMgzF3ptpyBonjISkj1GdFGMno4Gu2uW43aKGTmyj4Fi9J94UZvzZa4w==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.18.1.tgz", + "integrity": "sha512-gp/AdUtW6FqpKY4YyYJ3kz0OsXApwsV1FOUA9Z0VnOYKVZtt2snh4uNlI4Ltq+wh7pDU8mqaPWmX6Xy+HSRDkQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.18.0", - "cspell-glob": "8.18.0", - "cspell-io": "8.18.0" + "@cspell/url": "8.18.1", + "cspell-glob": "8.18.1", + "cspell-io": "8.18.1" }, "bin": { "cspell-gitignore": "bin.mjs" @@ -4537,13 +4537,13 @@ } }, "node_modules/cspell-glob": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.18.0.tgz", - "integrity": "sha512-ox3ygu5+3tXR3+XRbYJy/z+YK1zo4TFQFkvUEr+aV8Ogyvgm7qE9uTaFz6krkkMLNG6l8EZ7mJtdn0ZsXF/WKQ==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.18.1.tgz", + "integrity": "sha512-tlZXvzsN7dByHo69dz/HbJuQDUtrfhdioZ/LHaW7W9diG9NpaghgEfyX4fmsIXjU/2f66LDpYVY6osjtlOgyrg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.18.0", + "@cspell/url": "8.18.1", "micromatch": "^4.0.8" }, "engines": { @@ -4551,14 +4551,14 @@ } }, "node_modules/cspell-grammar": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.18.0.tgz", - "integrity": "sha512-/h8gLULvH+P+8N/cmIx8M85sqlER6AyO/RoCVudfq7lTkFneXXKmCoHSA2YQbod9ZSjL+voivBokN2yjMR+XEA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.18.1.tgz", + "integrity": "sha512-V6XTN1B++7EzJA0H4g4XbNJtqm6Y3/iXdLeZ6sMRDaNFKXXwTbWRtn8gukDQIytyw09AnCUKeqGSzCVqw26Omg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.18.0", - "@cspell/cspell-types": "8.18.0" + "@cspell/cspell-pipe": "8.18.1", + "@cspell/cspell-types": "8.18.1" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4568,42 +4568,42 @@ } }, "node_modules/cspell-io": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.18.0.tgz", - "integrity": "sha512-W6CfXY5dlGTd6XWgHl4B2qLD/gla9TXDVdSo3ViCMJoVu82UQD8b4mir5RfHqXiMrz7ItDeUy9BxFN42VB2YcA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.18.1.tgz", + "integrity": "sha512-mm9SUEF2yShuTXDSjCbsAqYTEb6jrtgcCnlqIzpsZOJOOe+zj/VyzTy2NJvOrdvR59dikdaqB75VGBMfHi804g==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.18.0", - "@cspell/url": "8.18.0" + "@cspell/cspell-service-bus": "8.18.1", + "@cspell/url": "8.18.1" }, "engines": { "node": ">=18" } }, "node_modules/cspell-lib": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.18.0.tgz", - "integrity": "sha512-346CAY12pVk40FWnfPOwajKug61EeawW3QMtJE/f6rMYGAjGxGExhZnl6eR/KuCMt/w60kqQMSjGDw2zJjJqUw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.18.1.tgz", + "integrity": "sha512-t1j+XB7515yHmrczK6I1N6j0a72vmL/6OxsMJnCucHC6DO0WkOqmHulNRH7LpFacnns0dx15lmrAqPg7gQFcIg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.18.0", - "@cspell/cspell-pipe": "8.18.0", - "@cspell/cspell-resolver": "8.18.0", - "@cspell/cspell-types": "8.18.0", - "@cspell/dynamic-import": "8.18.0", - "@cspell/filetypes": "8.18.0", - "@cspell/strong-weak-map": "8.18.0", - "@cspell/url": "8.18.0", + "@cspell/cspell-bundled-dicts": "8.18.1", + "@cspell/cspell-pipe": "8.18.1", + "@cspell/cspell-resolver": "8.18.1", + "@cspell/cspell-types": "8.18.1", + "@cspell/dynamic-import": "8.18.1", + "@cspell/filetypes": "8.18.1", + "@cspell/strong-weak-map": "8.18.1", + "@cspell/url": "8.18.1", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.18.0", - "cspell-dictionary": "8.18.0", - "cspell-glob": "8.18.0", - "cspell-grammar": "8.18.0", - "cspell-io": "8.18.0", - "cspell-trie-lib": "8.18.0", + "cspell-config-lib": "8.18.1", + "cspell-dictionary": "8.18.1", + "cspell-glob": "8.18.1", + "cspell-grammar": "8.18.1", + "cspell-io": "8.18.1", + "cspell-trie-lib": "8.18.1", "env-paths": "^3.0.0", "fast-equals": "^5.2.2", "gensequence": "^7.0.0", @@ -4618,14 +4618,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.18.0.tgz", - "integrity": "sha512-zhrCAHyQ2uiGpFdp6E336/L2oDTh/0fM22VpGbkBS4uYKqG9jMy4eUZdSKS8Lg3St4YdGK14J7dv/PiMLqqxlw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.18.1.tgz", + "integrity": "sha512-UaB36wsyp2eWeMtrbS6Q2t2WFvpedmGXJ879yHn9qKD7ViyUpI4cAbh6v7gWMUu+gjqCulXtke64k1ddmBihPQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.18.0", - "@cspell/cspell-types": "8.18.0", + "@cspell/cspell-pipe": "8.18.1", + "@cspell/cspell-types": "8.18.1", "gensequence": "^7.0.0" }, "engines": { diff --git a/package.json b/package.json index 68e613c5d0..66dee437be 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "cspell": "^8.18.0", + "cspell": "^8.18.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-jsdoc": "^50.6.9", diff --git a/vendor/package-lock.json b/vendor/package-lock.json index cde3c2c620..220bc63ae2 100644 --- a/vendor/package-lock.json +++ b/vendor/package-lock.json @@ -13,7 +13,7 @@ "animate.css": "^4.1.1", "croner": "^9.0.0", "moment": "^2.30.1", - "moment-timezone": "^0.5.47", + "moment-timezone": "^0.5.48", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" @@ -74,9 +74,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.47", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.47.tgz", - "integrity": "sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==", + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", "license": "MIT", "dependencies": { "moment": "^2.29.4" diff --git a/vendor/package.json b/vendor/package.json index 138be86b23..4f5ad3118b 100644 --- a/vendor/package.json +++ b/vendor/package.json @@ -15,7 +15,7 @@ "animate.css": "^4.1.1", "croner": "^9.0.0", "moment": "^2.30.1", - "moment-timezone": "^0.5.47", + "moment-timezone": "^0.5.48", "nunjucks": "^3.2.4", "suncalc": "^1.9.0", "weathericons": "^2.1.0" From 01fd41c191471ddec2cd9275f1a8fb3ebb033c29 Mon Sep 17 00:00:00 2001 From: Veeck Date: Tue, 1 Apr 2025 18:47:56 +0200 Subject: [PATCH 208/418] Prepare 2.31.0 release (#3757) updated CHANGELOG and release process documentation --------- Co-authored-by: veeck --- CHANGELOG.md | 5 +++-- Collaboration.md | 18 ++++++++++-------- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52d0d2708a..1a2eee1a5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². -## [2.31.0-develop] - unreleased +## [2.31.0] - 2025-04-01 -planned for 2025-04-01 +Thanks to: @Developer-Incoming, @eltociear, @geraki, @khassel, @KristjanESPERANTO, @MagMar94, @mixasgr, @n8many, @OWL4C, @rejas, @savvadam, @sdetweil. > ⚠️ This release needs nodejs version `v22.14.0 or higher` @@ -1720,6 +1720,7 @@ It includes (but is not limited to) the following features: This was part of the blogpost: [https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the](https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the) +[2.31.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.30.0...v2.31.0 [2.30.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.29.0...v2.30.0 [2.29.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.28.0...v2.29.0 [2.28.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.27.0...v2.28.0 diff --git a/Collaboration.md b/Collaboration.md index 31dd855dcc..435f136782 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -30,14 +30,16 @@ Are done by ### Deployment steps - [ ] pull latest `develop` branch -- [ ] update `package.json` and `package-lock.json` to reflect correct version number `2.xx.0` -- [ ] test `develop` branch -- [ ] update `CHANGELOG.md` - - [ ] add all contributor names: `...` - - [ ] add min. node version: > ⚠️ This release needs nodejs version `v22.14.0` or higher - - [ ] check release link at the bottom of the file -- [ ] commit and push all changes -- [ ] after successful test run via github actions: merge pull request to `develop` +- [ ] create `prep-release` branch from `develop` + - [ ] update `package.json` and `package-lock.json` to reflect correct version number `2.xx.0` + - [ ] test `prep-release` branch + - [ ] update `CHANGELOG.md` + - [ ] add all contributor names: `...` + - [ ] add min. node version: > ⚠️ This release needs nodejs version `v22.14.0` or higher + - [ ] check release link at the bottom of the file + - [ ] commit and push all changes + - [ ] create pull request from `prep-release` to `develop` branch with title `Prepare Release 2.xx.0` + - [ ] after successful test run via github actions: merge pull request to `develop` - [ ] after successful test run via github actions: create pull request from `develop` to `master` branch - [ ] add label `mastermerge` - [ ] title of the PR is `Release 2.xx.0` diff --git a/package-lock.json b/package-lock.json index da455afb3e..69eb8ed4fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.31.0-develop", + "version": "2.31.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.31.0-develop", + "version": "2.31.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 66dee437be..b97e604e64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.31.0-develop", + "version": "2.31.0", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From 86934c8375528a76ce28cd8e4b53bd5b6a5cd66b Mon Sep 17 00:00:00 2001 From: veeck Date: Tue, 1 Apr 2025 21:53:07 +0200 Subject: [PATCH 209/418] Prepare v2.32.0-develop --- CHANGELOG.md | 5 +++++ Collaboration.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a2eee1a5b..bde0b129a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror². +## [2.32.0] - unreleased + +planned for 2025-07-01 + ## [2.31.0] - 2025-04-01 Thanks to: @Developer-Incoming, @eltociear, @geraki, @khassel, @KristjanESPERANTO, @MagMar94, @mixasgr, @n8many, @OWL4C, @rejas, @savvadam, @sdetweil. @@ -1720,6 +1724,7 @@ It includes (but is not limited to) the following features: This was part of the blogpost: [https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the](https://michaelteeuw.nl/post/83916869600/magic-mirror-part-vi-production-of-the) +[2.32.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.31.0...develop [2.31.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.30.0...v2.31.0 [2.30.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.29.0...v2.30.0 [2.29.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.28.0...v2.29.0 diff --git a/Collaboration.md b/Collaboration.md index 435f136782..403a9fe187 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -56,7 +56,7 @@ Are done by - [ ] update `package.json` and `package-lock.json` to reflect correct version number `2.xx.0-develop` - [ ] draft new section in `CHANGELOG.md` - [ ] create new release link at the bottom of the file -- [ ] commit and publish `develop` branch +- [ ] commit and push `develop` branch - [ ] if new release will be in January, update the year in LICENSE.md ### After release diff --git a/package-lock.json b/package-lock.json index b3da529c3d..ca78e15d95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.31.0", + "version": "2.32.0-develop", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.31.0", + "version": "2.32.0-develop", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index b97e604e64..e8f81bc26b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.31.0", + "version": "2.32.0-develop", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From e1a53ef2d55c1b49f23a29b24e7b1055e0f5f4db Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 24 Apr 2025 00:42:48 +0200 Subject: [PATCH 210/418] [refactor] Simplify module loading process (#3766) While debugging a 3rd party module, I looked at how modules are loaded and realized that the `loadModules` method can be implemented much simpler. This refactor makes the method easier to understand and maintain. --- CHANGELOG.md | 4 ++++ js/loader.js | 33 +++++++++++++-------------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bde0b129a3..98ea0e697a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 planned for 2025-07-01 +### Changed + +- [refactor] Simplify module loading process + ## [2.31.0] - 2025-04-01 Thanks to: @Developer-Incoming, @eltociear, @geraki, @khassel, @KristjanESPERANTO, @MagMar94, @mixasgr, @n8many, @OWL4C, @rejas, @savvadam, @sdetweil. diff --git a/js/loader.js b/js/loader.js index e823b0b620..d86ef9323b 100644 --- a/js/loader.js +++ b/js/loader.js @@ -217,29 +217,22 @@ const Loader = (function () { * Load all modules as defined in the config. */ async loadModules () { - let moduleData = await getModuleData(); + const moduleData = await getModuleData(); const envVars = await getEnvVars(); const customCss = envVars.customCss; - /** - * @returns {Promise} when all modules are loaded - */ - const loadNextModule = async function () { - if (moduleData.length > 0) { - const nextModule = moduleData[0]; - await loadModule(nextModule); - moduleData = moduleData.slice(1); - await loadNextModule(); - } else { - // All modules loaded. Load custom.css - // This is done after all the modules so we can - // overwrite all the defined styles. - await loadFile(customCss); - // custom.css loaded. Start all modules. - await startModules(); - } - }; - await loadNextModule(); + // Load all modules + for (const module of moduleData) { + await loadModule(module); + } + + // Load custom.css + // Since this happens after loading the modules, + // it overwrites the default styles. + await loadFile(customCss); + + // Start all modules. + await startModules(); }, /** From ff6682982f1f611302f75338a9023051af8a6271 Mon Sep 17 00:00:00 2001 From: BugHaver <43462320+bughaver@users.noreply.github.com> Date: Mon, 28 Apr 2025 02:37:17 +1000 Subject: [PATCH 211/418] [feature] Introduce disableNextEvent to hide next sun event (#3769) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hello and thank you for wanting to contribute to the MagicMirror² project! **Please make sure that you have followed these 4 rules before submitting your Pull Request:** > 1. Base your pull requests against the `develop` branch. > 2. Include these infos in the description: > > - Does the pull request solve a **related** issue? No > - If so, can you reference the issue like this `Fixes #`? N/A > - What does the pull request accomplish? Use a list if needed. Introduce showNextEvent to show/hide next sun event > - If it includes major visual changes please add screenshots. > ![image](https://github.com/user-attachments/assets/410f6a82-e4fe-4c40-a477-8249149febf3) > 3. Please run `npm run lint:prettier` before submitting so that > style issues are fixed. > 4. Don't forget to add an entry about your changes to > the CHANGELOG.md file. **Note**: Sometimes the development moves very fast. It is highly recommended that you update your branch of `develop` before creating a pull request to send us your changes. This makes everyone's lives easier (including yours) and helps us out on the development team. Thanks again and have a nice day! --------- Co-authored-by: BugHaver <43462320+lsaadeh@users.noreply.github.com> --- CHANGELOG.md | 4 ++ modules/default/clock/clock.js | 37 +++++++++++-------- .../modules/clock/clock_showSunNoEvent.js | 20 ++++++++++ tests/e2e/modules/clock_spec.js | 18 +++++++++ 4 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 tests/configs/modules/clock/clock_showSunNoEvent.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 98ea0e697a..4340bef331 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 planned for 2025-07-01 +### Added + +- [clock] Added option 'disableNextEvent' to hide next sun event. + ### Changed - [refactor] Simplify module loading process diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 14667d0227..f5c7411d23 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -25,7 +25,7 @@ Module.register("clock", { analogShowDate: "top", // OBSOLETE, can be replaced with analogPlacement and showTime, options: false, 'top', or 'bottom' secondsColor: "#888888", // DEPRECATED, use CSS instead. Class "clock-second-digital" for digital clock, "clock-second" for analog clock. - showSunTimes: false, + showSunTimes: false, // options: true, false, 'disableNextEvent' showMoonTimes: false, // options: false, 'times' (rise/set), 'percent' (lit percent), 'phase' (current phase), or 'both' (percent & phase) lat: 47.630539, lon: -122.344147 @@ -171,21 +171,28 @@ Module.register("clock", { if (this.config.showSunTimes) { const sunTimes = SunCalc.getTimes(now, this.config.lat, this.config.lon); const isVisible = now.isBetween(sunTimes.sunrise, sunTimes.sunset); - let nextEvent; - if (now.isBefore(sunTimes.sunrise)) { - nextEvent = sunTimes.sunrise; - } else if (now.isBefore(sunTimes.sunset)) { - nextEvent = sunTimes.sunset; - } else { - const tomorrowSunTimes = SunCalc.getTimes(now.clone().add(1, "day"), this.config.lat, this.config.lon); - nextEvent = tomorrowSunTimes.sunrise; + let sunWrapperInnerHTML = ""; + + if (this.config.showSunTimes !== "disableNextEvent") { + let nextEvent; + if (now.isBefore(sunTimes.sunrise)) { + nextEvent = sunTimes.sunrise; + } else if (now.isBefore(sunTimes.sunset)) { + nextEvent = sunTimes.sunset; + } else { + const tomorrowSunTimes = SunCalc.getTimes(now.clone().add(1, "day"), this.config.lat, this.config.lon); + nextEvent = tomorrowSunTimes.sunrise; + } + const untilNextEvent = moment.duration(moment(nextEvent).diff(now)); + const untilNextEventString = `${untilNextEvent.hours()}h ${untilNextEvent.minutes()}m`; + + sunWrapperInnerHTML = ` ${untilNextEventString}`; } - const untilNextEvent = moment.duration(moment(nextEvent).diff(now)); - const untilNextEventString = `${untilNextEvent.hours()}h ${untilNextEvent.minutes()}m`; - sunWrapper.innerHTML - = ` ${untilNextEventString}` - + ` ${formatTime(this.config, sunTimes.sunrise)}` - + ` ${formatTime(this.config, sunTimes.sunset)}`; + + sunWrapperInnerHTML += ` ${formatTime(this.config, sunTimes.sunrise)}` + + ` ${formatTime(this.config, sunTimes.sunset)}`; + + sunWrapper.innerHTML = sunWrapperInnerHTML; digitalWrapper.appendChild(sunWrapper); } diff --git a/tests/configs/modules/clock/clock_showSunNoEvent.js b/tests/configs/modules/clock/clock_showSunNoEvent.js new file mode 100644 index 0000000000..5b5d029544 --- /dev/null +++ b/tests/configs/modules/clock/clock_showSunNoEvent.js @@ -0,0 +1,20 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 12, + + modules: [ + { + module: "clock", + position: "middle_center", + config: { + showSunTimes: "disableNextEvent" + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/e2e/modules/clock_spec.js b/tests/e2e/modules/clock_spec.js index a5a6d2e0ca..9d9680e1c4 100644 --- a/tests/e2e/modules/clock_spec.js +++ b/tests/e2e/modules/clock_spec.js @@ -92,6 +92,9 @@ describe("Clock module", () => { it("should show the sun times", async () => { const elem = await helpers.waitForElement(".clock .digital .sun"); expect(elem).not.toBeNull(); + + const elem2 = await helpers.waitForElement(".clock .digital .sun .fas.fa-sun"); + expect(elem2).not.toBeNull(); }); it("should show the moon times", async () => { @@ -100,6 +103,21 @@ describe("Clock module", () => { }); }); + describe("with showSunNextEvent disabled", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/clock/clock_showSunNoEvent.js"); + await helpers.getDocument(); + }); + + it("should show the sun times", async () => { + const elem = await helpers.waitForElement(".clock .digital .sun"); + expect(elem).not.toBeNull(); + + const elem2 = document.querySelector(".clock .digital .sun .fas.fa-sun"); + expect(elem2).toBeNull(); + }); + }); + describe("with showWeek config enabled", () => { beforeAll(async () => { await helpers.startApplication("tests/configs/modules/clock/clock_showWeek.js"); From b9d63d7252f99659cfabe00577aad63d8118d185 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 6 May 2025 20:33:42 +0200 Subject: [PATCH 212/418] Use "node --run" instead of "npm run" (#3764) This has the advantage that the package manager is no longer involved after the installation process. However, previous start commands such as `npm run start` continue to work. So we don't even have to adapt the documentation. --- .github/CONTRIBUTING.md | 12 ++++++------ .github/ISSUE_TEMPLATE/bug_report.yml | 10 +++++----- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/automated-tests.yaml | 14 +++++++------- .github/workflows/electron-rebuild.yaml | 2 +- .github/workflows/spellcheck.yaml | 4 ++-- .gitignore | 4 ++++ CHANGELOG.md | 5 +++-- js/defaults.js | 2 +- js/electron.js | 2 +- .../default/updatenotification/update_helper.js | 10 +++++----- package.json | 12 ++++++------ 12 files changed, 42 insertions(+), 37 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f934c59ccf..bbaeb71d13 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -8,31 +8,31 @@ We hold our code to standard, and these standards are documented below. We use [prettier](https://prettier.io/) for automatic formatting a lot all our files. The configuration is in our `prettier.config.mjs` file. -To run prettier, use `npm run lint:prettier`. +To run prettier, use `node --run lint:prettier`. ### JavaScript: Run ESLint We use [ESLint](https://eslint.org) to lint our JavaScript files. The configuration is in our `eslint.config.mjs` file. -To run ESLint, use `npm run lint:js`. +To run ESLint, use `node --run lint:js`. ### CSS: Run StyleLint We use [StyleLint](https://stylelint.io) to lint our CSS. The configuration is in our `.stylelintrc.json` file. -To run StyleLint, use `npm run lint:css`. +To run StyleLint, use `node --run lint:css`. ### Markdown: Run markdownlint We use [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) to lint our markdown files. The configuration is in our `.markdownlint.json` file. -To run markdownlint, use `npm run markdownlint:css`. +To run markdownlint, use `node --run markdownlint:css`. ## Testing We use [Jest](https://jestjs.io) for JavaScript testing. -To run all tests, use `npm run test`. +To run all tests, use `node --run test`. The specific test commands are defined in `package.json`. -So you can also run the specific tests with other commands, e.g. `npm run test:unit` or `npx jest tests/e2e/env_spec.js`. +So you can also run the specific tests with other commands, e.g. `node --run test:unit` or `npx jest tests/e2e/env_spec.js`. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index d9777a4d5d..318e11f458 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -44,11 +44,11 @@ body: description: | Please keep in mind that some problems are specific to certain start options. options: - - "npm run start" - - "npm run start:wayland" - - "npm run start:windows" - - "npm run start:x11" - - "npm run server" + - "node --run start" + - "node --run start:wayland" + - "node --run start:windows" + - "node --run start:x11" + - "node --run server" - "node clientonly --address ... --port ..." validations: required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e3dc222245..f1d2349952 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,7 +10,7 @@ Hello and thank you for wanting to contribute to the MagicMirror² project! > - What does the pull request accomplish? Use a list if needed. > - If it includes major visual changes please add screenshots. > -> 3. Please run `npm run lint:prettier` before submitting so that +> 3. Please run `node --run lint:prettier` before submitting so that > style issues are fixed. > 4. Don't forget to add an entry about your changes to > the CHANGELOG.md file. diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index f27439f634..3d0e886cba 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -26,13 +26,13 @@ jobs: cache: "npm" - name: "Install dependencies" run: | - npm run install-mm:dev + node --run install-mm:dev - name: "Run linter tests" run: | - npm run test:prettier - npm run test:js - npm run test:css - npm run test:markdown + node --run test:prettier + node --run test:js + node --run test:css + node --run test:markdown test: runs-on: ubuntu-24.04 timeout-minutes: 30 @@ -54,7 +54,7 @@ jobs: cache: "npm" - name: "Install MagicMirror²" run: | - npm run install-mm:dev + node --run install-mm:dev - name: "Run tests" run: | # Fix chrome-sandbox permissions: @@ -64,4 +64,4 @@ jobs: WLR_BACKENDS=headless WLR_LIBINPUT_NO_DEVICES=1 WLR_RENDERER=pixman labwc & export WAYLAND_DISPLAY=wayland-0 touch css/custom.css - npm run test + node --run test diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index 30c03e4a86..52c593425c 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -18,7 +18,7 @@ jobs: node-version: ${{ matrix.node-version }} check-latest: true - name: Install MagicMirror - run: npm run install-mm + run: node --run install-mm - name: Install @electron/rebuild run: npm install @electron/rebuild - name: Install node-libgpiod deps diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml index 8e3b915d07..bf327b6ebc 100644 --- a/.github/workflows/spellcheck.yaml +++ b/.github/workflows/spellcheck.yaml @@ -26,6 +26,6 @@ jobs: cache: "npm" - name: Install dependencies run: | - npm run install-mm:dev + node --run install-mm:dev - name: Run Spellcheck - run: npm run test:spelling + run: node --run test:spelling diff --git a/.gitignore b/.gitignore index 7301472cce..31c9a0bf75 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,7 @@ Temporary Items # Ignore positions file (#3518) js/positions.js + +# Ignore lock files other than package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 4340bef331..d489af6588 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ planned for 2025-07-01 ### Changed -- [refactor] Simplify module loading process +- [refactor] Simplify module loading process (#3766) +- Use "node --run" instead of "npm run" (#1511) ## [2.31.0] - 2025-04-01 @@ -38,7 +39,7 @@ Thanks to: @Developer-Incoming, @eltociear, @geraki, @khassel, @KristjanESPERANT ### Changed -- [core] starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) (#3677) +- [core] Starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) (#3677) - [core] Optimize systeminformation calls and output (#3689) - [core] Add issue templates for feature requests and bug reports (#3695) - [core] Adapt `start:x11:dev` script diff --git a/js/defaults.js b/js/defaults.js index ce16b1e95c..469a172b37 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -62,7 +62,7 @@ const defaults = { position: "middle_center", classes: "xsmall", config: { - text: "If you get this message while your config file is already created,
" + "it probably contains an error. To validate your config file run in your MagicMirror² directory
" + "
npm run config:check
" + text: "If you get this message while your config file is already created,
" + "it probably contains an error. To validate your config file run in your MagicMirror² directory
" + "
node --run config:check
" } }, { diff --git a/js/electron.js b/js/electron.js index 8bf8e15ba5..241602efc8 100644 --- a/js/electron.js +++ b/js/electron.js @@ -112,7 +112,7 @@ function createWindow () { const port = process.env.MM_PORT || config.port; mainWindow.loadURL(`${prefix}${address}:${port}`); - // Open the DevTools if run with "npm start dev" + // Open the DevTools if run with "node --run start:dev" if (process.argv.includes("dev")) { if (process.env.JEST_WORKER_ID !== undefined) { // if we are running with jest diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index fc7cc10b78..1aeace1029 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -133,10 +133,10 @@ class Updater { }); } - // restart rules (pm2 or npm start) + // restart rules (pm2 or node --run start) restart () { if (this.usePM2) this.pm2Restart(); - else this.npmRestart(); + else this.nodeRestart(); } // restart MagicMiror with "pm2": use PM2Id for restart it @@ -150,12 +150,12 @@ class Updater { }); } - // restart MagicMiror with "npm start" - npmRestart () { + // restart MagicMiror with "node --run start" + nodeRestart () { Log.info("updatenotification: Restarting MagicMirror..."); const out = process.stdout; const err = process.stderr; - const subprocess = Spawn("npm start", { cwd: this.root_path, shell: true, detached: true, stdio: ["ignore", out, err] }); + const subprocess = Spawn("node --run start", { cwd: this.root_path, shell: true, detached: true, stdio: ["ignore", out, err] }); subprocess.unref(); // detach the newly launched process from the master process process.exit(); } diff --git a/package.json b/package.json index e8f81bc26b..fd94f733cc 100644 --- a/package.json +++ b/package.json @@ -33,17 +33,17 @@ "lint:js": "eslint --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", - "postinstall": "npm run install-vendor && npm run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"", + "postinstall": "node --run install-vendor && node --run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"", "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.", "server": "node ./serveronly", - "start": "npm run start:x11", - "start:dev": "npm run start -- dev", + "start": "node --run start:x11", + "start:dev": "node --run start -- dev", "start:wayland": "WAYLAND_DISPLAY=\"${WAYLAND_DISPLAY:=wayland-1}\" ./node_modules/.bin/electron js/electron.js --enable-features=UseOzonePlatform --ozone-platform=wayland", - "start:wayland:dev": "npm run start:wayland -- dev", + "start:wayland:dev": "node --run start:wayland -- dev", "start:windows": ".\\node_modules\\.bin\\electron js\\electron.js", - "start:windows:dev": "npm run start:windows -- dev", + "start:windows:dev": "node --run start:windows -- dev", "start:x11": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js", - "start:x11:dev": "npm run start:x11 -- dev", + "start:x11:dev": "node --run start:x11 -- dev", "test": "NODE_ENV=test jest -i --forceExit", "test:calendar": "node ./modules/default/calendar/debug.js", "test:coverage": "NODE_ENV=test jest --coverage -i --verbose false --forceExit", From a5b85c4ab6b77e249161e641b5c51e133cb90037 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 7 May 2025 07:51:01 +0200 Subject: [PATCH 213/418] [workflow] Use LTS node version and split "Run test" step (#3767) Two small changes to the workflows: - Run linter and spellcheck workflows with LTS node version. The advantage of this is that we no longer have to raise the node version for them. - Split "Run test" step into two steps for more clarity. --- .github/workflows/automated-tests.yaml | 8 +++++--- .github/workflows/spellcheck.yaml | 2 +- CHANGELOG.md | 4 +++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 3d0e886cba..2f0541b41e 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -22,7 +22,7 @@ jobs: - name: "Use Node.js" uses: actions/setup-node@v4 with: - node-version: 23 + node-version: lts/* cache: "npm" - name: "Install dependencies" run: | @@ -55,13 +55,15 @@ jobs: - name: "Install MagicMirror²" run: | node --run install-mm:dev - - name: "Run tests" + - name: "Prepare environment for tests" run: | # Fix chrome-sandbox permissions: sudo chown root:root ./node_modules/electron/dist/chrome-sandbox sudo chmod 4755 ./node_modules/electron/dist/chrome-sandbox # Start labwc WLR_BACKENDS=headless WLR_LIBINPUT_NO_DEVICES=1 WLR_RENDERER=pixman labwc & - export WAYLAND_DISPLAY=wayland-0 touch css/custom.css + - name: "Run tests" + run: | + export WAYLAND_DISPLAY=wayland-0 node --run test diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml index bf327b6ebc..03053b2131 100644 --- a/.github/workflows/spellcheck.yaml +++ b/.github/workflows/spellcheck.yaml @@ -21,7 +21,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: "22" + node-version: lts/* check-latest: true cache: "npm" - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index d489af6588..9e602a0fad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,9 @@ planned for 2025-07-01 ### Changed - [refactor] Simplify module loading process (#3766) -- Use "node --run" instead of "npm run" (#1511) +- Use "node --run" instead of "npm run" (#3764) +- [workflow] Run linter und spellcheck with LTS node version (#3767) +- [workflow] Split "Run test" step into two steps for more clarity (#3767) ## [2.31.0] - 2025-04-01 From 7b4d363b07d7b1d99085c09783c913bf24d62103 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 7 May 2025 16:06:09 +0200 Subject: [PATCH 214/418] [fix] Fix `start:dev` script (#3773) This will fix #3772 caused by #3764. Since I work with `start:wayland:dev` instead of `start:dev`, I didn't notice this, sorry. --- CHANGELOG.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e602a0fad..88a081bfaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,12 +13,12 @@ planned for 2025-07-01 ### Added -- [clock] Added option 'disableNextEvent' to hide next sun event. +- [clock] Added option 'disableNextEvent' to hide next sun event (#3769) ### Changed - [refactor] Simplify module loading process (#3766) -- Use "node --run" instead of "npm run" (#3764) +- Use `node --run` instead of `npm run` (#3764) and adapt `start:dev` script. - [workflow] Run linter und spellcheck with LTS node version (#3767) - [workflow] Split "Run test" step into two steps for more clarity (#3767) diff --git a/package.json b/package.json index fd94f733cc..2b886e9ba4 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.", "server": "node ./serveronly", "start": "node --run start:x11", - "start:dev": "node --run start -- dev", + "start:dev": "node --run start:x11 -- dev", "start:wayland": "WAYLAND_DISPLAY=\"${WAYLAND_DISPLAY:=wayland-1}\" ./node_modules/.bin/electron js/electron.js --enable-features=UseOzonePlatform --ozone-platform=wayland", "start:wayland:dev": "node --run start:wayland -- dev", "start:windows": ".\\node_modules\\.bin\\electron js\\electron.js", From 2831ae985c831cc978f063a1e2820dacf0fe27e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bugsounet=20-=20C=C3=A9dric?= Date: Thu, 8 May 2025 10:15:02 +0200 Subject: [PATCH 215/418] [Feature Request] Allow to make an display order of module position in config (#3762) My proposal for #3761 * I use `flex` box for create region container * I have moved `container` definition to `main.css` (for css tunning, maybe it can be useful) * I create `order` in module config for define module order display from position # Advantage: We don't have to move module config in another place in array of modules # Another advantage that i did'nt think: We can change dynamicaly module order of a container: - So, in this case, for a module config builder, (I won't mention the name because otherwise I'll get angry...) It can be usefull for a config preview (before saving config) --> just change style css `order` module value for see preview - Or, change `order` value in dev console for testing # Disadvantages I don't see any ;) --- CHANGELOG.md | 1 + css/main.css | 13 +++++++++++++ js/loader.js | 3 ++- js/main.js | 5 ++++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88a081bfaa..05279fab93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ planned for 2025-07-01 ### Added +- [config] Allow to change module order for final renderer (or dynamicaly with CSS): Feature `order` in config. (#3762) - [clock] Added option 'disableNextEvent' to hide next sun event (#3769) ### Changed diff --git a/css/main.css b/css/main.css index 0aa5c3418e..e981635bc2 100644 --- a/css/main.css +++ b/css/main.css @@ -239,3 +239,16 @@ sup { border-spacing: 0; border-collapse: separate; } + +/** + * Container Definitions. + */ + +.region .container { + display: flex; + flex-direction: column; +} + +.region .container.hidden { + display: none; +} diff --git a/js/loader.js b/js/loader.js index d86ef9323b..2380b02ea9 100644 --- a/js/loader.js +++ b/js/loader.js @@ -108,7 +108,8 @@ const Loader = (function () { header: moduleData.header, configDeepMerge: typeof moduleData.configDeepMerge === "boolean" ? moduleData.configDeepMerge : false, config: moduleData.config, - classes: typeof moduleData.classes !== "undefined" ? `${moduleData.classes} ${module}` : module + classes: typeof moduleData.classes !== "undefined" ? `${moduleData.classes} ${module}` : module, + order: (typeof moduleData.order === "number" && Number.isInteger(moduleData.order)) ? moduleData.order : 0 }); }); diff --git a/js/main.js b/js/main.js index 7c0e9db390..c2a5605323 100644 --- a/js/main.js +++ b/js/main.js @@ -30,6 +30,8 @@ const MM = (function () { dom.className = `module ${dom.className} ${module.data.classes}`; } + dom.style.order = (typeof module.data.order === "number" && Number.isInteger(module.data.order)) ? module.data.order : 0; + dom.opacity = 0; wrapper.appendChild(dom); @@ -463,7 +465,8 @@ const MM = (function () { } }); - wrapper.style.display = showWrapper ? "block" : "none"; + // move container definitions to main CSS + wrapper.className = showWrapper ? "container" : "container hidden"; }); }; From 53bff7243ddf3fc61c09028a0cfb369a15698c08 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 9 May 2025 22:35:09 +0200 Subject: [PATCH 216/418] update dependencies (#3774) --- CHANGELOG.md | 4 + package-lock.json | 1785 +++++++++++++++++++++++---------------------- package.json | 26 +- 3 files changed, 916 insertions(+), 899 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05279fab93..752b451ba8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ planned for 2025-07-01 - [workflow] Run linter und spellcheck with LTS node version (#3767) - [workflow] Split "Run test" step into two steps for more clarity (#3767) +### Updated + +- [core] Update dependencies + ## [2.31.0] - 2025-04-01 Thanks to: @Developer-Incoming, @eltociear, @geraki, @khassel, @KristjanESPERANTO, @MagMar94, @mixasgr, @n8many, @OWL4C, @rejas, @savvadam, @sdetweil. diff --git a/package-lock.json b/package-lock.json index ca78e15d95..6fe9c90ef3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,11 +11,11 @@ "license": "MIT", "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.17.0", + "ansis": "^4.0.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.23.0", - "express": "^4.21.2", + "eslint": "^9.26.0", + "express": "^5.1.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^8.1.0", @@ -28,33 +28,33 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.6.0" + "undici": "^7.8.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "cspell": "^8.18.1", + "cspell": "^9.0.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.9", - "eslint-plugin-package-json": "^0.29.0", + "eslint-plugin-jsdoc": "^50.6.11", + "eslint-plugin-package-json": "^0.31.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", - "jsdom": "^26.0.0", - "lint-staged": "^15.5.0", + "jsdom": "^26.1.0", + "lint-staged": "^15.5.2", "markdownlint-cli2": "^0.17.2", - "playwright": "^1.51.1", + "playwright": "^1.52.0", "prettier": "^3.5.3", "sinon": "^20.0.0", - "stylelint": "^16.17.0", - "stylelint-config-standard": "^37.0.0", + "stylelint": "^16.19.1", + "stylelint-config-standard": "^38.0.0", "stylelint-prettier": "^5.0.3" }, "engines": { "node": ">=22.14.0" }, "optionalDependencies": { - "electron": "^35.1.2" + "electron": "^35.3.0" } }, "node_modules/@altano/repository-tools": { @@ -79,14 +79,14 @@ } }, "node_modules/@asamuzakjp/css-color": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.1.tgz", - "integrity": "sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.7.tgz", + "integrity": "sha512-Ok5fYhtwdyJQmU1PpEv6Si7Y+A4cYb8yNM9oiIJC9TzXPMuN9fvdonKJqcnz9TbFqV6bQ8z0giRq0iaOpGZV2g==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.2", - "@csstools/css-color-parser": "^3.0.8", + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", "lru-cache": "^10.4.3" @@ -100,24 +100,24 @@ "license": "ISC" }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", + "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", "dev": true, "license": "MIT", "engines": { @@ -125,22 +125,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", + "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helpers": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -166,14 +166,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", + "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -183,14 +183,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -210,29 +210,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", + "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -242,9 +242,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, "license": "MIT", "engines": { @@ -252,9 +252,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -262,9 +262,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, "license": "MIT", "engines": { @@ -272,9 +272,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -282,27 +282,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.27.1" }, "bin": { "parser": "bin/babel-parser.js" @@ -367,13 +367,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -409,13 +409,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -535,13 +535,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -551,32 +551,32 @@ } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", + "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -595,14 +595,14 @@ } }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -616,38 +616,38 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.18.1.tgz", - "integrity": "sha512-gxciVVfQqCVXYH0p2Q5D7x7/SgaW3Wv5UjRwO+TCme0P2lVLl/IcfjkujZX+6UQkT7X4QRglXo1QN141UcCRCQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.0.1.tgz", + "integrity": "sha512-h7gTqg0VF4N8VhOPk66XewuSsT56OP2ujgxtAyYQ4H+NuYd3HMfS0h/I3/y9uBhllwOEamaeAzYhc5JF/qIrsQ==", "dev": true, "license": "MIT", "dependencies": { "@cspell/dict-ada": "^4.1.0", "@cspell/dict-al": "^1.1.0", - "@cspell/dict-aws": "^4.0.9", + "@cspell/dict-aws": "^4.0.10", "@cspell/dict-bash": "^4.2.0", - "@cspell/dict-companies": "^3.1.14", - "@cspell/dict-cpp": "^6.0.6", + "@cspell/dict-companies": "^3.2.1", + "@cspell/dict-cpp": "^6.0.8", "@cspell/dict-cryptocurrencies": "^5.0.4", "@cspell/dict-csharp": "^4.0.6", "@cspell/dict-css": "^4.0.17", "@cspell/dict-dart": "^2.3.0", - "@cspell/dict-data-science": "^2.0.7", + "@cspell/dict-data-science": "^2.0.8", "@cspell/dict-django": "^4.1.4", - "@cspell/dict-docker": "^1.1.12", + "@cspell/dict-docker": "^1.1.14", "@cspell/dict-dotnet": "^5.0.9", "@cspell/dict-elixir": "^4.0.7", - "@cspell/dict-en_us": "^4.3.35", - "@cspell/dict-en-common-misspellings": "^2.0.10", - "@cspell/dict-en-gb": "1.1.33", - "@cspell/dict-filetypes": "^3.0.11", + "@cspell/dict-en_us": "^4.4.8", + "@cspell/dict-en-common-misspellings": "^2.0.11", + "@cspell/dict-en-gb-mit": "^3.0.6", + "@cspell/dict-filetypes": "^3.0.12", "@cspell/dict-flutter": "^1.1.0", "@cspell/dict-fonts": "^4.0.4", "@cspell/dict-fsharp": "^1.1.0", "@cspell/dict-fullstack": "^3.2.6", - "@cspell/dict-gaming-terms": "^1.1.0", + "@cspell/dict-gaming-terms": "^1.1.1", "@cspell/dict-git": "^3.0.4", - "@cspell/dict-golang": "^6.0.19", + "@cspell/dict-golang": "^6.0.21", "@cspell/dict-google": "^1.0.8", "@cspell/dict-haskell": "^4.0.5", "@cspell/dict-html": "^4.0.11", @@ -660,85 +660,85 @@ "@cspell/dict-lorem-ipsum": "^4.0.4", "@cspell/dict-lua": "^4.0.7", "@cspell/dict-makefile": "^1.0.4", - "@cspell/dict-markdown": "^2.0.9", + "@cspell/dict-markdown": "^2.0.10", "@cspell/dict-monkeyc": "^1.0.10", - "@cspell/dict-node": "^5.0.6", - "@cspell/dict-npm": "^5.1.31", + "@cspell/dict-node": "^5.0.7", + "@cspell/dict-npm": "^5.2.3", "@cspell/dict-php": "^4.0.14", "@cspell/dict-powershell": "^5.0.14", "@cspell/dict-public-licenses": "^2.0.13", - "@cspell/dict-python": "^4.2.16", + "@cspell/dict-python": "^4.2.18", "@cspell/dict-r": "^2.1.0", "@cspell/dict-ruby": "^5.0.8", "@cspell/dict-rust": "^4.0.11", "@cspell/dict-scala": "^5.0.7", "@cspell/dict-shell": "^1.1.0", - "@cspell/dict-software-terms": "^5.0.2", + "@cspell/dict-software-terms": "^5.0.8", "@cspell/dict-sql": "^2.2.0", "@cspell/dict-svelte": "^1.0.6", "@cspell/dict-swift": "^2.0.5", "@cspell/dict-terraform": "^1.1.1", - "@cspell/dict-typescript": "^3.2.0", + "@cspell/dict-typescript": "^3.2.1", "@cspell/dict-vue": "^3.0.4" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.18.1.tgz", - "integrity": "sha512-/U3/8bcOL5O35fI9F7nN7Mhic0K01ZRxRV/+5jj7atltBbqgFSxViHCZBX0lDZJM96gUHn+3r6q6/8VEJahpDA==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.0.1.tgz", + "integrity": "sha512-Rpn7Tuq9t8bZpXZFV43NkhCl0LaPDJZSON4/JFxGbOcH16ryXfrx7oObUTIIyxSxO3fGkzaJZHIwGibRJSsbNQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.18.1" + "@cspell/cspell-types": "9.0.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@cspell/cspell-pipe": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.18.1.tgz", - "integrity": "sha512-QHndTQPkR1c02pvvQ7UKFtLjCXgY0OcX8zjTLrCkynmcQxJFjAZAh9cJ7NMOAxab+ciSnkaVf4KWaRSEG17z8Q==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.0.1.tgz", + "integrity": "sha512-bhFcvF2a8KYKVh/OebCfJ8LFw5GYHyUsUjAbxnznTBrYOFSIclDjwUwT29yVDXwnQkJkB6Px5Y9e2VvtFizVFg==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@cspell/cspell-resolver": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.18.1.tgz", - "integrity": "sha512-T2sUBv0p9Hnfyg1xT1u3ESKuIWaaIDo0I8idh5DSlTpHgLjdIeAwasmFjEJ28qZv8OKSGawcSQKgJbStfbZASQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.0.1.tgz", + "integrity": "sha512-AhIXAhX1qt7Y3EyiP/5rAk7Ow7DJpAyB44wPbfdF9p1vhnk6oQ7RslnD3G6S9o/vNxZ0DWFPREMWx19J/3c+hw==", "dev": true, "license": "MIT", "dependencies": { "global-directory": "^4.0.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@cspell/cspell-service-bus": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.18.1.tgz", - "integrity": "sha512-PwWl7EyhGIu4wHEhvBJb6xVlqMtFwQk0qLDArBvugL6nA+MX9NfG/w7PTgS7tCkFjVF1ku2sDzDLTDWwEk+MLw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.0.1.tgz", + "integrity": "sha512-DoW6hLkFIO3BXePtUYQEax3FTH9fkwCUbf6qphAEXnr4PjoyPZsgBhR6iCrZd4DyhuFiRvK3Cgpq2o3O0NdODQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@cspell/cspell-types": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.18.1.tgz", - "integrity": "sha512-d/nMG+qnMbI/1JPm+lD0KcKpgtEHMRsHxkdtGyNCDgvHL/JOGaSHc5ERS3IUgBW0Dfya/3z9wPdaMcHEzt7YCQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.0.1.tgz", + "integrity": "sha512-8FRmvyV1AYEepJB3J7jji1ZYG9yOK0eYr4WuUVPfUJa6N3HyeZjWKhxbVvqedmEI74f5Ls3cQKHY1T2Yvqk/ag==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@cspell/dict-ada": { @@ -756,9 +756,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-aws": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.9.tgz", - "integrity": "sha512-bDYdnnJGwSkIZ4gzrauu7qzOs/ZAY/FnU4k11LgdMI8BhwMfsbsy2EI1iS+sD/BI5ZnNT9kU5YR3WADeNOmhRg==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.10.tgz", + "integrity": "sha512-0qW4sI0GX8haELdhfakQNuw7a2pnWXz3VYQA2MpydH2xT2e6EN9DWFpKAi8DfcChm8MgDAogKkoHtIo075iYng==", "dev": true, "license": "MIT" }, @@ -773,16 +773,16 @@ } }, "node_modules/@cspell/dict-companies": { - "version": "3.1.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.14.tgz", - "integrity": "sha512-iqo1Ce4L7h0l0GFSicm2wCLtfuymwkvgFGhmu9UHyuIcTbdFkDErH+m6lH3Ed+QuskJlpQ9dM7puMIGqUlVERw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.2.1.tgz", + "integrity": "sha512-ryaeJ1KhTTKL4mtinMtKn8wxk6/tqD4vX5tFP+Hg89SiIXmbMk5vZZwVf+eyGUWJOyw5A1CVj9EIWecgoi+jYQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.6.tgz", - "integrity": "sha512-HMV1chsExuZt5IL9rYBW7GmhNZDVdQJEd1WtFgOO6jqiNxbpTG3Is3Pkldl7FpusBQQZr4BdjMit5bnPpVRy3A==", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.8.tgz", + "integrity": "sha512-BzurRZilWqaJt32Gif6/yCCPi+FtrchjmnehVEIFzbWyeBd/VOUw77IwrEzehZsu5cRU91yPWuWp5fUsKfDAXA==", "dev": true, "license": "MIT" }, @@ -815,9 +815,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-data-science": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.7.tgz", - "integrity": "sha512-XhAkK+nSW6zmrnWzusmZ1BpYLc62AWYHZc2p17u4nE2Z9XG5DleG55PCZxXQTKz90pmwlhFM9AfpkJsYaBWATA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.8.tgz", + "integrity": "sha512-uyAtT+32PfM29wRBeAkUSbkytqI8bNszNfAz2sGPtZBRmsZTYugKMEO9eDjAIE/pnT9CmbjNuoiXhk+Ss4fCOg==", "dev": true, "license": "MIT" }, @@ -829,9 +829,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-docker": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.12.tgz", - "integrity": "sha512-6d25ZPBnYZaT9D9An/x6g/4mk542R8bR3ipnby3QFCxnfdd6xaWiTcwDPsCgwN2aQZIQ1jX/fil9KmBEqIK/qA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.14.tgz", + "integrity": "sha512-p6Qz5mokvcosTpDlgSUREdSbZ10mBL3ndgCdEKMqjCSZJFdfxRdNdjrGER3lQ6LMq5jGr1r7nGXA0gvUJK80nw==", "dev": true, "license": "MIT" }, @@ -850,30 +850,30 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.3.35", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.35.tgz", - "integrity": "sha512-HF6QNyPHkxeo/SosaZXRQlnKDUTjIzrGKyqfbw/fPPlPYrXefAZZ40ofheb5HnbUicR7xqV/lsc/HQfqYshGIw==", + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.8.tgz", + "integrity": "sha512-OkNUVuU9Q+Sf827/61YPkk6ya6dSsllzeYniBFqNW9TkoqQXT3vggkgmtCE1aEhSvVctMwxpPYoC8pZgn1TeSA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.10.tgz", - "integrity": "sha512-80mXJLtr0tVEtzowrI7ycVae/ULAYImZUlr0kUTpa8i57AUk7Zy3pYBs44EYIKW7ZC9AHu4Qjjfq4vriAtyTDQ==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.11.tgz", + "integrity": "sha512-xFQjeg0wFHh9sFhshpJ+5BzWR1m9Vu8pD0CGPkwZLK9oii8AD8RXNchabLKy/O5VTLwyqPOi9qpyp1cxm3US4Q==", "dev": true, "license": "CC BY-SA 4.0" }, - "node_modules/@cspell/dict-en-gb": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz", - "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==", + "node_modules/@cspell/dict-en-gb-mit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.0.6.tgz", + "integrity": "sha512-QYDwuXi9Yh+AvU1omhz8sWX+A1SxWI3zeK1HdGfTrICZavhp8xxcQGTa5zxTTFRCcQc483YzUH2Dl+6Zd50tJg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.11.tgz", - "integrity": "sha512-bBtCHZLo7MiSRUqx5KEiPdGOmXIlDGY+L7SJEtRWZENpAKE+96rT7hj+TUUYWBbCzheqHr0OXZJFEKDgsG/uZg==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.12.tgz", + "integrity": "sha512-+ds5wgNdlUxuJvhg8A1TjuSpalDFGCh7SkANCWvIplg6QZPXL4j83lqxP7PgjHpx7PsBUS7vw0aiHPjZy9BItw==", "dev": true, "license": "MIT" }, @@ -906,9 +906,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-gaming-terms": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.1.0.tgz", - "integrity": "sha512-46AnDs9XkgJ2f1Sqol1WgfJ8gOqp60fojpc9Wxch7x+BA63g4JfMV5/M5x0sI0TLlLY8EBSglcr8wQF/7C80AQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.1.1.tgz", + "integrity": "sha512-tb8GFxjTLDQstkJcJ90lDqF4rKKlMUKs5/ewePN9P+PYRSehqDpLI5S5meOfPit8LGszeOrjUdBQ4zXo7NpMyQ==", "dev": true, "license": "MIT" }, @@ -920,9 +920,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-golang": { - "version": "6.0.19", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.19.tgz", - "integrity": "sha512-VS+oinB2/CbgmHE06kMJlj52OVMZM0S2EEXph3oaroNTgTuclSwdFylQmOEjquZi55kW+n3FM9MyWXiitB7Dtg==", + "version": "6.0.21", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.21.tgz", + "integrity": "sha512-D3wG1MWhFx54ySFJ00CS1MVjR4UiBVsOWGIjJ5Av+HamnguqEshxbF9mvy+BX0KqzdLVzwFkoLBs8QeOID56HA==", "dev": true, "license": "MIT" }, @@ -1011,16 +1011,16 @@ "license": "MIT" }, "node_modules/@cspell/dict-markdown": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.9.tgz", - "integrity": "sha512-j2e6Eg18BlTb1mMP1DkyRFMM/FLS7qiZjltpURzDckB57zDZbUyskOFdl4VX7jItZZEeY0fe22bSPOycgS1Z5A==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.10.tgz", + "integrity": "sha512-vtVa6L/84F9sTjclTYDkWJF/Vx2c5xzxBKkQp+CEFlxOF2SYgm+RSoEvAvg5vj4N5kuqR4350ZlY3zl2eA3MXw==", "dev": true, "license": "MIT", "peerDependencies": { "@cspell/dict-css": "^4.0.17", "@cspell/dict-html": "^4.0.11", "@cspell/dict-html-symbol-entities": "^4.0.3", - "@cspell/dict-typescript": "^3.2.0" + "@cspell/dict-typescript": "^3.2.1" } }, "node_modules/@cspell/dict-monkeyc": { @@ -1031,16 +1031,16 @@ "license": "MIT" }, "node_modules/@cspell/dict-node": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.6.tgz", - "integrity": "sha512-CEbhPCpxGvRNByGolSBTrXXW2rJA4bGqZuTx1KKO85mwR6aadeOmUE7xf/8jiCkXSy+qvr9aJeh+jlfXcsrziQ==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.7.tgz", + "integrity": "sha512-ZaPpBsHGQCqUyFPKLyCNUH2qzolDRm1/901IO8e7btk7bEDF56DN82VD43gPvD4HWz3yLs/WkcLa01KYAJpnOw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.1.31", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.31.tgz", - "integrity": "sha512-Oh9nrhgNV4UD1hlbgO3TFQqQRKziwc7qXKoQiC4oqOYIhMs2WL9Ezozku7FY1e7o5XbCIZX9nRH0ymNx/Rwj6w==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.3.tgz", + "integrity": "sha512-EdGkCpAq66Mhi9Qldgsr+NvPVL4TdtmdlqDe4VBp0P3n6J0B7b0jT1MlVDIiLR+F1eqBfL0qjfHf0ey1CafeNw==", "dev": true, "license": "MIT" }, @@ -1066,13 +1066,13 @@ "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.16", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.16.tgz", - "integrity": "sha512-LkQssFt1hPOWXIQiD8ScTkz/41RL7Ti0V/2ytUzEW82dc0atIEksrBg8MuOjWXktp0Dk5tDwRLgmIvhV3CFFOA==", + "version": "4.2.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.18.tgz", + "integrity": "sha512-hYczHVqZBsck7DzO5LumBLJM119a3F17aj8a7lApnPIS7cmEwnPc2eACNscAHDk7qAo2127oI7axUoFMe9/g1g==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-data-science": "^2.0.7" + "@cspell/dict-data-science": "^2.0.8" } }, "node_modules/@cspell/dict-r": { @@ -1111,9 +1111,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.0.2.tgz", - "integrity": "sha512-aCzP+M0WXRLYXTriDMZygUe5s4jKyau/nCA6gBGt4EoHfXn+Ua/+DrW766oXOkkESIlqTBtRgb9gWwQvUdOXSQ==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.0.8.tgz", + "integrity": "sha512-VsJesitvaHZpMgNwHHms3yDsZz7LNToC2HuSAnyt1znn37ribiJF1ty0jWhVQO6fv7K4PM1KsKTJIwqBwc446g==", "dev": true, "license": "MIT" }, @@ -1146,9 +1146,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-typescript": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.0.tgz", - "integrity": "sha512-Pk3zNePLT8qg51l0M4g1ISowYAEGxTuNfZlgkU5SvHa9Cu7x/BWoyYq9Fvc3kAyoisCjRPyvWF4uRYrPitPDFw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.1.tgz", + "integrity": "sha512-jdnKg4rBl75GUBTsUD6nTJl7FGvaIt5wWcWP7TZSC3rV1LfkwvbUiY3PiGpfJlAIdnLYSeFWIpYU9gyVgz206w==", "dev": true, "license": "MIT" }, @@ -1160,47 +1160,47 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.18.1.tgz", - "integrity": "sha512-VJHfS/Iv0Rx7wn1pjPmwgsaw6r72N5Cx2gL0slWk8Cogc8YiK7/6jsGnsvxJZVkHntJoiT8PrkIvhNKb3awD3g==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.0.1.tgz", + "integrity": "sha512-BoWzHwkufo90ubMZUN8Jy4HQYYWFW7psVCdG/4RUgfvVnazkPfLxWBbsPQsLrlIP0utaqei7D9FU0K7r7mpl4A==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.18.1", + "@cspell/url": "9.0.1", "import-meta-resolve": "^4.1.0" }, "engines": { - "node": ">=18.0" + "node": ">=20" } }, "node_modules/@cspell/filetypes": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.18.1.tgz", - "integrity": "sha512-vTOb2itP0pjrccvt8wcKiTGyw0pFMTPI85H12T6n8ZhqXTktPgQH2gEf/SU/5tkPNnBKr4GJ+FdU5hJ27HzgXQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.0.1.tgz", + "integrity": "sha512-swZu3ra2AueyjEz/bPsvwFuHGYhjWZBx1K9FSvZA/yDIX5RVr6orQSuf9zvXNFui6Nyk0tudLnn3y9jT0LHk8A==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@cspell/strong-weak-map": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.18.1.tgz", - "integrity": "sha512-gsgv+5ZQD4aHNHDdfNGoafVYkqRynyYgaodt9Dp/3o0YKYcxGf2jrX8SJ35MfZ61qln0n7P4Djrg+bFV2zNH5w==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.0.1.tgz", + "integrity": "sha512-u87PWr1xACqs/F3HibZ4Eb0Za/ghWIa6WLvEKV9OaiLfEUQuczbrXPVgHmGr83H0XXWUKy8FvVbWGFmXwiw+gQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@cspell/url": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.18.1.tgz", - "integrity": "sha512-FRJbLYDC9ucpTOzbF6MohP2u5X3NU5L0RoVuoYCynqm/QOI38XP6WOEaI4H58CAn857bOIKZk0LZRPTGzi6Qlg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.0.1.tgz", + "integrity": "sha512-8xaLrsQ742dmwXwS6tjreps3NpSQe6WEZFPQQT2DprVJXGZnfQR8ob0c+kPhD0hu9A6PwShJsRsfh3DQGKCqAw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18.0" + "node": ">=20" } }, "node_modules/@csstools/color-helpers": { @@ -1224,9 +1224,9 @@ } }, "node_modules/@csstools/css-calc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz", - "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.3.tgz", + "integrity": "sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw==", "dev": true, "funding": [ { @@ -1248,9 +1248,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz", - "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.9.tgz", + "integrity": "sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw==", "dev": true, "funding": [ { @@ -1265,7 +1265,7 @@ "license": "MIT", "dependencies": { "@csstools/color-helpers": "^5.0.2", - "@csstools/css-calc": "^2.1.2" + "@csstools/css-calc": "^2.1.3" }, "engines": { "node": ">=18" @@ -1434,9 +1434,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", - "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -1473,9 +1473,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.6", @@ -1509,18 +1509,18 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", - "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", + "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -1597,9 +1597,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", - "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", + "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1615,12 +1615,12 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", - "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.12.0", + "@eslint/core": "^0.13.0", "levn": "^0.4.1" }, "engines": { @@ -1676,9 +1676,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", - "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -2157,6 +2157,27 @@ "buffer": "^6.0.3" } }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.1.tgz", + "integrity": "sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2195,19 +2216,6 @@ "node": ">= 8" } }, - "node_modules/@pkgr/core": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz", - "integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/@pm2/agent": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz", @@ -2636,9 +2644,9 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "license": "MIT", "dependencies": { @@ -2680,9 +2688,9 @@ } }, "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "version": "2.8.18", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.18.tgz", + "integrity": "sha512-nX3d0sxJW41CqQvfOzVG1NCTXfFDrDWIghCZncpHeWlVFd81zxB/DLhg7avFg6eHLCRX7ckBmoIIcqa++upvJA==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -2786,12 +2794,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.14.tgz", - "integrity": "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w==", + "version": "22.15.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", + "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/responselike": { @@ -2846,14 +2854,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz", - "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", + "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0" + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2864,9 +2872,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz", - "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", + "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", "dev": true, "license": "MIT", "engines": { @@ -2878,20 +2886,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz", - "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", + "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/visitor-keys": "8.28.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2905,16 +2913,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz", - "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", + "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.28.0", - "@typescript-eslint/types": "8.28.0", - "@typescript-eslint/typescript-estree": "8.28.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/typescript-estree": "8.32.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2929,13 +2937,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz", - "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", + "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/types": "8.32.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2947,13 +2955,13 @@ } }, "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { "node": ">= 0.6" @@ -3071,9 +3079,9 @@ } }, "node_modules/ansis": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", - "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.0.0.tgz", + "integrity": "sha512-P8nrHI1EyW9OfBt1X7hMSwGN2vwRuqHSKJAT1gbLWZRzDa24oHjYwGHvEgHeBepupzk878yS/HBZ0NMPYtbolw==", "license": "ISC", "engines": { "node": ">=14" @@ -3136,12 +3144,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, "node_modules/array-includes": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", @@ -3326,9 +3328,9 @@ } }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3564,56 +3566,25 @@ "license": "MIT" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -3645,9 +3616,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", "dev": true, "funding": [ { @@ -3665,10 +3636,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -3738,14 +3709,14 @@ } }, "node_modules/cacheable": { - "version": "1.8.9", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.9.tgz", - "integrity": "sha512-FicwAUyWnrtnd4QqYAoRlNs44/a1jTL7XDKqm5gJ90wz1DQPlC7U2Rd1Tydpv+E7WAr4sQHuw8Q8M3nZMAyecQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.9.0.tgz", + "integrity": "sha512-8D5htMCxPDUULux9gFzv30f04Xo3wCnik0oOxKoRTPIBoqA7HtOcJ87uBhQTs3jCfZZTrUBGsYIZOgE0ZRgMAg==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.7.1", - "keyv": "^5.3.1" + "hookified": "^1.8.2", + "keyv": "^5.3.3" } }, "node_modules/cacheable-lookup": { @@ -3778,9 +3749,9 @@ } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.2.tgz", - "integrity": "sha512-Lji2XRxqqa5Wg+CHLVfFKBImfJZ4pCSccu9eVWK6w4c2SDFLd8JAn1zqTuSFnsxb7ope6rMsnIHfp+eBbRBRZQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.3.tgz", + "integrity": "sha512-Rwu4+nXI9fqcxiEHtbkvoes2X+QfkTRo1TMkPfwzipGsJlJO/z69vqB4FNl9xJ3xCpAcbkvmEabZfPzrwN3+gQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3854,9 +3825,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001707", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", - "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", + "version": "1.0.30001717", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", + "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", "dev": true, "funding": [ { @@ -4309,9 +4280,9 @@ } }, "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -4337,19 +4308,22 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } }, "node_modules/core-util-is": { "version": "1.0.3", @@ -4451,159 +4425,158 @@ } }, "node_modules/cspell": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.18.1.tgz", - "integrity": "sha512-RE3LIgN9NAVcYBNX2NQVhLergok8EPymOuCUhu1vBR8cjRmioksn3CJeCoQgD8rPjalM+S9thYkMtOZc5Jjv2A==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.0.1.tgz", + "integrity": "sha512-AJqsX+3eSTz9GmIuyEZUzCCTbvCPw6+Nv7UYa4PCn7vNV3XEb5LHTp5i9y2i65fNaeNEcQXLrLYoY/JcBFmUSQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "8.18.1", - "@cspell/cspell-pipe": "8.18.1", - "@cspell/cspell-types": "8.18.1", - "@cspell/dynamic-import": "8.18.1", - "@cspell/url": "8.18.1", + "@cspell/cspell-json-reporter": "9.0.1", + "@cspell/cspell-pipe": "9.0.1", + "@cspell/cspell-types": "9.0.1", + "@cspell/dynamic-import": "9.0.1", + "@cspell/url": "9.0.1", "chalk": "^5.4.1", "chalk-template": "^1.1.0", "commander": "^13.1.0", - "cspell-dictionary": "8.18.1", - "cspell-gitignore": "8.18.1", - "cspell-glob": "8.18.1", - "cspell-io": "8.18.1", - "cspell-lib": "8.18.1", + "cspell-dictionary": "9.0.1", + "cspell-gitignore": "9.0.1", + "cspell-glob": "9.0.1", + "cspell-io": "9.0.1", + "cspell-lib": "9.0.1", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", - "get-stdin": "^9.0.0", "semver": "^7.7.1", - "tinyglobby": "^0.2.12" + "tinyglobby": "^0.2.13" }, "bin": { "cspell": "bin.mjs", "cspell-esm": "bin.mjs" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" } }, "node_modules/cspell-config-lib": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.18.1.tgz", - "integrity": "sha512-zdJ0uhLROSUrHoibysPw+AkxKPUmiG95hDtiL7s8smewkuaS1hpjqwsDBx981nHYs3xW3qDUfVATrAkSzb0VMw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.0.1.tgz", + "integrity": "sha512-hbeyU6cY4NPKh69L4QpBZgGz00f7rLk10xPlCo6MxEmCqSOTuXXvDEUR51d2ED69G+GyFAeZi5VU9IdJ4jhvzQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "8.18.1", + "@cspell/cspell-types": "9.0.1", "comment-json": "^4.2.5", - "yaml": "^2.7.0" + "yaml": "^2.7.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/cspell-dictionary": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.18.1.tgz", - "integrity": "sha512-vKHEPSfkMKMR4S4tk6K2vHC+f3kdJK8Kdh/C0jDh6RRDjDsyAPxshtbremxOgAX6X8GaRUCROoMZ7FhB92+Y9w==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.0.1.tgz", + "integrity": "sha512-I9gjRpfV4djxN0i2p9OzWIrkjtUaGUyVE9atvRbkHUMeqDUhC2Qt0Mb9tnF8I7qnHeZt+U44vUa9Dg7yrJ+k4Q==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.18.1", - "@cspell/cspell-types": "8.18.1", - "cspell-trie-lib": "8.18.1", + "@cspell/cspell-pipe": "9.0.1", + "@cspell/cspell-types": "9.0.1", + "cspell-trie-lib": "9.0.1", "fast-equals": "^5.2.2" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/cspell-gitignore": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.18.1.tgz", - "integrity": "sha512-gp/AdUtW6FqpKY4YyYJ3kz0OsXApwsV1FOUA9Z0VnOYKVZtt2snh4uNlI4Ltq+wh7pDU8mqaPWmX6Xy+HSRDkQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.0.1.tgz", + "integrity": "sha512-xjgOmeGbHEaeF0erRQ2QXwqxWqGDiI4mu+NjCL7ZHPoAM5y8PEO6IbxVNabIB1xC4QAborbtEQ/8ydDWLJcPoQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.18.1", - "cspell-glob": "8.18.1", - "cspell-io": "8.18.1" + "@cspell/url": "9.0.1", + "cspell-glob": "9.0.1", + "cspell-io": "9.0.1" }, "bin": { "cspell-gitignore": "bin.mjs" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/cspell-glob": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.18.1.tgz", - "integrity": "sha512-tlZXvzsN7dByHo69dz/HbJuQDUtrfhdioZ/LHaW7W9diG9NpaghgEfyX4fmsIXjU/2f66LDpYVY6osjtlOgyrg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.0.1.tgz", + "integrity": "sha512-dQU/ln6J9Qe31zk1cLJnq/WNAjRrTUig1GG8WA2oK1jHZKY9VbyJLb5DUFnDUx35cI0jdOEnGSCWi8qNjHSc1Q==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "8.18.1", - "micromatch": "^4.0.8" + "@cspell/url": "9.0.1", + "picomatch": "^4.0.2" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/cspell-grammar": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.18.1.tgz", - "integrity": "sha512-V6XTN1B++7EzJA0H4g4XbNJtqm6Y3/iXdLeZ6sMRDaNFKXXwTbWRtn8gukDQIytyw09AnCUKeqGSzCVqw26Omg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.0.1.tgz", + "integrity": "sha512-FZ1z1p3pslfotZT/W/VRZjB4S+z0ETrTbNmQ5pGmhdY0nm7Slmg+8nIJluLEjBneBGTJIOcLjYykwS2vI6jzxw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.18.1", - "@cspell/cspell-types": "8.18.1" + "@cspell/cspell-pipe": "9.0.1", + "@cspell/cspell-types": "9.0.1" }, "bin": { "cspell-grammar": "bin.mjs" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/cspell-io": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.18.1.tgz", - "integrity": "sha512-mm9SUEF2yShuTXDSjCbsAqYTEb6jrtgcCnlqIzpsZOJOOe+zj/VyzTy2NJvOrdvR59dikdaqB75VGBMfHi804g==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.0.1.tgz", + "integrity": "sha512-L5fZY0glVeQb6nmt1WL1wKzZzoHJUkBQ9BGCrwqSXIrjZrYmBNSKixCjo6o9n2keRUwpNjsvZj1TQDKDV+FsXA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "8.18.1", - "@cspell/url": "8.18.1" + "@cspell/cspell-service-bus": "9.0.1", + "@cspell/url": "9.0.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/cspell-lib": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.18.1.tgz", - "integrity": "sha512-t1j+XB7515yHmrczK6I1N6j0a72vmL/6OxsMJnCucHC6DO0WkOqmHulNRH7LpFacnns0dx15lmrAqPg7gQFcIg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.0.1.tgz", + "integrity": "sha512-F4vJG6GmAGVAuhgcepO12UtG7yev7Rcfa31MLIyYNTrd5NeORzM+GTHnL970FlEflwYPYjcSTGwkyowQ+ZbmDg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "8.18.1", - "@cspell/cspell-pipe": "8.18.1", - "@cspell/cspell-resolver": "8.18.1", - "@cspell/cspell-types": "8.18.1", - "@cspell/dynamic-import": "8.18.1", - "@cspell/filetypes": "8.18.1", - "@cspell/strong-weak-map": "8.18.1", - "@cspell/url": "8.18.1", + "@cspell/cspell-bundled-dicts": "9.0.1", + "@cspell/cspell-pipe": "9.0.1", + "@cspell/cspell-resolver": "9.0.1", + "@cspell/cspell-types": "9.0.1", + "@cspell/dynamic-import": "9.0.1", + "@cspell/filetypes": "9.0.1", + "@cspell/strong-weak-map": "9.0.1", + "@cspell/url": "9.0.1", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "8.18.1", - "cspell-dictionary": "8.18.1", - "cspell-glob": "8.18.1", - "cspell-grammar": "8.18.1", - "cspell-io": "8.18.1", - "cspell-trie-lib": "8.18.1", + "cspell-config-lib": "9.0.1", + "cspell-dictionary": "9.0.1", + "cspell-glob": "9.0.1", + "cspell-grammar": "9.0.1", + "cspell-io": "9.0.1", + "cspell-trie-lib": "9.0.1", "env-paths": "^3.0.0", "fast-equals": "^5.2.2", "gensequence": "^7.0.0", @@ -4614,22 +4587,22 @@ "xdg-basedir": "^5.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/cspell-trie-lib": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.18.1.tgz", - "integrity": "sha512-UaB36wsyp2eWeMtrbS6Q2t2WFvpedmGXJ879yHn9qKD7ViyUpI4cAbh6v7gWMUu+gjqCulXtke64k1ddmBihPQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.0.1.tgz", + "integrity": "sha512-gIupiHwLdsQun79biJgiqmXffKUGzFjGLFEeVptI2Zy5Oa3XhRJsHap4PyeleErONkpzxMG1tgpOWzhOqwl65Q==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "8.18.1", - "@cspell/cspell-types": "8.18.1", + "@cspell/cspell-pipe": "9.0.1", + "@cspell/cspell-types": "9.0.1", "gensequence": "^7.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/cspell/node_modules/chalk": { @@ -4683,13 +4656,13 @@ } }, "node_modules/cssstyle": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz", - "integrity": "sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.1.tgz", + "integrity": "sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^3.1.1", + "@asamuzakjp/css-color": "^3.1.2", "rrweb-cssom": "^0.8.0" }, "engines": { @@ -4859,9 +4832,9 @@ } }, "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4974,16 +4947,6 @@ "node": ">=6" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", @@ -5156,9 +5119,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "35.1.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-35.1.2.tgz", - "integrity": "sha512-ipYSDZEV3+PpHfJ8/oWlpMCvxwutX6xLvBz2HRPgEzSFzgLmGO7YXTjEow4DhDtCpGE+b95NTGoJaRAVQi5n7A==", + "version": "35.3.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-35.3.0.tgz", + "integrity": "sha512-6dLslJrQYB1qvqVPYRv1PhAA/uytC66nUeiTcq2JXiBzrmTWCHppqtGUjZhvnSRVatBCT5/SFdizdzcBiEiYUg==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5175,9 +5138,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.127", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.127.tgz", - "integrity": "sha512-Ke5OggqOtEqzCzcUyV+9jgO6L6sv1gQVKGtSExXHjD/FK0p4qzPZbrDsrCdy0DptcQprD0V80RCBYSWLMhTTgQ==", + "version": "1.5.151", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.151.tgz", + "integrity": "sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA==", "dev": true, "license": "ISC" }, @@ -5249,11 +5212,15 @@ "node": ">=10.0.0" } }, - "node_modules/engine.io/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "node_modules/engine.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, "engines": { "node": ">= 0.6" } @@ -5275,6 +5242,36 @@ } } }, + "node_modules/engine.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/engine.io/node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", @@ -5481,13 +5478,6 @@ "node": ">= 0.4" } }, - "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", - "dev": true, - "license": "MIT" - }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -5602,22 +5592,23 @@ } }, "node_modules/eslint": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", - "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", + "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.2", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.23.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.26.0", + "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", + "@modelcontextprotocol/sdk": "^1.8.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -5641,7 +5632,8 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3" + "optionator": "^0.9.3", + "zod": "^3.24.2" }, "bin": { "eslint": "bin/eslint.js" @@ -5835,9 +5827,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.9", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.9.tgz", - "integrity": "sha512-7/nHu3FWD4QRG8tCVqcv+BfFtctUtEDWc29oeDXB4bwmDM2/r1ndl14AG/2DUntdqH7qmpvdemJKwb3R97/QEw==", + "version": "50.6.11", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.11.tgz", + "integrity": "sha512-k4+MnBCGR8cuIB5MZ++FGd4gbXxjob2rX1Nq0q3nWFF4xSGZENTgTLZSjb+u9B8SAnP6lpGV2FJrBjllV3pVSg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5848,10 +5840,9 @@ "escape-string-regexp": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.6.0", - "parse-imports": "^2.1.1", + "parse-imports-exports": "^0.2.4", "semver": "^7.6.3", - "spdx-expression-parse": "^4.0.0", - "synckit": "^0.9.1" + "spdx-expression-parse": "^4.0.0" }, "engines": { "node": ">=18" @@ -5861,10 +5852,11 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.29.0.tgz", - "integrity": "sha512-S2YjWLMb+vaI0QbvkSrM6F2lEulaehGWEgHAXSoJI0F2eDw4udp5gtdFyKMLP2GSrfJB5cnKPnSJiOO5RGuaKg==", + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.31.0.tgz", + "integrity": "sha512-4bv/QDcExDUqs9/q89rJndkNV/hA0T5PzvRJX4oLdC5xvYXIZ4zz/RBs7KHj0JLE0BhGwLqHHVCLXQ+Y+IjHPg==", "dev": true, + "license": "MIT", "dependencies": { "@altano/repository-tools": "^0.1.1", "detect-indent": "6.1.0", @@ -6075,6 +6067,27 @@ "dev": true, "license": "MIT" }, + "node_modules/eventsource": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", + "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", + "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -6139,45 +6152,41 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 18" }, "funding": { "type": "opencollective", @@ -6209,21 +6218,21 @@ "node": ">=8.9.0" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/express-rate-limit": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", + "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "^4.11 || 5 || ^5.0.0-beta.1" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -6388,9 +6397,9 @@ } }, "node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -6441,38 +6450,22 @@ } }, "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { "node": ">= 0.8" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -6559,6 +6552,27 @@ "node": ">= 6" } }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -6569,12 +6583,12 @@ } }, "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/fs-extra": { @@ -6741,19 +6755,6 @@ "node": ">= 0.4" } }, - "node_modules/get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -6802,9 +6803,9 @@ } }, "node_modules/git-hooks-list": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz", - "integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-4.1.1.tgz", + "integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==", "dev": true, "license": "MIT", "funding": { @@ -7205,9 +7206,9 @@ } }, "node_modules/hookified": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.8.1.tgz", - "integrity": "sha512-GrO2l93P8xCWBSTBX9l2BxI78VU/MAAYag+pG8curS3aBGy0++ZlxrQ7PdUOUVMbn5BwkGb6+eRrnf43ipnFEA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.9.0.tgz", + "integrity": "sha512-2yEEGqphImtKIe1NXWEhu6yD3hlFR4Mxk4Mtp3XEyScpSt4pQ4ymmXA1zzxZpj99QkFK+nN0nzjeb2+RUi/6CQ==", "dev": true, "license": "MIT" }, @@ -7910,6 +7911,12 @@ "dev": true, "license": "MIT" }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -8786,16 +8793,15 @@ } }, "node_modules/jsdom": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.0.0.tgz", - "integrity": "sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", "dev": true, "license": "MIT", "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", - "decimal.js": "^10.4.3", - "form-data": "^4.0.1", + "decimal.js": "^10.5.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", @@ -8805,12 +8811,12 @@ "rrweb-cssom": "^0.8.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^5.0.0", + "tough-cookie": "^5.1.1", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.0", + "whatwg-url": "^14.1.1", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, @@ -8955,9 +8961,9 @@ } }, "node_modules/katex": { - "version": "0.16.21", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.21.tgz", - "integrity": "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A==", + "version": "0.16.22", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", + "integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==", "dev": true, "funding": [ "https://opencollective.com/katex", @@ -9011,9 +9017,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", - "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz", + "integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==", "dev": true, "license": "MIT" }, @@ -9089,9 +9095,9 @@ } }, "node_modules/lint-staged": { - "version": "15.5.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.0.tgz", - "integrity": "sha512-WyCzSbfYGhK7cU+UuDDkzUiytbfbi0ZdPy2orwtM75P3WTtQBzmG40cCxIa8Ii2+XjfxzLH6Be46tUfWS85Xfg==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", + "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", "dev": true, "license": "MIT", "dependencies": { @@ -9274,9 +9280,9 @@ } }, "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9617,12 +9623,12 @@ "license": "MIT" }, "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/meow": { @@ -9639,10 +9645,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", + "engines": { + "node": ">=18" + }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -9664,15 +9673,6 @@ "node": ">= 8" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/micromark": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.1.tgz", @@ -10236,34 +10236,22 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { "node": ">= 0.6" @@ -10346,9 +10334,9 @@ "license": "MIT" }, "node_modules/module-details-from-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", "license": "MIT" }, "node_modules/moment": { @@ -10448,9 +10436,9 @@ } }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -10552,9 +10540,9 @@ "license": "MIT" }, "node_modules/nwsapi": { - "version": "2.2.19", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.19.tgz", - "integrity": "sha512-94bcyI3RsqiZufXjkr3ltkI86iEl+I7uiHVDtcq9wJUTwYQJ5odHDeSzkkrRzi80jJ8MaeZgqKjH1bAWAFw9bA==", + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", + "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==", "dev": true, "license": "MIT" }, @@ -10677,7 +10665,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "devOptional": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -10816,9 +10803,9 @@ } }, "node_modules/package-json-validator": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.10.0.tgz", - "integrity": "sha512-zaPt4x0ZIxA4KYWpPMkbOEhkEDfQdtkCCC1xhnbnYrQV+Kry3zMAxENujgdT6aPA5BJ+FfpncKoNULWc/qjloQ==", + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.10.2.tgz", + "integrity": "sha512-i8qx/xfHdkzOzP39bNOtK6VauRrLdJoQf7L1lVRG2/evpLAd3vrj3EGNlzB9QiztBerxWAx5QXZh5z+Jfi0IvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10870,18 +10857,14 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/parse-imports": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", - "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", "dev": true, - "license": "Apache-2.0 AND MIT", + "license": "MIT", "dependencies": { - "es-module-lexer": "^1.5.3", - "slashes": "^3.0.12" - }, - "engines": { - "node": ">= 18" + "parse-statements": "1.0.11" } }, "node_modules/parse-json": { @@ -10903,19 +10886,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "dev": true, + "license": "MIT" + }, "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^4.5.0" + "entities": "^6.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", + "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/parseley": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", @@ -10973,10 +10976,13 @@ "license": "MIT" }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } }, "node_modules/path-type": { "version": "5.0.0", @@ -11062,6 +11068,15 @@ "node": ">= 6" } }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -11132,13 +11147,13 @@ } }, "node_modules/playwright": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz", - "integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.51.1" + "playwright-core": "1.52.0" }, "bin": { "playwright": "cli.js" @@ -11151,9 +11166,9 @@ } }, "node_modules/playwright-core": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz", - "integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -11619,12 +11634,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -11690,32 +11705,20 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", - "iconv-lite": "0.4.24", + "iconv-lite": "0.6.3", "unpipe": "1.0.0" }, "engines": { "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -12008,6 +12011,22 @@ "node": ">=8.0" } }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/rrule": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.8.1.tgz", @@ -12203,51 +12222,25 @@ "optional": true }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + "node": ">= 18" } }, "node_modules/serialize-error": { @@ -12280,18 +12273,18 @@ } }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" } }, "node_modules/set-function-length": { @@ -12506,13 +12499,6 @@ "node": ">=8" } }, - "node_modules/slashes": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", - "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", - "dev": true, - "license": "ISC" - }, "node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -12649,6 +12635,19 @@ } } }, + "node_modules/socket.io/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/socket.io/node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -12666,6 +12665,36 @@ } } }, + "node_modules/socket.io/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/socket.io/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/socks": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", @@ -12702,16 +12731,15 @@ "license": "MIT" }, "node_modules/sort-package-json": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.0.0.tgz", - "integrity": "sha512-vfZWx4DnFNB8R9Vg4Dnx21s20auNzWH15ZaCBfADAiyrCwemRmhWstTgvLjMek1DW3+MHcNaqkp86giCF24rMA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.2.1.tgz", + "integrity": "sha512-rTfRdb20vuoAn7LDlEtCqOkYfl2X+Qze6cLbNOzcDpbmKEhJI30tTN44d5shbKJnXsvz24QQhlCm81Bag7EOKg==", "dev": true, "license": "MIT", "dependencies": { "detect-indent": "^7.0.1", "detect-newline": "^4.0.1", - "get-stdin": "^9.0.0", - "git-hooks-list": "^3.0.0", + "git-hooks-list": "^4.0.0", "is-plain-obj": "^4.1.0", "semver": "^7.7.1", "sort-object-keys": "^1.1.3", @@ -13037,9 +13065,9 @@ } }, "node_modules/stylelint": { - "version": "16.17.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.17.0.tgz", - "integrity": "sha512-I9OwVIWRMqVm2Br5iTbrfSqGRPWQUlvm6oXO1xZuYYu0Gpduy67N8wXOZv15p6E/JdlZiAtQaIoLKZEWk5hrjw==", + "version": "16.19.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.19.1.tgz", + "integrity": "sha512-C1SlPZNMKl+d/C867ZdCRthrS+6KuZ3AoGW113RZCOL0M8xOGpgx7G70wq7lFvqvm4dcfdGFVLB/mNaLFChRKw==", "dev": true, "funding": [ { @@ -13066,7 +13094,7 @@ "debug": "^4.3.7", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.0.7", + "file-entry-cache": "^10.0.8", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -13074,7 +13102,7 @@ "ignore": "^7.0.3", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.35.0", + "known-css-properties": "^0.36.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", "micromatch": "^4.0.8", @@ -13100,9 +13128,9 @@ } }, "node_modules/stylelint-config-recommended": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-15.0.0.tgz", - "integrity": "sha512-9LejMFsat7L+NXttdHdTq94byn25TD+82bzGRiV1Pgasl99pWnwipXS5DguTpp3nP1XjvLXVnEJIuYBfsRjRkA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-16.0.0.tgz", + "integrity": "sha512-4RSmPjQegF34wNcK1e1O3Uz91HN8P1aFdFzio90wNK9mjgAI19u5vsU868cVZboKzCaa5XbpvtTzAAGQAxpcXA==", "dev": true, "funding": [ { @@ -13119,13 +13147,13 @@ "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.13.0" + "stylelint": "^16.16.0" } }, "node_modules/stylelint-config-standard": { - "version": "37.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-37.0.0.tgz", - "integrity": "sha512-+6eBlbSTrOn/il2RlV0zYGQwRTkr+WtzuVSs1reaWGObxnxLpbcspCUYajVQHonVfxVw2U+h42azGhrBvcg8OA==", + "version": "38.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-38.0.0.tgz", + "integrity": "sha512-uj3JIX+dpFseqd/DJx8Gy3PcRAJhlEZ2IrlFOc4LUxBX/PNMEQ198x7LCOE2Q5oT9Vw8nyc4CIL78xSqPr6iag==", "dev": true, "funding": [ { @@ -13139,13 +13167,13 @@ ], "license": "MIT", "dependencies": { - "stylelint-config-recommended": "^15.0.0" + "stylelint-config-recommended": "^16.0.0" }, "engines": { "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.13.0" + "stylelint": "^16.18.0" } }, "node_modules/stylelint-prettier": { @@ -13180,25 +13208,25 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.7.tgz", - "integrity": "sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.0.tgz", + "integrity": "sha512-Et/ex6smi3wOOB+n5mek+Grf7P2AxZR5ueqRUvAAn4qkyatXi3cUC1cuQXVkX0VlzBVsN4BkWJFmY/fYiRTdww==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.7" + "flat-cache": "^6.1.9" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.7", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.7.tgz", - "integrity": "sha512-qwZ4xf1v1m7Rc9XiORly31YaChvKt6oNVHuqqZcoED/7O+ToyNVGobKsIAopY9ODcWpEDKEBAbrSOCBHtNQvew==", + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.9.tgz", + "integrity": "sha512-DUqiKkTlAfhtl7g78IuwqYM+YqvT+as0mY+EVk6mfimy19U79pJCzDZQsnqk3Ou/T6hFXWLGbwbADzD/c8Tydg==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.8.9", + "cacheable": "^1.9.0", "flatted": "^3.3.3", - "hookified": "^1.7.1" + "hookified": "^1.8.2" } }, "node_modules/stylelint/node_modules/globby": { @@ -13233,9 +13261,9 @@ } }, "node_modules/stylelint/node_modules/ignore": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", - "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", "dev": true, "license": "MIT", "engines": { @@ -13366,30 +13394,6 @@ "dev": true, "license": "MIT" }, - "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/synckit/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, "node_modules/systeminformation": { "version": "5.25.11", "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.25.11.tgz", @@ -13523,13 +13527,13 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", - "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.3", + "fdir": "^6.4.4", "picomatch": "^4.0.2" }, "engines": { @@ -13540,22 +13544,22 @@ } }, "node_modules/tldts": { - "version": "6.1.85", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.85.tgz", - "integrity": "sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==", + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.85" + "tldts-core": "^6.1.86" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.85", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz", - "integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==", + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "dev": true, "license": "MIT" }, @@ -13601,9 +13605,9 @@ } }, "node_modules/tr46": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", - "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", "dev": true, "license": "MIT", "dependencies": { @@ -13732,13 +13736,14 @@ } }, "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { "node": ">= 0.6" @@ -13819,9 +13824,9 @@ } }, "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -13872,18 +13877,18 @@ } }, "node_modules/undici": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.6.0.tgz", - "integrity": "sha512-gaFsbThjrDGvAaD670r81RZro/s6H2PVZF640Qn0p5kZK+/rim7/mmyfp2W7VB5vOMaFM8vuFBJUaMlaZTYHlA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.8.0.tgz", + "integrity": "sha512-vFv1GA99b7eKO1HG/4RPu2Is3FBTWBrmzqzO0mz+rLxN3yXkE4mqRcb8g8fHxzX4blEysrNZLqg5RbJLqX5buA==", "license": "MIT", "engines": { "node": ">=20.18.1" } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, "node_modules/unicorn-magic": { @@ -13965,15 +13970,6 @@ "dev": true, "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", @@ -14314,7 +14310,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "devOptional": true, "license": "ISC" }, "node_modules/write-file-atomic": { @@ -14332,9 +14327,9 @@ } }, "node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", "dev": true, "license": "MIT", "engines": { @@ -14401,9 +14396,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", "dev": true, "license": "ISC", "bin": { @@ -14496,6 +14491,24 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.24.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", + "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", + "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } } } } diff --git a/package.json b/package.json index 2b886e9ba4..036651c8ff 100644 --- a/package.json +++ b/package.json @@ -63,11 +63,11 @@ }, "dependencies": { "ajv": "^8.17.1", - "ansis": "^3.17.0", + "ansis": "^4.0.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.23.0", - "express": "^4.21.2", + "eslint": "^9.26.0", + "express": "^5.1.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^8.1.0", @@ -80,30 +80,30 @@ "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", - "undici": "^7.6.0" + "undici": "^7.8.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "cspell": "^8.18.1", + "cspell": "^9.0.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.9", - "eslint-plugin-package-json": "^0.29.0", + "eslint-plugin-jsdoc": "^50.6.11", + "eslint-plugin-package-json": "^0.31.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", - "jsdom": "^26.0.0", - "lint-staged": "^15.5.0", + "jsdom": "^26.1.0", + "lint-staged": "^15.5.2", "markdownlint-cli2": "^0.17.2", - "playwright": "^1.51.1", + "playwright": "^1.52.0", "prettier": "^3.5.3", "sinon": "^20.0.0", - "stylelint": "^16.17.0", - "stylelint-config-standard": "^37.0.0", + "stylelint": "^16.19.1", + "stylelint-config-standard": "^38.0.0", "stylelint-prettier": "^5.0.3" }, "optionalDependencies": { - "electron": "^35.1.2" + "electron": "^35.3.0" }, "engines": { "node": ">=22.14.0" From ed419ce5b33706291250df180528cb714ec040c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 22:47:20 +0200 Subject: [PATCH 217/418] Bump pm2 from 5.4.3 to 6.0.5 (#3776) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [pm2](https://github.com/Unitech/pm2) from 5.4.3 to 6.0.5.
Release notes

Sourced from pm2's releases.

v6.0.5

6.0.5

Changelog

Sourced from pm2's changelog.

6.0.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pm2&package-manager=npm_and_yarn&previous-version=5.4.3&new-version=6.0.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 77 +++++++++++++++-------------------------------- package.json | 2 +- 2 files changed, 25 insertions(+), 54 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6fe9c90ef3..6df94c5b5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.20.1", - "pm2": "^5.4.3", + "pm2": "^6.0.5", "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", @@ -2217,9 +2217,9 @@ } }, "node_modules/@pm2/agent": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz", - "integrity": "sha512-n7WYvvTJhHLS2oBb1PjOtgLpMhgImOq8sXkPBw6smeg9LJBWZjiEgPKOpR8mn9UJZsB5P3W4V/MyvNnp31LKeA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.1.1.tgz", + "integrity": "sha512-0V9ckHWd/HSC8BgAbZSoq8KXUG81X97nSkAxmhKDhmF8vanyaoc1YXwc2KVkbWz82Rg4gjd2n9qiT3i7bdvGrQ==", "license": "AGPL-3.0", "dependencies": { "async": "~3.2.0", @@ -2227,12 +2227,11 @@ "dayjs": "~1.8.24", "debug": "~4.3.1", "eventemitter2": "~5.0.1", - "fast-json-patch": "^3.0.0-1", + "fast-json-patch": "^3.1.0", "fclone": "~1.0.11", - "nssocket": "0.6.0", "pm2-axon": "~4.0.1", "pm2-axon-rpc": "~0.7.0", - "proxy-agent": "~6.3.0", + "proxy-agent": "~6.4.0", "semver": "~7.5.0", "ws": "~7.5.10" } @@ -2328,9 +2327,9 @@ "license": "ISC" }, "node_modules/@pm2/io": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.1.tgz", - "integrity": "sha512-KiA+shC6sULQAr9mGZ1pg+6KVW9MF8NpG99x26Lf/082/Qy8qsTCtnJy+HQReW1A9Rdf0C/404cz0RZGZro+IA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.1.0.tgz", + "integrity": "sha512-IxHuYURa3+FQ6BKePlgChZkqABUKFYH6Bwbw7V/pWU1pP6iR1sCI26l7P9ThUEB385ruZn/tZS3CXDUF5IA1NQ==", "license": "Apache-2", "dependencies": { "async": "~2.6.1", @@ -9023,15 +9022,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lazy": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", - "integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==", - "license": "MIT", - "engines": { - "node": ">=0.2.0" - } - }, "node_modules/leac": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", @@ -10520,25 +10510,6 @@ "node": ">=8" } }, - "node_modules/nssocket": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", - "integrity": "sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==", - "license": "MIT", - "dependencies": { - "eventemitter2": "~0.4.14", - "lazy": "~1.0.11" - }, - "engines": { - "node": ">= 0.10.x" - } - }, - "node_modules/nssocket/node_modules/eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==", - "license": "MIT" - }, "node_modules/nwsapi": { "version": "2.2.20", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", @@ -11194,24 +11165,24 @@ } }, "node_modules/pm2": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.3.tgz", - "integrity": "sha512-4/I1htIHzZk1Y67UgOCo4F1cJtas1kSds31N8zN0PybO230id1nigyjGuGFzUnGmUFPmrJ0On22fO1ChFlp7VQ==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.5.tgz", + "integrity": "sha512-+O43WPaEiwYbm6/XSpAOO1Rtya/Uof0n7x8hJZGfwIuepesNTIVArpZh4KqFfze0cvvqZMr0maTW3ifhvmyeMQ==", "license": "AGPL-3.0", "dependencies": { - "@pm2/agent": "~2.0.0", - "@pm2/io": "~6.0.1", + "@pm2/agent": "~2.1.1", + "@pm2/io": "~6.1.0", "@pm2/js-api": "~0.8.0", "@pm2/pm2-version-check": "latest", - "async": "~3.2.0", + "async": "~3.2.6", "blessed": "0.1.81", "chalk": "3.0.0", "chokidar": "^3.5.3", "cli-tableau": "^2.0.0", "commander": "2.15.1", "croner": "~4.1.92", - "dayjs": "~1.11.5", - "debug": "^4.3.1", + "dayjs": "~1.11.13", + "debug": "^4.3.7", "enquirer": "2.3.6", "eventemitter2": "5.0.1", "fclone": "1.0.11", @@ -11224,7 +11195,7 @@ "pm2-deploy": "~1.0.2", "pm2-multimeter": "^0.1.2", "promptly": "^2", - "semver": "^7.2", + "semver": "^7.6.2", "source-map-support": "0.5.21", "sprintf-js": "1.1.2", "vizion": "~2.2.1" @@ -11236,7 +11207,7 @@ "pm2-runtime": "bin/pm2-runtime" }, "engines": { - "node": ">=12.0.0" + "node": ">=16.0.0" }, "optionalDependencies": { "pm2-sysmonit": "^1.2.8" @@ -11553,15 +11524,15 @@ } }, "node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", "lru-cache": "^7.14.1", "pac-proxy-agent": "^7.0.1", "proxy-from-env": "^1.1.0", diff --git a/package.json b/package.json index 036651c8ff..d224f400c1 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.20.1", - "pm2": "^5.4.3", + "pm2": "^6.0.5", "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.25.11", From 2422e847b15f653465ad6f552fe1861a63280d26 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Mon, 12 May 2025 16:39:36 -0500 Subject: [PATCH 218/418] Fix calendar rrule until where event is fullday but rrule until has a non-0 time (#3782) This fixes #3781 tests supplied see https://forum.magicmirror.builders/topic/19637/issue-with-outlook-recurring-events --- CHANGELOG.md | 4 +++ .../default/calendar/calendarfetcherutils.js | 7 +++++ .../configs/modules/calendar/fullday_until.js | 27 ++++++++++++++++++ tests/electron/modules/calendar_spec.js | 4 +++ tests/mocks/fullday_until.ics | 28 +++++++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 tests/configs/modules/calendar/fullday_until.js create mode 100644 tests/mocks/fullday_until.ics diff --git a/CHANGELOG.md b/CHANGELOG.md index 752b451ba8..37cd41cf90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ planned for 2025-07-01 - [workflow] Run linter und spellcheck with LTS node version (#3767) - [workflow] Split "Run test" step into two steps for more clarity (#3767) +### Fixed + +- [calendar] fix fullday event rrule until with timezone offset (#3781) + ### Updated - [core] Update dependencies diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index df567af4f6..c61fd33034 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -293,6 +293,13 @@ const CalendarFetcherUtils = { event.start = rule.options.dtstart; + // if until is set, and its a full day event, force the time to midnight. rrule gets confused with non-00 offset + // looks like MS Outlook sets the until time incorrectly for fullday events + if ((rule.options.until !== undefined) && CalendarFetcherUtils.isFullDayEvent(event)) { + Log.debug("fixup rrule until"); + rule.options.until = new Date(new Date(moment(rule.options.until).startOf("day").add(1, "day")).getTime()); + } + Log.debug("fix rrule start=", rule.options.dtstart); Log.debug("event before rrule.between=", JSON.stringify(event, null, 2), "exdates=", event.exdate); // fixup the exdate and recurrence date to local time too for post between() handling diff --git a/tests/configs/modules/calendar/fullday_until.js b/tests/configs/modules/calendar/fullday_until.js new file mode 100644 index 0000000000..6713d62441 --- /dev/null +++ b/tests/configs/modules/calendar/fullday_until.js @@ -0,0 +1,27 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 12, + + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + hideDuplicates: false, + maximumEntries: 100, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/fullday_until.ics" + } + ] + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 0f8ee5803b..b819d2dc97 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -84,6 +84,10 @@ describe("Calendar module", () => { await helpers.startApplication("tests/configs/modules/calendar/rrule_until.js", "07 Mar 2024 10:38:00 GMT-07:00", [], "America/Los_Angeles"); await expect(doTestCount()).resolves.toBe(1); }); + it("Issue #3781 recurrence rrule until with date only uses timezone offset incorrectly", async () => { + await helpers.startApplication("tests/configs/modules/calendar/fullday_until.js", "01 May 2025", [], "America/Los_Angeles"); + await expect(doTestCount()).resolves.toBe(1); + }); }); /* diff --git a/tests/mocks/fullday_until.ics b/tests/mocks/fullday_until.ics new file mode 100644 index 0000000000..ffdc293dcd --- /dev/null +++ b/tests/mocks/fullday_until.ics @@ -0,0 +1,28 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DESCRIPTION:\n +RRULE:FREQ=YEARLY;UNTIL=20250504T230000Z;INTERVAL=1;BYMONTHDAY=5;BYMONTH=5 +UID:040000008200E00074C5B7101A82E00800000000DAEF6ED30D9FDA01000000000000000 + 010000000D37F812F0777844A93E97B96AD2D278B +SUMMARY:Person A's Birthday +DTSTART;VALUE=DATE:20250505 +DTEND;VALUE=DATE:20250506 +CLASS:PUBLIC +PRIORITY:5 +DTSTAMP:20250428T133000Z +TRANSP:TRANSPARENT +STATUS:CONFIRMED +SEQUENCE:0 +LOCATION: +X-MICROSOFT-CDO-APPT-SEQUENCE:0 +X-MICROSOFT-CDO-BUSYSTATUS:FREE +X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY +X-MICROSOFT-CDO-ALLDAYEVENT:TRUE +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-CDO-INSTTYPE:1 +X-MICROSOFT-DONOTFORWARDMEETING:FALSE +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MICROSOFT-REQUESTEDATTENDANCEMODE:DEFAULT +X-MICROSOFT-ISRESPONSEREQUESTED:FALSE +END:VEVENT +END:VCALENDAR From 965e9358816defa57db91844e69572dcf51706e5 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 12 May 2025 23:40:05 +0200 Subject: [PATCH 219/418] [linter] Review linter setup (#3783) - [2b395b9f] Fix command to lint markdown in `CONTRIBUTING.md` - [fed4c86c] Re-activate JSDoc ESLint plugin and fix linting issues (As far as I remember, we deactivated it when we upgraded to ESLint 9 because it was not compatible with it. But its now.) - [a3d2064b] Refactor ESLint config to use `defineConfig` and `globalIgnores` ([these are like new defaults](https://eslint.org/blog/2025/03/flat-config-extends-define-config-global-ignores/)) - [a3d2064b] Replace `eslint-plugin-import` with `eslint-plugin-import-x` (https://github.com/es-tooling/module-replacements/blob/main/docs/modules/eslint-plugin-import.md) - [86a185b6] Switch Stylelint config to flat format and simplify Stylelint scripts (like we already did for ESLint and prettier) - [f5a2c541] Fix some typos --- .github/CONTRIBUTING.md | 4 +- .stylelintrc.json | 7 - CHANGELOG.md | 24 +- cspell.config.json | 4 + eslint.config.mjs | 54 +- js/check_config.js | 4 + .../default/calendar/calendarfetcherutils.js | 29 +- modules/default/newsfeed/newsfeed.js | 1 + modules/default/utils.js | 4 +- package-lock.json | 741 ++++++++++-------- package.json | 6 +- stylelint.config.mjs | 7 + tests/electron/modules/compliments_spec.js | 3 +- 13 files changed, 495 insertions(+), 393 deletions(-) delete mode 100644 .stylelintrc.json create mode 100644 stylelint.config.mjs diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index bbaeb71d13..37d01ccc4f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -18,7 +18,7 @@ To run ESLint, use `node --run lint:js`. ### CSS: Run StyleLint -We use [StyleLint](https://stylelint.io) to lint our CSS. The configuration is in our `.stylelintrc.json` file. +We use [StyleLint](https://stylelint.io) to lint our CSS. The configuration is in our `stylelint.config.mjs` file. To run StyleLint, use `node --run lint:css`. @@ -26,7 +26,7 @@ To run StyleLint, use `node --run lint:css`. We use [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) to lint our markdown files. The configuration is in our `.markdownlint.json` file. -To run markdownlint, use `node --run markdownlint:css`. +To run markdownlint, use `node --run lint:markdown`. ## Testing diff --git a/.stylelintrc.json b/.stylelintrc.json deleted file mode 100644 index 18ff23e703..0000000000 --- a/.stylelintrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": ["stylelint-config-standard"], - "plugins": ["stylelint-prettier"], - "rules": { - "prettier/prettier": true - } -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 37cd41cf90..8a24952ade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,15 +13,25 @@ planned for 2025-07-01 ### Added -- [config] Allow to change module order for final renderer (or dynamicaly with CSS): Feature `order` in config. (#3762) +- [config] Allow to change module order for final renderer (or dynamically with CSS): Feature `order` in config (#3762) - [clock] Added option 'disableNextEvent' to hide next sun event (#3769) ### Changed - [refactor] Simplify module loading process (#3766) -- Use `node --run` instead of `npm run` (#3764) and adapt `start:dev` script. -- [workflow] Run linter und spellcheck with LTS node version (#3767) +- Use `node --run` instead of `npm run` (#3764) and adapt `start:dev` script (#3773) +- [workflow] Run linter and spellcheck with LTS node version (#3767) - [workflow] Split "Run test" step into two steps for more clarity (#3767) +- [linter] Review linter setup (#3783) + - Fix command to lint markdown in `CONTRIBUTING.md` + - Re-activate JSDoc linting and fix linting issues + - Refactor ESLint config to use `defineConfig` and `globalIgnores` + - Replace `eslint-plugin-import` with `eslint-plugin-import-x` + - Switch Stylelint config to flat format and simplify Stylelint scripts + +### Fixed + +- [fix] Handle spellcheck issues (#3783) ### Fixed @@ -29,7 +39,7 @@ planned for 2025-07-01 ### Updated -- [core] Update dependencies +- [core] Update dependencies (#3774) ## [2.31.0] - 2025-04-01 @@ -40,7 +50,7 @@ Thanks to: @Developer-Incoming, @eltociear, @geraki, @khassel, @KristjanESPERANT ### Added - Add CSS support to the digital clock hour/minute/second through the use of the classes `clock-hour-digital`, `clock-minute-digital`, and `clock-second-digital`. -- Add Arabic (#3719) and Esperanto translation. +- Add Arabic (#3719) and Esperanto translation (#3740) - Mark option `secondsColor` as deprecated in clock module. - Add Greek translation to Alerts module. - [newsfeed] Add specific ignoreOlderThan value (override) per feed (#3360) @@ -50,7 +60,7 @@ Thanks to: @Developer-Incoming, @eltociear, @geraki, @khassel, @KristjanESPERANT ### Changed -- [core] Starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set wayland is used) (#3677) +- [core] Starting clientonly now checks for needed env var `WAYLAND_DISPLAY` or `DISPLAY` and starts electron with needed parameters (if both are set Wayland is used) (#3677) - [core] Optimize systeminformation calls and output (#3689) - [core] Add issue templates for feature requests and bug reports (#3695) - [core] Adapt `start:x11:dev` script @@ -88,7 +98,7 @@ Thanks to: @xsorifc28, @HeikoGr, @bugsounet, @khassel, @KristjanESPERANTO, @reja ### Added -- [core] Add wayland and windows start options to `package.json` (#3594) +- [core] Add Wayland and Windows start options to `package.json` (#3594) - [docs] Add step for npm publishing in release process (#3595) - [core] Add GitHub workflow to run spellcheck a few days before each release (#3623) - [core] Add test flag to `index.html` to pass to module js for test mode detection (needed by #3630) diff --git a/cspell.config.json b/cspell.config.json index a4ecc259fd..337a7ee890 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -59,6 +59,7 @@ "Edgardos", "Ekristoffe", "elec", + "eltociear", "envcanada", "envsub", "envsubst", @@ -82,6 +83,7 @@ "fulldate", "fullday", "fullscreen", + "geraki", "Gevoelstemperatuur", "GHSA", "ghsas", @@ -143,6 +145,7 @@ "Midori", "mirontoli", "MISSINGLANG", + "mixasgr", "MMPM", "modernizr", "modulename", @@ -183,6 +186,7 @@ "rohitdharavath", "Rosso", "rrule", + "savvadam", "sdetweil", "sendheaders", "serveronly", diff --git a/eslint.config.mjs b/eslint.config.mjs index 1f69ae342a..a22a0dc610 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,16 +1,14 @@ -import eslintPluginImport from "eslint-plugin-import"; -import eslintPluginJest from "eslint-plugin-jest"; -import eslintPluginJs from "@eslint/js"; -import eslintPluginPackageJson from "eslint-plugin-package-json"; -import eslintPluginStylistic from "@stylistic/eslint-plugin"; +import {defineConfig, globalIgnores} from "eslint/config"; import globals from "globals"; +import {flatConfigs as importX} from "eslint-plugin-import-x"; +import jest from "eslint-plugin-jest"; +import js from "@eslint/js"; +import jsdoc from "eslint-plugin-jsdoc"; +import packageJson from "eslint-plugin-package-json"; +import stylistic from "@stylistic/eslint-plugin"; -const config = [ - eslintPluginImport.flatConfigs.recommended, - eslintPluginJest.configs["flat/recommended"], - eslintPluginJs.configs.recommended, - eslintPluginPackageJson.configs.recommended, - eslintPluginStylistic.configs.all, +export default defineConfig([ + globalIgnores(["config/**", "modules/**/*", "!modules/default/**", "js/positions.js"]), { files: ["**/*.js"], languageOptions: { @@ -18,7 +16,6 @@ const config = [ globals: { ...globals.browser, ...globals.node, - ...globals.jest, Log: "readonly", MM: "readonly", Module: "readonly", @@ -26,6 +23,8 @@ const config = [ moment: "readonly" } }, + plugins: {js, jsdoc, stylistic}, + extends: [importX.recommended, jest.configs["flat/recommended"], "js/recommended", jsdoc.configs["flat/recommended"], "stylistic/all"], rules: { "@stylistic/array-element-newline": ["error", "consistent"], "@stylistic/arrow-parens": ["error", "always"], @@ -54,9 +53,9 @@ const config = [ "dot-notation": "error", eqeqeq: "error", "id-length": "off", - "import/extensions": "error", - "import/newline-after-import": "error", - "import/order": "error", + "import-x/extensions": "error", + "import-x/newline-after-import": "error", + "import-x/order": "error", "init-declarations": "off", "jest/consistent-test-it": "warn", "jest/no-done-callback": "warn", @@ -81,11 +80,15 @@ const config = [ "no-warning-comments": "off", "object-shorthand": ["error", "methods"], "one-var": "off", - "prefer-destructuring": "off", "prefer-template": "error", "sort-keys": "off" } }, + { + files: ["**/package.json"], + plugins: {packageJson}, + extends: ["packageJson/recommended"] + }, { files: ["**/*.mjs"], languageOptions: { @@ -95,19 +98,19 @@ const config = [ }, sourceType: "module" }, + plugins: {js, stylistic}, + extends: [importX.recommended, "js/all", "stylistic/all"], rules: { "@stylistic/array-element-newline": "off", "@stylistic/indent": ["error", "tab"], + "@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}], "@stylistic/padded-blocks": ["error", "never"], "@stylistic/quote-props": ["error", "as-needed"], - "func-style": "off", - "import/namespace": "off", - "import/no-unresolved": "off", + "import-x/no-unresolved": ["error", {ignore: ["eslint/config"]}], "max-lines-per-function": ["error", 100], "no-magic-numbers": "off", - "one-var": "off", - "prefer-destructuring": "off", - "sort-keys": "error" + "one-var": ["error", "never"], + "sort-keys": "off" } }, { @@ -115,10 +118,5 @@ const config = [ rules: { "@stylistic/quotes": "off" } - }, - { - ignores: ["config/**", "modules/**/*", "!modules/default/**", "js/positions.js"] } -]; - -export default config; +]); diff --git a/js/check_config.js b/js/check_config.js index d159d9f45a..50cf4f4463 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -72,6 +72,10 @@ function checkConfigFile () { } } +/** + * + * @param {string} configFileName - The path and filename of the configuration file to validate. + */ function validateModulePositions (configFileName) { Log.info("Checking modules structure configuration ..."); diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index c61fd33034..3b037f13c0 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -509,10 +509,10 @@ const CalendarFetcherUtils = { }, /** - * fixup thew event fields that have dates to use local time - * BEFORE calling rrule.between - * @param the event being processed - * @returns nothing + * Fixes the event fields that have dates to use local time + * before calling rrule.between. + * @param {object} event - The event being processed. + * @returns {void} */ fixEventtoLocal (event) { // if there are excluded dates, their date is incorrect and possibly key as well. @@ -549,9 +549,9 @@ const CalendarFetcherUtils = { /** * convert a UTC date to local time * BEFORE calling rrule.between - * @param date ti conert - * tz event is currently in - * @returns updated date object + * @param {Date} date The date to convert + * @param {string} tz The timezone string to convert the date to. + * @returns {Date} updated date object */ convertDateToLocalTime (date, tz) { let delta_tz_offset = 0; @@ -592,8 +592,8 @@ const CalendarFetcherUtils = { /** * get the exdate/recurrence hash key from the date object * BEFORE calling rrule.between - * @param the date of the event - * @returns string date key YYYY-MM-DD + * @param {Date} date The date of the event + * @returns {string} date key in the format YYYY-MM-DD */ getDateKeyFromDate (date) { // get our runtime timezone offset @@ -618,9 +618,8 @@ const CalendarFetcherUtils = { /** * get the timezone offset from the timezone string - * - * @param the timezone string - * @returns the numerical offset + * @param {string} timeZone The timezone string + * @returns {number} The numerical offset in minutes from UTC. */ getTimezoneOffsetFromTimezone (timeZone) { const str = new Date().toLocaleString("en", { timeZone, timeZoneName: "longOffset" }); @@ -631,10 +630,10 @@ const CalendarFetcherUtils = { /** * fixup the date start moment after rrule.between returns date array - * - * @param date object from rrule.between results + * @param {Date} date object from rrule.between results * the event object it came from - * @returns moment object + * @param {object} event - The event object it came from. + * @returns {Moment} moment object */ getAdjustedStartMoment (date, event) { diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 2907439d00..1e8cadfe1f 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -181,6 +181,7 @@ Module.register("newsfeed", { * Gets a feed property by name * @param {object} feed A feed object. * @param {string} property The name of the property. + * @returns {*} The value of the specified property for the feed. */ getFeedProperty (feed, property) { let res = this.config[property]; diff --git a/modules/default/utils.js b/modules/default/utils.js index 12d9b36a80..2d6e43ab10 100644 --- a/modules/default/utils.js +++ b/modules/default/utils.js @@ -5,7 +5,7 @@ * @param {boolean} useCorsProxy A flag to indicate * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive - * @param {string} basePath, default / + * @param {string} basePath The base path, default is "/" * @returns {Promise} resolved when the fetch is done. The response headers is placed in a headers-property (provided the response does not already contain a headers-property). */ async function performWebRequest (url, type = "json", useCorsProxy = false, requestHeaders = undefined, expectedResponseHeaders = undefined, basePath = "/") { @@ -38,7 +38,7 @@ async function performWebRequest (url, type = "json", useCorsProxy = false, requ * @param {string} url the url to fetch from * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive - * @param {string} basePath, default / + * @param {string} basePath The base path, default is "/" * @returns {string} to be used as URL when calling CORS-method on server. */ const getCorsUrl = function (url, requestHeaders, expectedResponseHeaders, basePath = "/") { diff --git a/package-lock.json b/package-lock.json index 6df94c5b5c..4bb2e2d649 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", "cspell": "^9.0.1", - "eslint-plugin-import": "^2.31.0", + "eslint-plugin-import-x": "^4.11.1", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-jsdoc": "^50.6.11", "eslint-plugin-package-json": "^0.31.0", @@ -1418,6 +1418,40 @@ "semver": "bin/semver.js" } }, + "node_modules/@emnapi/core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", + "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", + "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@es-joy/jsdoccomment": { "version": "0.49.0", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz", @@ -2178,6 +2212,19 @@ "node": ">=18" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz", + "integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.0", + "@emnapi/runtime": "^1.4.0", + "@tybys/wasm-util": "^0.9.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2404,6 +2451,12 @@ "node": ">=10" } }, + "node_modules/@pm2/io/node_modules/tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "license": "Apache-2.0" + }, "node_modules/@pm2/io/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -2488,13 +2541,6 @@ "debug": "^4.3.1" } }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", @@ -2628,6 +2674,17 @@ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", "license": "MIT" }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2761,13 +2818,6 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/katex": { "version": "0.16.7", "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", @@ -2953,6 +3003,247 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.2.tgz", + "integrity": "sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.2.tgz", + "integrity": "sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.2.tgz", + "integrity": "sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.2.tgz", + "integrity": "sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.2.tgz", + "integrity": "sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.2.tgz", + "integrity": "sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.2.tgz", + "integrity": "sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.2.tgz", + "integrity": "sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.2.tgz", + "integrity": "sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.2.tgz", + "integrity": "sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.2.tgz", + "integrity": "sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.2.tgz", + "integrity": "sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.2.tgz", + "integrity": "sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.2.tgz", + "integrity": "sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.9" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.2.tgz", + "integrity": "sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.2.tgz", + "integrity": "sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.2.tgz", + "integrity": "sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -3143,27 +3434,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-timsort": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", @@ -3181,66 +3451,6 @@ "node": ">=8" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", - "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", @@ -3274,12 +3484,6 @@ "node": ">=4" } }, - "node_modules/ast-types/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -5029,19 +5233,6 @@ "node": ">=8" } }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -5504,19 +5695,6 @@ "node": ">= 0.4" } }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/es-to-primitive": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", @@ -5693,110 +5871,33 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "node_modules/eslint-plugin-import-x": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.11.1.tgz", + "integrity": "sha512-CiqREASJRnhwCB0NujkTdo4jU+cJAnhQrd4aCnWC1o+rYWIWakVbyuzVbnCriUUSLAnn5CoJ2ob36TEgNzejBQ==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", + "@typescript-eslint/utils": "^8.31.0", + "comment-parser": "^1.4.1", + "debug": "^4.4.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "get-tsconfig": "^4.10.0", "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", - "tsconfig-paths": "^3.15.0" + "minimatch": "^9.0.3 || ^10.0.1", + "semver": "^7.7.1", + "stable-hash": "^0.0.5", + "tslib": "^2.8.1", + "unrs-resolver": "^1.7.0" }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" + "funding": { + "url": "https://opencollective.com/eslint-plugin-import-x" }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/eslint-plugin-jest": { @@ -6067,9 +6168,9 @@ "license": "MIT" }, "node_modules/eventsource": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", - "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", "license": "MIT", "dependencies": { "eventsource-parser": "^3.0.1" @@ -6787,6 +6888,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/get-uri": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", @@ -7280,9 +7394,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "license": "BSD-2-Clause", "optional": true }, @@ -10381,6 +10495,22 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-postinstall": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.3.tgz", + "integrity": "sha512-Mi7JISo/4Ij2tDZ2xBE2WH+/KvVlkhA6juEjpEeRAVPNCpN3nxJo/5FhDNKgBcdmcmhaH6JjgST4xY/23ZYK0w==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -10567,59 +10697,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -11877,6 +11954,16 @@ "node": ">=8" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve.exports": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", @@ -12007,12 +12094,6 @@ "tslib": "^2.4.0" } }, - "node_modules/rrule/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/rrweb-cssom": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", @@ -12804,6 +12885,13 @@ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", "license": "BSD-3-Clause" }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -13601,47 +13689,11 @@ "typescript": ">=4.8.4" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "license": "Apache-2.0" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tv4": { "version": "1.3.0", @@ -13894,6 +13946,39 @@ "node": ">= 0.8" } }, + "node_modules/unrs-resolver": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz", + "integrity": "sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/JounQin" + }, + "optionalDependencies": { + "@unrs/resolver-binding-darwin-arm64": "1.7.2", + "@unrs/resolver-binding-darwin-x64": "1.7.2", + "@unrs/resolver-binding-freebsd-x64": "1.7.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.7.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.7.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.7.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-x64-musl": "1.7.2", + "@unrs/resolver-binding-wasm32-wasi": "1.7.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.7.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.7.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.7.2" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", diff --git a/package.json b/package.json index d224f400c1..5096885b3f 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev", "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier", "install-vendor": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", - "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix", + "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --fix", "lint:js": "eslint --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", @@ -47,7 +47,7 @@ "test": "NODE_ENV=test jest -i --forceExit", "test:calendar": "node ./modules/default/calendar/debug.js", "test:coverage": "NODE_ENV=test jest --coverage -i --verbose false --forceExit", - "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json", + "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css'", "test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit", "test:electron": "NODE_ENV=test jest --selectProjects electron -i --forceExit", "test:js": "eslint", @@ -85,7 +85,7 @@ "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", "cspell": "^9.0.1", - "eslint-plugin-import": "^2.31.0", + "eslint-plugin-import-x": "^4.11.1", "eslint-plugin-jest": "^28.11.0", "eslint-plugin-jsdoc": "^50.6.11", "eslint-plugin-package-json": "^0.31.0", diff --git a/stylelint.config.mjs b/stylelint.config.mjs new file mode 100644 index 0000000000..5b1d8920a6 --- /dev/null +++ b/stylelint.config.mjs @@ -0,0 +1,7 @@ +const config = { + extends: ["stylelint-config-standard", "stylelint-prettier/recommended"], + root: true, + rules: {} +}; + +export default config; diff --git a/tests/electron/modules/compliments_spec.js b/tests/electron/modules/compliments_spec.js index 1cb23914fd..8745b25fcf 100644 --- a/tests/electron/modules/compliments_spec.js +++ b/tests/electron/modules/compliments_spec.js @@ -5,6 +5,7 @@ describe("Compliments module", () => { /** * move similar tests in function doTest * @param {Array} complimentsArray The array of compliments. + * @param {string} state The state of the element (e.g., "visible" or "attached"). * @returns {boolean} result */ const doTest = async (complimentsArray, state = "visible") => { @@ -35,7 +36,7 @@ describe("Compliments module", () => { await expect(doTest(["Hello There", "Good Evening", "Evening test"])).resolves.toBe(true); }); - it("doesnt show evening compliments during the day when the other parts of day are not set", async () => { + it("doesn't show evening compliments during the day when the other parts of day are not set", async () => { await helpers.startApplication("tests/configs/modules/compliments/compliments_evening.js", "01 Oct 2022 08:00:00 GMT"); await expect(doTest([""], "attached")).resolves.toBe(true); }); From 554bb0ed5c2fe30be9308d4c96f4c5962b44f5f5 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 15 May 2025 00:15:54 +0200 Subject: [PATCH 220/418] [feat] Add rule `no-undef` in config file validation (#3786) This should solve the problem #3785. --- CHANGELOG.md | 4 +--- js/check_config.js | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a24952ade..f82de5f079 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,10 +32,8 @@ planned for 2025-07-01 ### Fixed - [fix] Handle spellcheck issues (#3783) - -### Fixed - - [calendar] fix fullday event rrule until with timezone offset (#3781) +- [feat] Add rule `no-undef` in config file validation to fix #3785 (#3786) ### Updated diff --git a/js/check_config.js b/js/check_config.js index 50cf4f4463..b7912ced1e 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -54,7 +54,8 @@ function checkConfigFile () { globals: { ...globals.node } - } + }, + rules: { "no-undef": "error" } }, configFileName ); From 2f9f4b625329dda695f46b91cd3e4dbe74b0fdda Mon Sep 17 00:00:00 2001 From: BugHaver <43462320+bughaver@users.noreply.github.com> Date: Fri, 16 May 2025 16:04:18 +1000 Subject: [PATCH 221/418] [feature] implement short syntax for clock week (#3775) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hello and thank you for wanting to contribute to the MagicMirror² project! **Please make sure that you have followed these 4 rules before submitting your Pull Request:** > 1. Base your pull requests against the `develop` branch. > 2. Include these infos in the description: implement short syntax for clock week > > - Does the pull request solve a **related** issue? n/a > - If so, can you reference the issue like this `Fixes #`? > - What does the pull request accomplish? Use a list if needed. > - If it includes major visual changes please add screenshots. > > 3. Please run `npm run lint:prettier` before submitting so that > style issues are fixed. > 4. Don't forget to add an entry about your changes to > the CHANGELOG.md file. ![image](https://github.com/user-attachments/assets/e6c16981-de0a-45be-b553-7a7a67977d55) ![image](https://github.com/user-attachments/assets/ebae32e7-e6fb-41aa-971a-908880acc7b9) **Note**: Sometimes the development moves very fast. It is highly recommended that you update your branch of `develop` before creating a pull request to send us your changes. This makes everyone's lives easier (including yours) and helps us out on the development team. Thanks again and have a nice day! --------- Co-authored-by: BugHaver <43462320+lsaadeh@users.noreply.github.com> --- CHANGELOG.md | 1 + modules/default/clock/clock.js | 9 ++++-- .../modules/clock/clock_showWeek_short.js | 20 ++++++++++++ .../modules/clock/de/clock_showWeek.js | 21 +++++++++++++ .../modules/clock/de/clock_showWeek_short.js | 21 +++++++++++++ .../modules/clock/es/clock_showWeek_short.js | 21 +++++++++++++ tests/e2e/modules/clock_de_spec.js | 31 +++++++++++++++++++ tests/e2e/modules/clock_es_spec.js | 12 +++++++ tests/e2e/modules/clock_spec.js | 20 ++++++++++++ translations/de.json | 1 + translations/en.json | 1 + translations/es.json | 1 + translations/fr.json | 1 + 13 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 tests/configs/modules/clock/clock_showWeek_short.js create mode 100644 tests/configs/modules/clock/de/clock_showWeek.js create mode 100644 tests/configs/modules/clock/de/clock_showWeek_short.js create mode 100644 tests/configs/modules/clock/es/clock_showWeek_short.js create mode 100644 tests/e2e/modules/clock_de_spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index f82de5f079..f0c55e5209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ planned for 2025-07-01 - [config] Allow to change module order for final renderer (or dynamically with CSS): Feature `order` in config (#3762) - [clock] Added option 'disableNextEvent' to hide next sun event (#3769) +- [clock] Implement short syntax for clock week (#3775) ### Changed diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index f5c7411d23..d013cd25a0 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -14,7 +14,7 @@ Module.register("clock", { clockBold: false, showDate: true, showTime: true, - showWeek: false, + showWeek: false, // options: true, false, 'short' dateFormat: "dddd, LL", sendNotifications: false, @@ -224,7 +224,12 @@ Module.register("clock", { } if (this.config.showWeek) { - weekWrapper.innerHTML = this.translate("WEEK", { weekNumber: now.week() }); + if (this.config.showWeek === "short") { + weekWrapper.innerHTML = this.translate("WEEK_SHORT", { weekNumber: now.week() }); + } else { + weekWrapper.innerHTML = this.translate("WEEK", { weekNumber: now.week() }); + } + digitalWrapper.appendChild(weekWrapper); } diff --git a/tests/configs/modules/clock/clock_showWeek_short.js b/tests/configs/modules/clock/clock_showWeek_short.js new file mode 100644 index 0000000000..6728d01f8e --- /dev/null +++ b/tests/configs/modules/clock/clock_showWeek_short.js @@ -0,0 +1,20 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 12, + + modules: [ + { + module: "clock", + position: "middle_center", + config: { + showWeek: "short" + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/clock/de/clock_showWeek.js b/tests/configs/modules/clock/de/clock_showWeek.js new file mode 100644 index 0000000000..3adf26556a --- /dev/null +++ b/tests/configs/modules/clock/de/clock_showWeek.js @@ -0,0 +1,21 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + language: "de", + timeFormat: 12, + + modules: [ + { + module: "clock", + position: "middle_center", + config: { + showWeek: true + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/clock/de/clock_showWeek_short.js b/tests/configs/modules/clock/de/clock_showWeek_short.js new file mode 100644 index 0000000000..bdbdca7258 --- /dev/null +++ b/tests/configs/modules/clock/de/clock_showWeek_short.js @@ -0,0 +1,21 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + language: "de", + timeFormat: 12, + + modules: [ + { + module: "clock", + position: "middle_center", + config: { + showWeek: "short" + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/clock/es/clock_showWeek_short.js b/tests/configs/modules/clock/es/clock_showWeek_short.js new file mode 100644 index 0000000000..2581a2d46d --- /dev/null +++ b/tests/configs/modules/clock/es/clock_showWeek_short.js @@ -0,0 +1,21 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + language: "es", + timeFormat: 12, + + modules: [ + { + module: "clock", + position: "middle_center", + config: { + showWeek: "short" + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/e2e/modules/clock_de_spec.js b/tests/e2e/modules/clock_de_spec.js new file mode 100644 index 0000000000..e46b37abbc --- /dev/null +++ b/tests/e2e/modules/clock_de_spec.js @@ -0,0 +1,31 @@ +const helpers = require("../helpers/global-setup"); + +describe("Clock set to german language module", () => { + afterAll(async () => { + await helpers.stopApplication(); + }); + + describe("with showWeek config enabled", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/clock/de/clock_showWeek.js"); + await helpers.getDocument(); + }); + + it("shows week with correct format", async () => { + const weekRegex = /^[0-9]{1,2}. Kalenderwoche$/; + await expect(helpers.testMatch(".clock .week", weekRegex)).resolves.toBe(true); + }); + }); + + describe("with showWeek short config enabled", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/clock/de/clock_showWeek_short.js"); + await helpers.getDocument(); + }); + + it("shows week with correct format", async () => { + const weekRegex = /^[0-9]{1,2}KW$/; + await expect(helpers.testMatch(".clock .week", weekRegex)).resolves.toBe(true); + }); + }); +}); diff --git a/tests/e2e/modules/clock_es_spec.js b/tests/e2e/modules/clock_es_spec.js index 134c795b0a..38b997a50b 100644 --- a/tests/e2e/modules/clock_es_spec.js +++ b/tests/e2e/modules/clock_es_spec.js @@ -62,4 +62,16 @@ describe("Clock set to spanish language module", () => { await expect(helpers.testMatch(".clock .week", weekRegex)).resolves.toBe(true); }); }); + + describe("with showWeek short config enabled", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/clock/es/clock_showWeek_short.js"); + await helpers.getDocument(); + }); + + it("shows week with correct format", async () => { + const weekRegex = /^S[0-9]{1,2}$/; + await expect(helpers.testMatch(".clock .week", weekRegex)).resolves.toBe(true); + }); + }); }); diff --git a/tests/e2e/modules/clock_spec.js b/tests/e2e/modules/clock_spec.js index 9d9680e1c4..71470fec54 100644 --- a/tests/e2e/modules/clock_spec.js +++ b/tests/e2e/modules/clock_spec.js @@ -138,6 +138,26 @@ describe("Clock module", () => { }); }); + describe("with showWeek short config enabled", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/clock/clock_showWeek_short.js"); + await helpers.getDocument(); + }); + + it("should show the week in the correct format", async () => { + const weekRegex = /^W[0-9]{1,2}$/; + await expect(helpers.testMatch(".clock .week", weekRegex)).resolves.toBe(true); + }); + + it("should show the week with the correct number of week of year", async () => { + const currentWeekNumber = moment().week(); + const weekToShow = `W${currentWeekNumber}`; + const elem = await helpers.waitForElement(".clock .week"); + expect(elem).not.toBeNull(); + expect(elem.textContent).toBe(weekToShow); + }); + }); + describe("with analog clock face enabled", () => { beforeAll(async () => { await helpers.startApplication("tests/configs/modules/clock/clock_analog.js"); diff --git a/translations/de.json b/translations/de.json index d0f5eed7cb..86597b1601 100644 --- a/translations/de.json +++ b/translations/de.json @@ -9,6 +9,7 @@ "RUNNING": "noch", "EMPTY": "Keine Termine.", "WEEK": "{weekNumber}. Kalenderwoche", + "WEEK_SHORT": "{weekNumber}KW", "N": "N", "NNE": "NNO", diff --git a/translations/en.json b/translations/en.json index e10801e5b8..c4a2f196df 100644 --- a/translations/en.json +++ b/translations/en.json @@ -7,6 +7,7 @@ "RUNNING": "Ends in", "EMPTY": "No upcoming events.", "WEEK": "Week {weekNumber}", + "WEEK_SHORT": "W{weekNumber}", "N": "N", "NNE": "NNE", diff --git a/translations/es.json b/translations/es.json index 454dcf404e..67be6ab952 100644 --- a/translations/es.json +++ b/translations/es.json @@ -9,6 +9,7 @@ "RUNNING": "Termina en", "EMPTY": "No hay eventos programados.", "WEEK": "Semana {weekNumber}", + "WEEK_SHORT": "S{weekNumber}", "N": "N", "NNE": "NNE", diff --git a/translations/fr.json b/translations/fr.json index b7f9d02746..226f454fcf 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -9,6 +9,7 @@ "RUNNING": "Se termine dans", "EMPTY": "Aucun RDV à venir.", "WEEK": "Semaine {weekNumber}", + "WEEK_SHORT": "S{weekNumber}", "N": "N", "NNE": "NNE", From d1790513293dc1a6fe6765b0a22c5a041227697e Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 20 May 2025 06:48:10 +0200 Subject: [PATCH 222/418] fix `roboto.css` to avoid error message (#3787) --- CHANGELOG.md | 1 + fonts/roboto.css | 112 +++++++++++++++++++++++------------------------ 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0c55e5209..de39c21a02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ planned for 2025-07-01 - [fix] Handle spellcheck issues (#3783) - [calendar] fix fullday event rrule until with timezone offset (#3781) - [feat] Add rule `no-undef` in config file validation to fix #3785 (#3786) +- [fonts] Fix `roboto.css` to avoid error message `Unknown descriptor 'var(' in @font-face rule.` in firefox console ### Updated diff --git a/fonts/roboto.css b/fonts/roboto.css index bb760f8d8e..3743e4a872 100644 --- a/fonts/roboto.css +++ b/fonts/roboto.css @@ -2,7 +2,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 100; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-100-normal.woff2") format("woff2"), @@ -14,7 +14,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 100; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-100-normal.woff2") format("woff2"), @@ -26,7 +26,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 100; src: url("node_modules/@fontsource/roboto/files/roboto-greek-ext-100-normal.woff2") format("woff2"), @@ -38,7 +38,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 100; src: url("node_modules/@fontsource/roboto/files/roboto-greek-100-normal.woff2") format("woff2"), @@ -50,7 +50,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 100; src: url("node_modules/@fontsource/roboto/files/roboto-vietnamese-100-normal.woff2") format("woff2"), @@ -62,7 +62,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 100; src: url("node_modules/@fontsource/roboto/files/roboto-latin-ext-100-normal.woff2") format("woff2"), @@ -74,7 +74,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 100; src: url("node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff2") format("woff2"), @@ -86,7 +86,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-300-normal.woff2") format("woff2"), @@ -98,7 +98,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-300-normal.woff2") format("woff2"), @@ -110,7 +110,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto/files/roboto-greek-ext-300-normal.woff2") format("woff2"), @@ -122,7 +122,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto/files/roboto-greek-300-normal.woff2") format("woff2"), @@ -134,7 +134,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto/files/roboto-vietnamese-300-normal.woff2") format("woff2"), @@ -146,7 +146,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto/files/roboto-latin-ext-300-normal.woff2") format("woff2"), @@ -158,7 +158,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff2") format("woff2"), @@ -170,7 +170,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-400-normal.woff2") format("woff2"), @@ -182,7 +182,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-400-normal.woff2") format("woff2"), @@ -194,7 +194,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto/files/roboto-greek-ext-400-normal.woff2") format("woff2"), @@ -206,7 +206,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto/files/roboto-greek-400-normal.woff2") format("woff2"), @@ -218,7 +218,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto/files/roboto-vietnamese-400-normal.woff2") format("woff2"), @@ -230,7 +230,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto/files/roboto-latin-ext-400-normal.woff2") format("woff2"), @@ -242,7 +242,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff2") format("woff2"), @@ -254,7 +254,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 500; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-500-normal.woff2") format("woff2"), @@ -266,7 +266,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 500; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-500-normal.woff2") format("woff2"), @@ -278,7 +278,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 500; src: url("node_modules/@fontsource/roboto/files/roboto-greek-ext-500-normal.woff2") format("woff2"), @@ -290,7 +290,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 500; src: url("node_modules/@fontsource/roboto/files/roboto-greek-500-normal.woff2") format("woff2"), @@ -302,7 +302,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 500; src: url("node_modules/@fontsource/roboto/files/roboto-vietnamese-500-normal.woff2") format("woff2"), @@ -314,7 +314,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 500; src: url("node_modules/@fontsource/roboto/files/roboto-latin-ext-500-normal.woff2") format("woff2"), @@ -326,7 +326,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 500; src: url("node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff2") format("woff2"), @@ -338,7 +338,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-700-normal.woff2") format("woff2"), @@ -350,7 +350,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto/files/roboto-cyrillic-700-normal.woff2") format("woff2"), @@ -362,7 +362,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto/files/roboto-greek-ext-700-normal.woff2") format("woff2"), @@ -374,7 +374,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto/files/roboto-greek-700-normal.woff2") format("woff2"), @@ -386,7 +386,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto/files/roboto-vietnamese-700-normal.woff2") format("woff2"), @@ -398,7 +398,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto/files/roboto-latin-ext-700-normal.woff2") format("woff2"), @@ -410,7 +410,7 @@ @font-face { font-family: Roboto; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff2") format("woff2"), @@ -422,7 +422,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-300-normal.woff2") format("woff2"), @@ -434,7 +434,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-300-normal.woff2") format("woff2"), @@ -446,7 +446,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-300-normal.woff2") format("woff2"), @@ -458,7 +458,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-300-normal.woff2") format("woff2"), @@ -470,7 +470,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-300-normal.woff2") format("woff2"), @@ -482,7 +482,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-300-normal.woff2") format("woff2"), @@ -494,7 +494,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 300; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff2") format("woff2"), @@ -506,7 +506,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-400-normal.woff2") format("woff2"), @@ -518,7 +518,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-400-normal.woff2") format("woff2"), @@ -530,7 +530,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-400-normal.woff2") format("woff2"), @@ -542,7 +542,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-400-normal.woff2") format("woff2"), @@ -554,7 +554,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-400-normal.woff2") format("woff2"), @@ -566,7 +566,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-400-normal.woff2") format("woff2"), @@ -578,7 +578,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 400; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff2") format("woff2"), @@ -590,7 +590,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-700-normal.woff2") format("woff2"), @@ -602,7 +602,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-700-normal.woff2") format("woff2"), @@ -614,7 +614,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-700-normal.woff2") format("woff2"), @@ -626,7 +626,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-700-normal.woff2") format("woff2"), @@ -638,7 +638,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-700-normal.woff2") format("woff2"), @@ -650,7 +650,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-700-normal.woff2") format("woff2"), @@ -662,7 +662,7 @@ @font-face { font-family: "Roboto Condensed"; font-style: normal; - font-display: var(--fontsource-display, swap); + font-display: swap; font-weight: 700; src: url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff2") format("woff2"), From d07912d4b2b55031906a77545e4edb4f3903e4e2 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 23 May 2025 06:52:28 +0200 Subject: [PATCH 223/418] update dependencies incl. electron to v36 (#3788) --- CHANGELOG.md | 4 +- package-lock.json | 853 ++++++++++++++++++---------------------------- package.json | 20 +- 3 files changed, 336 insertions(+), 541 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de39c21a02..281cdee57c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ planned for 2025-07-01 ### Updated -- [core] Update dependencies (#3774) +- [core] Update dependencies incl. electron to v36 (#3774) ## [2.31.0] - 2025-04-01 @@ -1504,7 +1504,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we ### Fixed - Fix instruction in README for using automatically installer script. -- Bug of duplicated compliments as described in [here](https://forum.magicmirror.builders/topic/2381/compliments-module-stops-cycling-compliments). +- Bug of [duplicated compliments](https://forum.magicmirror.builders/topic/2381/compliments-module-stops-cycling-compliments). - Fix double message about port when server is starting - Corrected Swedish translations for TODAY/TOMORROW/DAYAFTERTOMORROW. - Removed unused import from js/electron.js diff --git a/package-lock.json b/package-lock.json index 4bb2e2d649..bb93cf60ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "ansis": "^4.0.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.26.0", + "eslint": "^9.27.0", "express": "^5.1.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -24,25 +24,25 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.20.1", - "pm2": "^6.0.5", + "pm2": "^6.0.6", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.25.11", - "undici": "^7.8.0" + "systeminformation": "^5.26.1", + "undici": "^7.10.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "cspell": "^9.0.1", - "eslint-plugin-import-x": "^4.11.1", + "cspell": "^9.0.2", + "eslint-plugin-import-x": "^4.12.2", "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.11", + "eslint-plugin-jsdoc": "^50.6.17", "eslint-plugin-package-json": "^0.31.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^26.1.0", - "lint-staged": "^15.5.2", - "markdownlint-cli2": "^0.17.2", + "lint-staged": "^16.0.0", + "markdownlint-cli2": "^0.18.1", "playwright": "^1.52.0", "prettier": "^3.5.3", "sinon": "^20.0.0", @@ -54,7 +54,7 @@ "node": ">=22.14.0" }, "optionalDependencies": { - "electron": "^35.3.0" + "electron": "^36.3.0" } }, "node_modules/@altano/repository-tools": { @@ -79,9 +79,9 @@ } }, "node_modules/@asamuzakjp/css-color": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.7.tgz", - "integrity": "sha512-Ok5fYhtwdyJQmU1PpEv6Si7Y+A4cYb8yNM9oiIJC9TzXPMuN9fvdonKJqcnz9TbFqV6bQ8z0giRq0iaOpGZV2g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", "dev": true, "license": "MIT", "dependencies": { @@ -616,9 +616,9 @@ "license": "MIT" }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.0.1.tgz", - "integrity": "sha512-h7gTqg0VF4N8VhOPk66XewuSsT56OP2ujgxtAyYQ4H+NuYd3HMfS0h/I3/y9uBhllwOEamaeAzYhc5JF/qIrsQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.0.2.tgz", + "integrity": "sha512-gGFSfVIvYtO95O3Yhcd1o0sOZHjVaCPwYq3MnaNsBBzaMviIZli4FZW9Z+XNKsgo1zRzbl2SdOXJPP0VcyAY0A==", "dev": true, "license": "MIT", "dependencies": { @@ -646,7 +646,7 @@ "@cspell/dict-fsharp": "^1.1.0", "@cspell/dict-fullstack": "^3.2.6", "@cspell/dict-gaming-terms": "^1.1.1", - "@cspell/dict-git": "^3.0.4", + "@cspell/dict-git": "^3.0.5", "@cspell/dict-golang": "^6.0.21", "@cspell/dict-google": "^1.0.8", "@cspell/dict-haskell": "^4.0.5", @@ -673,7 +673,7 @@ "@cspell/dict-rust": "^4.0.11", "@cspell/dict-scala": "^5.0.7", "@cspell/dict-shell": "^1.1.0", - "@cspell/dict-software-terms": "^5.0.8", + "@cspell/dict-software-terms": "^5.0.9", "@cspell/dict-sql": "^2.2.0", "@cspell/dict-svelte": "^1.0.6", "@cspell/dict-swift": "^2.0.5", @@ -686,22 +686,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.0.1.tgz", - "integrity": "sha512-Rpn7Tuq9t8bZpXZFV43NkhCl0LaPDJZSON4/JFxGbOcH16ryXfrx7oObUTIIyxSxO3fGkzaJZHIwGibRJSsbNQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.0.2.tgz", + "integrity": "sha512-Hy9hKG53cFhLwiSZuRVAd5YfBb5pPj3V2Val69TW1j4+sy3podewqm4sb3RqoB01LcDkLI/mOeMwHz1xyIjfoA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.0.1" + "@cspell/cspell-types": "9.0.2" }, "engines": { "node": ">=20" } }, "node_modules/@cspell/cspell-pipe": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.0.1.tgz", - "integrity": "sha512-bhFcvF2a8KYKVh/OebCfJ8LFw5GYHyUsUjAbxnznTBrYOFSIclDjwUwT29yVDXwnQkJkB6Px5Y9e2VvtFizVFg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.0.2.tgz", + "integrity": "sha512-M1e+u3dyGCJicSZ16xmoVut4pI8ynfqILYiDAYC9+rbn04wJdnWD46ElIZnRriFXx7fu/UsUEexu3lFaqKVGEg==", "dev": true, "license": "MIT", "engines": { @@ -709,9 +709,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.0.1.tgz", - "integrity": "sha512-AhIXAhX1qt7Y3EyiP/5rAk7Ow7DJpAyB44wPbfdF9p1vhnk6oQ7RslnD3G6S9o/vNxZ0DWFPREMWx19J/3c+hw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.0.2.tgz", + "integrity": "sha512-JkMQb+hcEyZ2ALvEeJvfxoIblRpZlnek50Ew5sLSSZciRuhNvQZS5+Apwt1GXHitTo8/bqXFxABNP36O++YAwA==", "dev": true, "license": "MIT", "dependencies": { @@ -722,9 +722,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.0.1.tgz", - "integrity": "sha512-DoW6hLkFIO3BXePtUYQEax3FTH9fkwCUbf6qphAEXnr4PjoyPZsgBhR6iCrZd4DyhuFiRvK3Cgpq2o3O0NdODQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.0.2.tgz", + "integrity": "sha512-OjfZ3vnBjmkctC9xs/87/9bx/3kZYUPJkWsZxzfH4rla/HeIUrm9UZlDqCibhWifhPHrDdV9hDW5QEGXkYR2hw==", "dev": true, "license": "MIT", "engines": { @@ -732,9 +732,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.0.1.tgz", - "integrity": "sha512-8FRmvyV1AYEepJB3J7jji1ZYG9yOK0eYr4WuUVPfUJa6N3HyeZjWKhxbVvqedmEI74f5Ls3cQKHY1T2Yvqk/ag==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.0.2.tgz", + "integrity": "sha512-RioULo34qbUXuCCLi/DCDxdb++Nm1ospNXzVkKZrSvTG4AjkC95ZhfIOp9jbGSWqL2PGdaHVXgG77EyQbAk5xA==", "dev": true, "license": "MIT", "engines": { @@ -850,9 +850,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.8.tgz", - "integrity": "sha512-OkNUVuU9Q+Sf827/61YPkk6ya6dSsllzeYniBFqNW9TkoqQXT3vggkgmtCE1aEhSvVctMwxpPYoC8pZgn1TeSA==", + "version": "4.4.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.9.tgz", + "integrity": "sha512-5gjqpUwhE+qP9A9wxD1+MGGJ3DNqTgSpiOsS10cGJfV4p/Z194XkDUZrUrJsnJA/3fsCZHAzcNWh8m0bw1v++A==", "dev": true, "license": "MIT" }, @@ -864,9 +864,9 @@ "license": "CC BY-SA 4.0" }, "node_modules/@cspell/dict-en-gb-mit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.0.6.tgz", - "integrity": "sha512-QYDwuXi9Yh+AvU1omhz8sWX+A1SxWI3zeK1HdGfTrICZavhp8xxcQGTa5zxTTFRCcQc483YzUH2Dl+6Zd50tJg==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.0.7.tgz", + "integrity": "sha512-fdZbu4jbkzjjTO0jPBGINwQwzNFGapMnhH9D4mDa4UzGGyQFVRx6n/FFwxnfs7CXbuCV6UFSwjHZEAB8pfWn0A==", "dev": true, "license": "MIT" }, @@ -913,9 +913,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-git": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.4.tgz", - "integrity": "sha512-C44M+m56rYn6QCsLbiKiedyPTMZxlDdEYAsPwwlL5bhMDDzXZ3Ic8OCQIhMbiunhCOJJT+er4URmOmM+sllnjg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.5.tgz", + "integrity": "sha512-I7l86J2nOcpBY0OcwXLTGMbcXbEE7nxZme9DmYKrNgmt35fcLu+WKaiXW7P29V+lIXjJo/wKrEDY+wUEwVuABQ==", "dev": true, "license": "MIT" }, @@ -1038,9 +1038,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.3.tgz", - "integrity": "sha512-EdGkCpAq66Mhi9Qldgsr+NvPVL4TdtmdlqDe4VBp0P3n6J0B7b0jT1MlVDIiLR+F1eqBfL0qjfHf0ey1CafeNw==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.4.tgz", + "integrity": "sha512-/hK5ii9OzSOQkmTjkzJlEYWz+PBnz2hRq5Xu7d4aDURaynO9xMAcK31JJlKNQulBkVbQHxFZLUrzjdzdAr/Opw==", "dev": true, "license": "MIT" }, @@ -1111,9 +1111,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.0.8.tgz", - "integrity": "sha512-VsJesitvaHZpMgNwHHms3yDsZz7LNToC2HuSAnyt1znn37ribiJF1ty0jWhVQO6fv7K4PM1KsKTJIwqBwc446g==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.0.10.tgz", + "integrity": "sha512-2nTcVKTYJKU5GzeviXGPtRRC9d23MtfpD4PM4pLSzl29/5nx5MxOUHkzPuJdyaw9mXIz8Rm9IlGeVAvQoTI8aw==", "dev": true, "license": "MIT" }, @@ -1160,13 +1160,13 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.0.1.tgz", - "integrity": "sha512-BoWzHwkufo90ubMZUN8Jy4HQYYWFW7psVCdG/4RUgfvVnazkPfLxWBbsPQsLrlIP0utaqei7D9FU0K7r7mpl4A==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.0.2.tgz", + "integrity": "sha512-KhcoNUj6Ij2P8fbRC7QOn3jzbTZFxoQpFGanGU9f+4DfZBH86PCADyKYH+ZpJPlYgrI+Jh4wKzF5y5YKKNrdrw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.0.1", + "@cspell/url": "9.0.2", "import-meta-resolve": "^4.1.0" }, "engines": { @@ -1174,9 +1174,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.0.1.tgz", - "integrity": "sha512-swZu3ra2AueyjEz/bPsvwFuHGYhjWZBx1K9FSvZA/yDIX5RVr6orQSuf9zvXNFui6Nyk0tudLnn3y9jT0LHk8A==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.0.2.tgz", + "integrity": "sha512-8KEIgptldoZT3pM+yhYV8nXq5T9Sz0YvZIqwDGEqKJ6j447K+I91QWS7RQDrvHkElMi/2g/h08Efg0RIT+QEaQ==", "dev": true, "license": "MIT", "engines": { @@ -1184,9 +1184,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.0.1.tgz", - "integrity": "sha512-u87PWr1xACqs/F3HibZ4Eb0Za/ghWIa6WLvEKV9OaiLfEUQuczbrXPVgHmGr83H0XXWUKy8FvVbWGFmXwiw+gQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.0.2.tgz", + "integrity": "sha512-SHTPUcu2e6aYxI5sr1L/9pzz68CArV6WzMvAio//5LbtKI6NtDp/7tARBwLi1G3A3C0289zDHbDKm3wc1lRNhQ==", "dev": true, "license": "MIT", "engines": { @@ -1194,9 +1194,9 @@ } }, "node_modules/@cspell/url": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.0.1.tgz", - "integrity": "sha512-8xaLrsQ742dmwXwS6tjreps3NpSQe6WEZFPQQT2DprVJXGZnfQR8ob0c+kPhD0hu9A6PwShJsRsfh3DQGKCqAw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.0.2.tgz", + "integrity": "sha512-KwCDL0ejgwVSZB8KTp8FhDe42UOaebTVIMi3O5GcYHi9Cut8B5QU4tbQOFGXP6E4pjimeO9yIkr9Z34kTljj/g==", "dev": true, "license": "MIT", "engines": { @@ -1453,18 +1453,20 @@ } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz", - "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==", + "version": "0.50.2", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.50.2.tgz", + "integrity": "sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA==", "dev": true, "license": "MIT", "dependencies": { + "@types/estree": "^1.0.6", + "@typescript-eslint/types": "^8.11.0", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.1.0" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -1552,9 +1554,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -1631,12 +1633,15 @@ } }, "node_modules/@eslint/js": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", - "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", + "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { @@ -1649,12 +1654,12 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", - "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", + "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.13.0", + "@eslint/core": "^0.14.0", "levn": "^0.4.1" }, "engines": { @@ -2191,37 +2196,16 @@ "buffer": "^6.0.3" } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.1.tgz", - "integrity": "sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==", - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.3", - "eventsource": "^3.0.2", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz", - "integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz", + "integrity": "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.4.0", - "@emnapi/runtime": "^1.4.0", + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.9.0" } }, @@ -2843,9 +2827,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", - "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", + "version": "22.15.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz", + "integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -2903,14 +2887,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", - "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0" + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2921,9 +2905,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", - "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "dev": true, "license": "MIT", "engines": { @@ -2935,14 +2919,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", - "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2962,16 +2946,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", - "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0" + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2986,13 +2970,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", - "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -4028,9 +4012,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001717", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", - "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", + "version": "1.0.30001718", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", + "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", "dev": true, "funding": [ { @@ -4427,13 +4411,13 @@ } }, "node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/comment-json": { @@ -4628,28 +4612,28 @@ } }, "node_modules/cspell": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.0.1.tgz", - "integrity": "sha512-AJqsX+3eSTz9GmIuyEZUzCCTbvCPw6+Nv7UYa4PCn7vNV3XEb5LHTp5i9y2i65fNaeNEcQXLrLYoY/JcBFmUSQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.0.2.tgz", + "integrity": "sha512-VwPNTTivvv/NyovXUMcTYc7BaOgun7k8FhRWaVKxZPEsl/9r9WTLmQ1dNbHRq56LajH2b7wKGQYuRsfov3UWTg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "9.0.1", - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-types": "9.0.1", - "@cspell/dynamic-import": "9.0.1", - "@cspell/url": "9.0.1", + "@cspell/cspell-json-reporter": "9.0.2", + "@cspell/cspell-pipe": "9.0.2", + "@cspell/cspell-types": "9.0.2", + "@cspell/dynamic-import": "9.0.2", + "@cspell/url": "9.0.2", "chalk": "^5.4.1", "chalk-template": "^1.1.0", - "commander": "^13.1.0", - "cspell-dictionary": "9.0.1", - "cspell-gitignore": "9.0.1", - "cspell-glob": "9.0.1", - "cspell-io": "9.0.1", - "cspell-lib": "9.0.1", + "commander": "^14.0.0", + "cspell-dictionary": "9.0.2", + "cspell-gitignore": "9.0.2", + "cspell-glob": "9.0.2", + "cspell-io": "9.0.2", + "cspell-lib": "9.0.2", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^9.1.0", - "semver": "^7.7.1", + "semver": "^7.7.2", "tinyglobby": "^0.2.13" }, "bin": { @@ -4664,30 +4648,30 @@ } }, "node_modules/cspell-config-lib": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.0.1.tgz", - "integrity": "sha512-hbeyU6cY4NPKh69L4QpBZgGz00f7rLk10xPlCo6MxEmCqSOTuXXvDEUR51d2ED69G+GyFAeZi5VU9IdJ4jhvzQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.0.2.tgz", + "integrity": "sha512-8rCmGUEzlytnNeAazvbBdLeUoN18Cct8k6KLePiUS0GglYomSAvcPWsamSk9jeh947m0cu2dhjZPnKQlp11XBA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.0.1", + "@cspell/cspell-types": "9.0.2", "comment-json": "^4.2.5", - "yaml": "^2.7.1" + "yaml": "^2.8.0" }, "engines": { "node": ">=20" } }, "node_modules/cspell-dictionary": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.0.1.tgz", - "integrity": "sha512-I9gjRpfV4djxN0i2p9OzWIrkjtUaGUyVE9atvRbkHUMeqDUhC2Qt0Mb9tnF8I7qnHeZt+U44vUa9Dg7yrJ+k4Q==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.0.2.tgz", + "integrity": "sha512-u1jLnqu+2IJiGKdUP9LF1/vseOrCh6hUACHZQ8JsCbHC2KU/DL68s4IgS5jDyK5lBcwPOWzQOiTuXQSEardpFQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-types": "9.0.1", - "cspell-trie-lib": "9.0.1", + "@cspell/cspell-pipe": "9.0.2", + "@cspell/cspell-types": "9.0.2", + "cspell-trie-lib": "9.0.2", "fast-equals": "^5.2.2" }, "engines": { @@ -4695,15 +4679,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.0.1.tgz", - "integrity": "sha512-xjgOmeGbHEaeF0erRQ2QXwqxWqGDiI4mu+NjCL7ZHPoAM5y8PEO6IbxVNabIB1xC4QAborbtEQ/8ydDWLJcPoQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.0.2.tgz", + "integrity": "sha512-2CXpUYa+mf1I0oMH/V0qzT0zP95IqYzaS9BfEB7AcSmjrvuIgmiGLztUNrG5mMMBAlHk7sfI8gAEMMvr/Q7sTQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.0.1", - "cspell-glob": "9.0.1", - "cspell-io": "9.0.1" + "@cspell/url": "9.0.2", + "cspell-glob": "9.0.2", + "cspell-io": "9.0.2" }, "bin": { "cspell-gitignore": "bin.mjs" @@ -4713,13 +4697,13 @@ } }, "node_modules/cspell-glob": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.0.1.tgz", - "integrity": "sha512-dQU/ln6J9Qe31zk1cLJnq/WNAjRrTUig1GG8WA2oK1jHZKY9VbyJLb5DUFnDUx35cI0jdOEnGSCWi8qNjHSc1Q==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.0.2.tgz", + "integrity": "sha512-trTskAU7tw9RpCb+/uPM4zWByZEavHh3SIrjz7Du/ritjZi85O80HItNw5O3ext4zSPfNNLL3kBT7fLLphFHrw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.0.1", + "@cspell/url": "9.0.2", "picomatch": "^4.0.2" }, "engines": { @@ -4727,14 +4711,14 @@ } }, "node_modules/cspell-grammar": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.0.1.tgz", - "integrity": "sha512-FZ1z1p3pslfotZT/W/VRZjB4S+z0ETrTbNmQ5pGmhdY0nm7Slmg+8nIJluLEjBneBGTJIOcLjYykwS2vI6jzxw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.0.2.tgz", + "integrity": "sha512-3hrNZJYEgWSaCvH3rpFq43PX9pxdJt60+pFG3CTZAdpcI97DDsrdH3f7a6h8sNAb+pN59JnV2DtWexsAVL6vjA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-types": "9.0.1" + "@cspell/cspell-pipe": "9.0.2", + "@cspell/cspell-types": "9.0.2" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4744,42 +4728,42 @@ } }, "node_modules/cspell-io": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.0.1.tgz", - "integrity": "sha512-L5fZY0glVeQb6nmt1WL1wKzZzoHJUkBQ9BGCrwqSXIrjZrYmBNSKixCjo6o9n2keRUwpNjsvZj1TQDKDV+FsXA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.0.2.tgz", + "integrity": "sha512-TO93FTgQjjp62nAn213885RdyOTsQwdjSHdeYaaNiaTBOBgj2jR8M8bi3+h2imGBlinlYERoVbPF9wghJEK2nw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "9.0.1", - "@cspell/url": "9.0.1" + "@cspell/cspell-service-bus": "9.0.2", + "@cspell/url": "9.0.2" }, "engines": { "node": ">=20" } }, "node_modules/cspell-lib": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.0.1.tgz", - "integrity": "sha512-F4vJG6GmAGVAuhgcepO12UtG7yev7Rcfa31MLIyYNTrd5NeORzM+GTHnL970FlEflwYPYjcSTGwkyowQ+ZbmDg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.0.2.tgz", + "integrity": "sha512-uoPQ0f+umOGUQB/q0H+K/gWfd7xJMaPlt5rXMMTeKIPHLDRBE7lBx4mHVCmgevL+oTNSLpIE5FdqRDbr+Q+Awg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "9.0.1", - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-resolver": "9.0.1", - "@cspell/cspell-types": "9.0.1", - "@cspell/dynamic-import": "9.0.1", - "@cspell/filetypes": "9.0.1", - "@cspell/strong-weak-map": "9.0.1", - "@cspell/url": "9.0.1", + "@cspell/cspell-bundled-dicts": "9.0.2", + "@cspell/cspell-pipe": "9.0.2", + "@cspell/cspell-resolver": "9.0.2", + "@cspell/cspell-types": "9.0.2", + "@cspell/dynamic-import": "9.0.2", + "@cspell/filetypes": "9.0.2", + "@cspell/strong-weak-map": "9.0.2", + "@cspell/url": "9.0.2", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "9.0.1", - "cspell-dictionary": "9.0.1", - "cspell-glob": "9.0.1", - "cspell-grammar": "9.0.1", - "cspell-io": "9.0.1", - "cspell-trie-lib": "9.0.1", + "cspell-config-lib": "9.0.2", + "cspell-dictionary": "9.0.2", + "cspell-glob": "9.0.2", + "cspell-grammar": "9.0.2", + "cspell-io": "9.0.2", + "cspell-trie-lib": "9.0.2", "env-paths": "^3.0.0", "fast-equals": "^5.2.2", "gensequence": "^7.0.0", @@ -4794,14 +4778,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.0.1.tgz", - "integrity": "sha512-gIupiHwLdsQun79biJgiqmXffKUGzFjGLFEeVptI2Zy5Oa3XhRJsHap4PyeleErONkpzxMG1tgpOWzhOqwl65Q==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.0.2.tgz", + "integrity": "sha512-inXu6YEoJFLYnxgcXy3quCoGgSWYRye1kM4dj8kbYtNAQgUVD93hPFdmPWObwhVawsS3rQybckG3DSnmxBe9Fg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.0.1", - "@cspell/cspell-types": "9.0.1", + "@cspell/cspell-pipe": "9.0.2", + "@cspell/cspell-types": "9.0.2", "gensequence": "^7.0.0" }, "engines": { @@ -4968,9 +4952,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5309,9 +5293,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "35.3.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-35.3.0.tgz", - "integrity": "sha512-6dLslJrQYB1qvqVPYRv1PhAA/uytC66nUeiTcq2JXiBzrmTWCHppqtGUjZhvnSRVatBCT5/SFdizdzcBiEiYUg==", + "version": "36.3.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-36.3.0.tgz", + "integrity": "sha512-xk5AJtjxfFRAmehcChWSz/duxI+bJiUCIkH2IX2z8K1SyGsWdpqg+NoJ20JRQ6dpSJw89KXH6juESp8nSyBexA==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5328,9 +5312,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.151", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.151.tgz", - "integrity": "sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA==", + "version": "1.5.156", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.156.tgz", + "integrity": "sha512-QeOqv11TSASsY/3Ft3LUyDqEiEOph5/85srEPFUo9wuGFNTb0/z5fGE/+ZzTrYvSTGoXNkdQLTw3MKRmgyOyGA==", "dev": true, "license": "ISC" }, @@ -5586,27 +5570,27 @@ } }, "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "version": "1.23.10", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.10.tgz", + "integrity": "sha512-MtUbM072wlJNyeYAe0mhzrD+M6DIJa96CZAOBBrhDbgKnB4MApIKefcyAB1eOdYn8cUNZgvwBvEzdoAYsxgEIw==", "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -5622,13 +5606,13 @@ "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", + "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", + "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", @@ -5641,7 +5625,7 @@ "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -5769,23 +5753,22 @@ } }, "node_modules/eslint": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", - "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", + "version": "9.27.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", + "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.13.0", + "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.26.0", - "@eslint/plugin-kit": "^0.2.8", + "@eslint/js": "9.27.0", + "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", - "@modelcontextprotocol/sdk": "^1.8.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -5809,8 +5792,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "zod": "^3.24.2" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -5872,9 +5854,9 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.11.1.tgz", - "integrity": "sha512-CiqREASJRnhwCB0NujkTdo4jU+cJAnhQrd4aCnWC1o+rYWIWakVbyuzVbnCriUUSLAnn5CoJ2ob36TEgNzejBQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.12.2.tgz", + "integrity": "sha512-0jVUgJQipbs0yUfLe7LwYD6p8rIGqCysWZdyJFgkPzDyJgiKpuCaXlywKUAWgJ6u1nLpfrdt21B60OUkupyBrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5927,13 +5909,13 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.11", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.11.tgz", - "integrity": "sha512-k4+MnBCGR8cuIB5MZ++FGd4gbXxjob2rX1Nq0q3nWFF4xSGZENTgTLZSjb+u9B8SAnP6lpGV2FJrBjllV3pVSg==", + "version": "50.6.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.17.tgz", + "integrity": "sha512-hq+VQylhd12l8qjexyriDsejZhqiP33WgMTy2AmaGZ9+MrMWVqPECsM87GPxgHfQn0zw+YTuhqjUfk1f+q67aQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.49.0", + "@es-joy/jsdoccomment": "~0.50.1", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.6", @@ -6167,27 +6149,6 @@ "dev": true, "license": "MIT" }, - "node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", - "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -6318,21 +6279,6 @@ "node": ">=8.9.0" } }, - "node_modules/express-rate-limit": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", - "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": "^4.11 || 5 || ^5.0.0-beta.1" - } - }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -6889,9 +6835,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7106,18 +7052,18 @@ } }, "node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", "dev": true, "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" + "unicorn-magic": "^0.3.0" }, "engines": { "node": ">=18" @@ -7126,6 +7072,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globby/node_modules/ignore": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/globby/node_modules/slash": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", @@ -9199,28 +9155,28 @@ } }, "node_modules/lint-staged": { - "version": "15.5.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", - "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.0.0.tgz", + "integrity": "sha512-sUCprePs6/rbx4vKC60Hez6X10HPkpDJaGcy3D1NdwR7g1RcNkWL8q9mJMreOqmHBTs+1sNFp+wOiX9fr+hoOQ==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^5.4.1", "commander": "^13.1.0", "debug": "^4.4.0", - "execa": "^8.0.1", "lilconfig": "^3.1.3", - "listr2": "^8.2.5", + "listr2": "^8.3.3", "micromatch": "^4.0.8", + "nano-spawn": "^1.0.0", "pidtree": "^0.6.0", "string-argv": "^0.3.2", - "yaml": "^2.7.0" + "yaml": "^2.7.1" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=18.12.0" + "node": ">=20.18" }, "funding": { "url": "https://opencollective.com/lint-staged" @@ -9239,148 +9195,14 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/lint-staged/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/lint-staged/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "node_modules/lint-staged/node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, "node_modules/listr2": { @@ -9619,40 +9441,40 @@ } }, "node_modules/markdownlint": { - "version": "0.37.4", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.37.4.tgz", - "integrity": "sha512-u00joA/syf3VhWh6/ybVFkib5Zpj2e5KB/cfCei8fkSRuums6nyisTWGqjTWIOFoFwuXoTBQQiqlB4qFKp8ncQ==", + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.38.0.tgz", + "integrity": "sha512-xaSxkaU7wY/0852zGApM8LdlIfGCW8ETZ0Rr62IQtAnUMlMuifsg09vWJcNYeL4f0anvr8Vo4ZQar8jGpV0btQ==", "dev": true, "license": "MIT", "dependencies": { - "markdown-it": "14.1.0", - "micromark": "4.0.1", - "micromark-core-commonmark": "2.0.2", - "micromark-extension-directive": "3.0.2", + "micromark": "4.0.2", + "micromark-core-commonmark": "2.0.3", + "micromark-extension-directive": "4.0.0", "micromark-extension-gfm-autolink-literal": "2.1.0", "micromark-extension-gfm-footnote": "2.1.0", - "micromark-extension-gfm-table": "2.1.0", + "micromark-extension-gfm-table": "2.1.1", "micromark-extension-math": "3.1.0", - "micromark-util-types": "2.0.1" + "micromark-util-types": "2.0.2" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/DavidAnson" } }, "node_modules/markdownlint-cli2": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.17.2.tgz", - "integrity": "sha512-XH06ZOi8wCrtOSSj3p8y3yJzwgzYOSa7lglNyS3fP05JPRzRGyjauBb5UvlLUSCGysMmULS1moxdRHHudV+g/Q==", + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.18.1.tgz", + "integrity": "sha512-/4Osri9QFGCZOCTkfA8qJF+XGjKYERSHkXzxSyS1hd3ZERJGjvsUao2h4wdnvpHp6Tu2Jh/bPHM0FE9JJza6ng==", "dev": true, "license": "MIT", "dependencies": { - "globby": "14.0.2", + "globby": "14.1.0", "js-yaml": "4.1.0", "jsonc-parser": "3.3.1", - "markdownlint": "0.37.4", + "markdown-it": "14.1.0", + "markdownlint": "0.38.0", "markdownlint-cli2-formatter-default": "0.0.5", "micromatch": "4.0.8" }, @@ -9660,7 +9482,7 @@ "markdownlint-cli2": "markdownlint-cli2-bin.mjs" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/DavidAnson" @@ -9778,9 +9600,9 @@ } }, "node_modules/micromark": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.1.tgz", - "integrity": "sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", "dev": true, "funding": [ { @@ -9814,9 +9636,9 @@ } }, "node_modules/micromark-core-commonmark": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.2.tgz", - "integrity": "sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", "dev": true, "funding": [ { @@ -9849,9 +9671,9 @@ } }, "node_modules/micromark-extension-directive": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", - "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz", + "integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==", "dev": true, "license": "MIT", "dependencies": { @@ -9907,9 +9729,9 @@ } }, "node_modules/micromark-extension-gfm-table": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", - "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", "dev": true, "license": "MIT", "dependencies": { @@ -10297,9 +10119,9 @@ "license": "MIT" }, "node_modules/micromark-util-types": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.1.tgz", - "integrity": "sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "dev": true, "funding": [ { @@ -10476,6 +10298,19 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "license": "ISC" }, + "node_modules/nano-spawn": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.2.tgz", + "integrity": "sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -10496,9 +10331,9 @@ } }, "node_modules/napi-postinstall": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.3.tgz", - "integrity": "sha512-Mi7JISo/4Ij2tDZ2xBE2WH+/KvVlkhA6juEjpEeRAVPNCpN3nxJo/5FhDNKgBcdmcmhaH6JjgST4xY/23ZYK0w==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz", + "integrity": "sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==", "dev": true, "license": "MIT", "bin": { @@ -11033,13 +10868,13 @@ } }, "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11116,15 +10951,6 @@ "node": ">= 6" } }, - "node_modules/pkce-challenge": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", - "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -11242,18 +11068,18 @@ } }, "node_modules/pm2": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.5.tgz", - "integrity": "sha512-+O43WPaEiwYbm6/XSpAOO1Rtya/Uof0n7x8hJZGfwIuepesNTIVArpZh4KqFfze0cvvqZMr0maTW3ifhvmyeMQ==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.6.tgz", + "integrity": "sha512-6t+I+Gc232dKe0OjwFYlU59JoY8MWBqsBmcZMSfKollByL4q8APUFwWOt7OtPH4lGO4Sb6GiFAqu7xT42QeRBA==", "license": "AGPL-3.0", "dependencies": { "@pm2/agent": "~2.1.1", "@pm2/io": "~6.1.0", "@pm2/js-api": "~0.8.0", "@pm2/pm2-version-check": "latest", + "ansis": "4.0.0", "async": "~3.2.6", "blessed": "0.1.81", - "chalk": "3.0.0", "chokidar": "^3.5.3", "cli-tableau": "^2.0.0", "commander": "2.15.1", @@ -11366,19 +11192,6 @@ "node": ">=8" } }, - "node_modules/pm2/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/pm2/node_modules/commander": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", @@ -12255,9 +12068,9 @@ } }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -13454,9 +13267,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.25.11", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.25.11.tgz", - "integrity": "sha512-jI01fn/t47rrLTQB0FTlMCC+5dYx8o0RRF+R4BPiUNsvg5OdY0s9DKMFmJGrx5SwMZQ4cag0Gl6v8oycso9b/g==", + "version": "5.26.1", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.26.1.tgz", + "integrity": "sha512-Nd503zsVvWKBREk5ekpCqONR6EVeualuZNm1ZS2BBCX/f/AUsOmsF32UVHUj8CUghWQle+6MdelIxRENGDvGhA==", "license": "MIT", "os": [ "darwin", @@ -13900,9 +13713,9 @@ } }, "node_modules/undici": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.8.0.tgz", - "integrity": "sha512-vFv1GA99b7eKO1HG/4RPu2Is3FBTWBrmzqzO0mz+rLxN3yXkE4mqRcb8g8fHxzX4blEysrNZLqg5RbJLqX5buA==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.10.0.tgz", + "integrity": "sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -13915,9 +13728,9 @@ "license": "MIT" }, "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "dev": true, "license": "MIT", "engines": { @@ -14452,16 +14265,16 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" } }, "node_modules/yargs": { @@ -14547,24 +14360,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "3.24.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", - "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.24.5", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", - "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.24.1" - } } } } diff --git a/package.json b/package.json index 5096885b3f..5a91f557c9 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "ansis": "^4.0.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", - "eslint": "^9.26.0", + "eslint": "^9.27.0", "express": "^5.1.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -76,25 +76,25 @@ "module-alias": "^2.2.3", "moment": "^2.30.1", "node-ical": "^0.20.1", - "pm2": "^6.0.5", + "pm2": "^6.0.6", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.25.11", - "undici": "^7.8.0" + "systeminformation": "^5.26.1", + "undici": "^7.10.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", - "cspell": "^9.0.1", - "eslint-plugin-import-x": "^4.11.1", + "cspell": "^9.0.2", + "eslint-plugin-import-x": "^4.12.2", "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.11", + "eslint-plugin-jsdoc": "^50.6.17", "eslint-plugin-package-json": "^0.31.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^26.1.0", - "lint-staged": "^15.5.2", - "markdownlint-cli2": "^0.17.2", + "lint-staged": "^16.0.0", + "markdownlint-cli2": "^0.18.1", "playwright": "^1.52.0", "prettier": "^3.5.3", "sinon": "^20.0.0", @@ -103,7 +103,7 @@ "stylelint-prettier": "^5.0.3" }, "optionalDependencies": { - "electron": "^35.3.0" + "electron": "^36.3.0" }, "engines": { "node": ">=22.14.0" From 4e3821c2ff59e8e5406c91054a4efb2f4995c800 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 23 May 2025 19:34:43 +0200 Subject: [PATCH 224/418] [workflow] Replace Node.js version v23 with v24 (#3770) node v24 was released today and v23 will have reached EOL with our next release. --- .github/workflows/automated-tests.yaml | 2 +- .github/workflows/electron-rebuild.yaml | 2 +- CHANGELOG.md | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 2f0541b41e..1c23a276b8 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -38,7 +38,7 @@ jobs: timeout-minutes: 30 strategy: matrix: - node-version: [22.14.0, 22.x, 23.x] + node-version: [22.14.0, 22.x, 24.x] steps: - name: Install electron dependencies and labwc run: | diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index 52c593425c..b34a7553ca 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [22.14.0, 22.x, 23.x] + node-version: [22.14.0, 22.x, 24.x] steps: - name: Checkout code uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 281cdee57c..2c49c1a695 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ planned for 2025-07-01 - Refactor ESLint config to use `defineConfig` and `globalIgnores` - Replace `eslint-plugin-import` with `eslint-plugin-import-x` - Switch Stylelint config to flat format and simplify Stylelint scripts +- [workflow] Replace Node.js version v23 with v24 (#3770) ### Fixed From 85b4ece767dcf0567f36cb220696440c58b5762a Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 23 May 2025 23:57:50 +0200 Subject: [PATCH 225/418] [refactor] Replace deprecated constants (#3789) `fs.F_OK` and `fs.R_OK` are [deprecated since a while node 20.8.0](https://nodejs.org/api/deprecations.html#DEP0176). Node 24 now complains about them when running server mode (`node --run server`): ```bash [2025-05-23 23:11:44.932] [ERROR] (node:37733) [DEP0176] DeprecationWarning: fs.F_OK is deprecated, use fs.constants.F_OK instead (Use `node --trace-deprecation ...` to show where the warning was created) ``` The replacements have been in place for a while, and this change should work without any issues. --- CHANGELOG.md | 5 +++-- js/app.js | 8 ++++---- js/check_config.js | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c49c1a695..637f220143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,17 +30,18 @@ planned for 2025-07-01 - Replace `eslint-plugin-import` with `eslint-plugin-import-x` - Switch Stylelint config to flat format and simplify Stylelint scripts - [workflow] Replace Node.js version v23 with v24 (#3770) +- [refactor] Replace deprecated constants `fs.F_OK` and `fs.R_OK` (#3789) ### Fixed - [fix] Handle spellcheck issues (#3783) - [calendar] fix fullday event rrule until with timezone offset (#3781) - [feat] Add rule `no-undef` in config file validation to fix #3785 (#3786) -- [fonts] Fix `roboto.css` to avoid error message `Unknown descriptor 'var(' in @font-face rule.` in firefox console +- [fonts] Fix `roboto.css` to avoid error message `Unknown descriptor 'var(' in @font-face rule.` in firefox console (#3787) ### Updated -- [core] Update dependencies incl. electron to v36 (#3774) +- [core] Update dependencies incl. electron to v36 (#3774, #3788) ## [2.31.0] - 2025-04-01 diff --git a/js/app.js b/js/app.js index 20bc856cf3..00d714de0b 100644 --- a/js/app.js +++ b/js/app.js @@ -77,7 +77,7 @@ function App () { // check if templateFile exists try { - fs.accessSync(templateFile, fs.F_OK); + fs.accessSync(templateFile, fs.constants.F_OK); } catch (err) { templateFile = null; Log.log("config template file not exists, no envsubst"); @@ -126,7 +126,7 @@ function App () { require(`${global.root_path}/js/check_config.js`); try { - fs.accessSync(configFilename, fs.F_OK); + fs.accessSync(configFilename, fs.constants.F_OK); const c = require(configFilename); if (Object.keys(c).length === 0) { Log.error("WARNING! Config file appears empty, maybe missing module.exports last line?"); @@ -198,7 +198,7 @@ function App () { const moduleFile = `${moduleFolder}/${moduleName}.js`; try { - fs.accessSync(moduleFile, fs.R_OK); + fs.accessSync(moduleFile, fs.constants.R_OK); } catch (e) { Log.warn(`No ${moduleFile} found for module: ${moduleName}.`); } @@ -207,7 +207,7 @@ function App () { let loadHelper = true; try { - fs.accessSync(helperPath, fs.R_OK); + fs.accessSync(helperPath, fs.constants.R_OK); } catch (e) { loadHelper = false; Log.log(`No helper found for module: ${moduleName}.`); diff --git a/js/check_config.js b/js/check_config.js index b7912ced1e..109deb9384 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -35,7 +35,7 @@ function checkConfigFile () { // Check permission try { - fs.accessSync(configFileName, fs.F_OK); + fs.accessSync(configFileName, fs.constants.F_OK); } catch (error) { throw new Error(`${error}\nNo permission to access config file!`); } From e26aed927d921c844800c4af16ee501b6ae13bd8 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 27 May 2025 22:36:02 +0200 Subject: [PATCH 226/418] [refactor] Replace `ansis` with built-in function `util.styleText` (#3793) > What does the pull request accomplish? One external dependency less. --- CHANGELOG.md | 1 + js/check_config.js | 6 +++--- js/logger.js | 16 ++++++++-------- package-lock.json | 1 - package.json | 1 - 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 637f220143..ab7bb02c5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ planned for 2025-07-01 - Switch Stylelint config to flat format and simplify Stylelint scripts - [workflow] Replace Node.js version v23 with v24 (#3770) - [refactor] Replace deprecated constants `fs.F_OK` and `fs.R_OK` (#3789) +- [refactor] Replace `ansis` with built-in function `util.styleText` ### Fixed diff --git a/js/check_config.js b/js/check_config.js index 109deb9384..628c37475e 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -1,7 +1,7 @@ const path = require("node:path"); const fs = require("node:fs"); +const { styleText } = require("node:util"); const Ajv = require("ajv"); -const colors = require("ansis"); const globals = require("globals"); const { Linter } = require("eslint"); @@ -61,7 +61,7 @@ function checkConfigFile () { ); if (errors.length === 0) { - Log.info(colors.green("Your configuration file doesn't contain syntax errors :)")); + Log.info(styleText("green", "Your configuration file doesn't contain syntax errors :)")); validateModulePositions(configFileName); } else { let errorMessage = "Your configuration file contains syntax errors :("; @@ -112,7 +112,7 @@ function validateModulePositions (configFileName) { const valid = validate(data); if (valid) { - Log.info(colors.green("Your modules structure configuration doesn't contain errors :)")); + Log.info(styleText("green", "Your modules structure configuration doesn't contain errors :)")); } else { const module = validate.errors[0].instancePath.split("/")[2]; const position = validate.errors[0].instancePath.split("/")[3]; diff --git a/js/logger.js b/js/logger.js index 0c254082c4..1870987129 100644 --- a/js/logger.js +++ b/js/logger.js @@ -2,7 +2,7 @@ (function (root, factory) { if (typeof exports === "object") { if (process.env.JEST_WORKER_ID === undefined) { - const colors = require("ansis"); + const { styleText } = require("node:util"); // add timestamps in front of log messages require("console-stamp")(console, { @@ -12,13 +12,13 @@ const { method, defaultTokens } = arg; let label = defaultTokens.label(arg); if (method === "error") { - label = colors.red(label); + label = styleText("red", label); } else if (method === "warn") { - label = colors.yellow(label); + label = styleText("yellow", label); } else if (method === "debug") { - label = colors.bgBlue(label); + label = styleText("bgBlue", label); } else if (method === "info") { - label = colors.blue(label); + label = styleText("blue", label); } return label; }, @@ -26,11 +26,11 @@ const { method, defaultTokens } = arg; let msg = defaultTokens.msg(arg); if (method === "error") { - msg = colors.red(msg); + msg = styleText("red", msg); } else if (method === "warn") { - msg = colors.yellow(msg); + msg = styleText("yellow", msg); } else if (method === "info") { - msg = colors.blue(msg); + msg = styleText("blue", msg); } return msg; } diff --git a/package-lock.json b/package-lock.json index bb93cf60ae..87ea69a011 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "license": "MIT", "dependencies": { "ajv": "^8.17.1", - "ansis": "^4.0.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^9.27.0", diff --git a/package.json b/package.json index 5a91f557c9..60c70397a7 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ }, "dependencies": { "ajv": "^8.17.1", - "ansis": "^4.0.0", "console-stamp": "^3.1.2", "envsub": "^4.1.0", "eslint": "^9.27.0", From c8625ff50692a01ada61dc8e0fba574a8743583f Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 1 Jun 2025 17:03:11 +0200 Subject: [PATCH 227/418] simplify install and maintaining dependencies (#3795) I was always unhappy when maintaining dependency updates to have 3 `package.json` files. This PR moves all deps into the main `package.json` and removes the folders `fonts` and `vendor`. If accepted I will update the docs too. --------- Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> --- .github/dependabot.yaml | 20 --- .gitignore | 4 +- CHANGELOG.md | 3 +- cspell.config.json | 2 +- {vendor/css => css}/font-awesome.css | 0 {fonts => css}/roboto.css | 224 +++++++++++++-------------- fonts/package-lock.json | 35 ----- fonts/package.json | 17 -- index.html | 8 +- js/loader.js | 2 +- js/server.js | 12 +- {vendor => js}/vendor.js | 0 package-lock.json | 113 +++++++++++++- package.json | 17 +- tests/e2e/fonts_spec.js | 2 +- tests/e2e/vendor_spec.js | 12 +- vendor/package-lock.json | 125 --------------- vendor/package.json | 23 --- 18 files changed, 252 insertions(+), 367 deletions(-) rename {vendor/css => css}/font-awesome.css (100%) rename {fonts => css}/roboto.css (57%) delete mode 100644 fonts/package-lock.json delete mode 100644 fonts/package.json rename {vendor => js}/vendor.js (100%) delete mode 100644 vendor/package-lock.json delete mode 100644 vendor/package.json diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 4f7b4405cb..5e3e863077 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -18,23 +18,3 @@ updates: - "Skip Changelog" - "dependencies" - "javascript" - - - package-ecosystem: "npm" - directory: "/vendor" - schedule: - interval: "monthly" - target-branch: "develop" - labels: - - "Skip Changelog" - - "dependencies" - - "javascript" - - - package-ecosystem: "npm" - directory: "/fonts" - schedule: - interval: "monthly" - target-branch: "develop" - labels: - - "Skip Changelog" - - "dependencies" - - "javascript" diff --git a/.gitignore b/.gitignore index 31c9a0bf75..d279c822a1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,8 +10,6 @@ coverage .lock-wscript build/Release /node_modules/**/* -fonts/node_modules/**/* -vendor/node_modules/**/* !/tests/node_modules/**/* jspm_modules .npm @@ -67,6 +65,8 @@ Temporary Items /css/* !/css/custom.css.sample !/css/main.css +!/css/roboto.css +!/css/font-awesome.css # Ignore users config file but keep the sample. /config/* diff --git a/CHANGELOG.md b/CHANGELOG.md index ab7bb02c5c..c81b67c840 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,8 @@ planned for 2025-07-01 - Switch Stylelint config to flat format and simplify Stylelint scripts - [workflow] Replace Node.js version v23 with v24 (#3770) - [refactor] Replace deprecated constants `fs.F_OK` and `fs.R_OK` (#3789) -- [refactor] Replace `ansis` with built-in function `util.styleText` +- [refactor] Replace `ansis` with built-in function `util.styleText` (#3793) +- [core] Integrate stuff from `vendor` and `fonts` folders into main `package.json`, simplifies install and maintaining dependencies (#3795) ### Fixed diff --git a/cspell.config.json b/cspell.config.json index 337a7ee890..e681059f84 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -244,6 +244,6 @@ "Ybbet", "yearmatchgroup" ], - "ignorePaths": ["node_modules/**", "modules/**", "vendor/node_modules/**", "translations/**", "tests/mocks/**", "tests/e2e/modules/clock_es_spec.js", "fonts/roboto.css"], + "ignorePaths": ["node_modules/**", "modules/**", "translations/**", "tests/mocks/**", "tests/e2e/modules/clock_es_spec.js", "css/roboto.css"], "dictionaries": ["node"] } diff --git a/vendor/css/font-awesome.css b/css/font-awesome.css similarity index 100% rename from vendor/css/font-awesome.css rename to css/font-awesome.css diff --git a/fonts/roboto.css b/css/roboto.css similarity index 57% rename from fonts/roboto.css rename to css/roboto.css index 3743e4a872..4f214a050e 100644 --- a/fonts/roboto.css +++ b/css/roboto.css @@ -5,8 +5,8 @@ font-display: swap; font-weight: 100; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-100-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-100-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-100-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-100-normal.woff") format("woff"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -17,8 +17,8 @@ font-display: swap; font-weight: 100; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-100-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-100-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-100-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-100-normal.woff") format("woff"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -29,8 +29,8 @@ font-display: swap; font-weight: 100; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-100-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-100-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-100-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-100-normal.woff") format("woff"); unicode-range: U+1F00-1FFF; } @@ -41,8 +41,8 @@ font-display: swap; font-weight: 100; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-100-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-100-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-100-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-100-normal.woff") format("woff"); unicode-range: U+0370-03FF; } @@ -53,8 +53,8 @@ font-display: swap; font-weight: 100; src: - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-100-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-100-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-100-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-100-normal.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @@ -65,8 +65,8 @@ font-display: swap; font-weight: 100; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-100-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-100-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-100-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-100-normal.woff") format("woff"); unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -77,8 +77,8 @@ font-display: swap; font-weight: 100; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -89,8 +89,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-300-normal.woff") format("woff"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -101,8 +101,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-300-normal.woff") format("woff"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -113,8 +113,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-300-normal.woff") format("woff"); unicode-range: U+1F00-1FFF; } @@ -125,8 +125,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-300-normal.woff") format("woff"); unicode-range: U+0370-03FF; } @@ -137,8 +137,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-300-normal.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @@ -149,8 +149,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-300-normal.woff") format("woff"); unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -161,8 +161,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -173,8 +173,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-400-normal.woff") format("woff"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -185,8 +185,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-400-normal.woff") format("woff"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -197,8 +197,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-400-normal.woff") format("woff"); unicode-range: U+1F00-1FFF; } @@ -209,8 +209,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-400-normal.woff") format("woff"); unicode-range: U+0370-03FF; } @@ -221,8 +221,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-400-normal.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @@ -233,8 +233,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-400-normal.woff") format("woff"); unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -245,8 +245,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -257,8 +257,8 @@ font-display: swap; font-weight: 500; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-500-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-500-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-500-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-500-normal.woff") format("woff"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -269,8 +269,8 @@ font-display: swap; font-weight: 500; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-500-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-500-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-500-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-500-normal.woff") format("woff"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -281,8 +281,8 @@ font-display: swap; font-weight: 500; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-500-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-500-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-500-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-500-normal.woff") format("woff"); unicode-range: U+1F00-1FFF; } @@ -293,8 +293,8 @@ font-display: swap; font-weight: 500; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-500-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-500-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-500-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-500-normal.woff") format("woff"); unicode-range: U+0370-03FF; } @@ -305,8 +305,8 @@ font-display: swap; font-weight: 500; src: - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-500-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-500-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-500-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-500-normal.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @@ -317,8 +317,8 @@ font-display: swap; font-weight: 500; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-500-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-500-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-500-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-500-normal.woff") format("woff"); unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -329,8 +329,8 @@ font-display: swap; font-weight: 500; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -341,8 +341,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-ext-700-normal.woff") format("woff"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -353,8 +353,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-cyrillic-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-cyrillic-700-normal.woff") format("woff"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -365,8 +365,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-ext-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-ext-700-normal.woff") format("woff"); unicode-range: U+1F00-1FFF; } @@ -377,8 +377,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto/files/roboto-greek-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-greek-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-greek-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-greek-700-normal.woff") format("woff"); unicode-range: U+0370-03FF; } @@ -389,8 +389,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-vietnamese-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-vietnamese-700-normal.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @@ -401,8 +401,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-ext-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-ext-700-normal.woff") format("woff"); unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -413,8 +413,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -425,8 +425,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-300-normal.woff") format("woff"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -437,8 +437,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-300-normal.woff") format("woff"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -449,8 +449,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-300-normal.woff") format("woff"); unicode-range: U+1F00-1FFF; } @@ -461,8 +461,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-300-normal.woff") format("woff"); unicode-range: U+0370-03FF; } @@ -473,8 +473,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-300-normal.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @@ -485,8 +485,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-300-normal.woff") format("woff"); unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -497,8 +497,8 @@ font-display: swap; font-weight: 300; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -509,8 +509,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-400-normal.woff") format("woff"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -521,8 +521,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-400-normal.woff") format("woff"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -533,8 +533,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-400-normal.woff") format("woff"); unicode-range: U+1F00-1FFF; } @@ -545,8 +545,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-400-normal.woff") format("woff"); unicode-range: U+0370-03FF; } @@ -557,8 +557,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-400-normal.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @@ -569,8 +569,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-400-normal.woff") format("woff"); unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -581,8 +581,8 @@ font-display: swap; font-weight: 400; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -593,8 +593,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-ext-700-normal.woff") format("woff"); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -605,8 +605,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-cyrillic-700-normal.woff") format("woff"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -617,8 +617,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-ext-700-normal.woff") format("woff"); unicode-range: U+1F00-1FFF; } @@ -629,8 +629,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-greek-700-normal.woff") format("woff"); unicode-range: U+0370-03FF; } @@ -641,8 +641,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-vietnamese-700-normal.woff") format("woff"); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; } @@ -653,8 +653,8 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-ext-700-normal.woff") format("woff"); unicode-range: U+0100-02AF, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -665,7 +665,7 @@ font-display: swap; font-weight: 700; src: - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff2") format("woff2"), - url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff") format("woff"); + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff2") format("woff2"), + url("../node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff") format("woff"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } diff --git a/fonts/package-lock.json b/fonts/package-lock.json deleted file mode 100644 index 0e5c7452a0..0000000000 --- a/fonts/package-lock.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "magicmirror-fonts", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "magicmirror-fonts", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@fontsource/roboto": "^5.2.5", - "@fontsource/roboto-condensed": "^5.2.5" - } - }, - "node_modules/@fontsource/roboto": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.5.tgz", - "integrity": "sha512-70r2UZ0raqLn5W+sPeKhqlf8wGvUXFWlofaDlcbt/S3d06+17gXKr3VNqDODB0I1ASme3dGT5OJj9NABt7OTZQ==", - "license": "OFL-1.1", - "funding": { - "url": "https://github.com/sponsors/ayuhito" - } - }, - "node_modules/@fontsource/roboto-condensed": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.2.5.tgz", - "integrity": "sha512-FVubmVJpZ2js2+nCBEA3IOHhAgWmZ2/YKvTae0X25jlxbd85umOOvUIY6FL6OMpUvIgvwOImS9l0GJjzEPk+mg==", - "license": "OFL-1.1", - "funding": { - "url": "https://github.com/sponsors/ayuhito" - } - } - } -} diff --git a/fonts/package.json b/fonts/package.json deleted file mode 100644 index 62d73e1546..0000000000 --- a/fonts/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "magicmirror-fonts", - "version": "1.0.0", - "description": "Package for fonts use by MagicMirror² core.", - "bugs": { - "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/MagicMirrorOrg/MagicMirror" - }, - "license": "MIT", - "dependencies": { - "@fontsource/roboto": "^5.2.5", - "@fontsource/roboto-condensed": "^5.2.5" - } -} diff --git a/index.html b/index.html index df64a08203..de29247dab 100644 --- a/index.html +++ b/index.html @@ -12,8 +12,8 @@ - - + + - + - + diff --git a/js/loader.js b/js/loader.js index 2380b02ea9..d43dcb7221 100644 --- a/js/loader.js +++ b/js/loader.js @@ -260,7 +260,7 @@ const Loader = (function () { // This file is available in the vendor folder. // Load it from this vendor folder. loadedFiles.push(fileName.toLowerCase()); - return loadFile(`vendor/${vendor[fileName]}`); + return loadFile(`${vendor[fileName]}`); } // File not loaded yet. diff --git a/js/server.js b/js/server.js index dd8b7b2e98..a15c811d23 100644 --- a/js/server.js +++ b/js/server.js @@ -6,10 +6,11 @@ const express = require("express"); const ipfilter = require("express-ipfilter").IpFilter; const helmet = require("helmet"); const socketio = require("socket.io"); - const Log = require("logger"); const { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars } = require("./server_functions"); +const vendor = require(`${__dirname}/vendor`); + /** * Server * @param {object} config The MM config @@ -72,8 +73,13 @@ function Server (config) { app.use(helmet(config.httpHeaders)); app.use("/js", express.static(__dirname)); - let directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations", "/tests/configs", "/tests/mocks"]; - for (const directory of directories) { + let directories = ["/config", "/css", "/modules", "/node_modules/animate.css", "/node_modules/@fontsource", "/node_modules/@fortawesome", "/translations", "/tests/configs", "/tests/mocks"]; + for (const [key, value] of Object.entries(vendor)) { + const dirArr = value.split("/"); + if (dirArr[0] === "node_modules") directories.push(`/${dirArr[0]}/${dirArr[1]}`); + } + const uniqDirs = [...new Set(directories)]; + for (const directory of uniqDirs) { app.use(directory, express.static(path.resolve(global.root_path + directory))); } diff --git a/vendor/vendor.js b/js/vendor.js similarity index 100% rename from vendor/vendor.js rename to js/vendor.js diff --git a/package-lock.json b/package-lock.json index 87ea69a011..5f77251dc9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,11 +7,15 @@ "": { "name": "magicmirror", "version": "2.32.0-develop", - "hasInstallScript": true, "license": "MIT", "dependencies": { + "@fontsource/roboto": "^5.2.5", + "@fontsource/roboto-condensed": "^5.2.5", + "@fortawesome/fontawesome-free": "^6.7.2", "ajv": "^8.17.1", + "animate.css": "^4.1.1", "console-stamp": "^3.1.2", + "croner": "^9.0.0", "envsub": "^4.1.0", "eslint": "^9.27.0", "express": "^5.1.0", @@ -22,12 +26,15 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", + "moment-timezone": "^0.5.48", "node-ical": "^0.20.1", + "nunjucks": "^3.2.4", "pm2": "^6.0.6", "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.26.1", - "undici": "^7.10.0" + "undici": "^7.10.0", + "weathericons": "^2.1.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", @@ -1665,6 +1672,33 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@fontsource/roboto": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.5.tgz", + "integrity": "sha512-70r2UZ0raqLn5W+sPeKhqlf8wGvUXFWlofaDlcbt/S3d06+17gXKr3VNqDODB0I1ASme3dGT5OJj9NABt7OTZQ==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, + "node_modules/@fontsource/roboto-condensed": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.2.5.tgz", + "integrity": "sha512-FVubmVJpZ2js2+nCBEA3IOHhAgWmZ2/YKvTae0X25jlxbd85umOOvUIY6FL6OMpUvIgvwOImS9l0GJjzEPk+mg==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz", + "integrity": "sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==", + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", + "engines": { + "node": ">=6" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -3227,6 +3261,12 @@ "win32" ] }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "license": "MIT" + }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -3301,6 +3341,12 @@ "amp": "0.3.1" } }, + "node_modules/animate.css": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==", + "license": "MIT" + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -3455,6 +3501,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -4591,10 +4643,13 @@ } }, "node_modules/croner": { - "version": "4.1.97", - "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", - "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==", - "license": "MIT" + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/croner/-/croner-9.0.0.tgz", + "integrity": "sha512-onMB0OkDjkXunhdW9htFjEhqrD54+M94i6ackoUkjHKbRnXdyEyKRelp4nJ1kAz32+s27jP1FsebpJCVl0BsvA==", + "license": "MIT", + "engines": { + "node": ">=18.0" + } }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -10474,6 +10529,40 @@ "node": ">=8" } }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/nwsapi": { "version": "2.2.20", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz", @@ -11197,6 +11286,12 @@ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "license": "MIT" }, + "node_modules/pm2/node_modules/croner": { + "version": "4.1.97", + "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==", + "license": "MIT" + }, "node_modules/pm2/node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -13952,6 +14047,12 @@ "makeerror": "1.0.12" } }, + "node_modules/weathericons": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/weathericons/-/weathericons-2.1.0.tgz", + "integrity": "sha512-V45viuyuQQOuoePTqzxvP/wBpYALWkD695fkFvqpn+BiMyo64fFlyDbP2A8umZyFyz1cXFPNw1pWqeaSaQqJlQ==", + "license": "MIT" + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", diff --git a/package.json b/package.json index 60c70397a7..e2839b00ce 100644 --- a/package.json +++ b/package.json @@ -25,15 +25,12 @@ "main": "js/electron.js", "scripts": { "config:check": "node js/check_config.js", - "install-fonts": "echo \"Installing fonts ...\n\" && cd fonts && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", "install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev", "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier", - "install-vendor": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error --no-audit --no-fund --no-update-notifier", - "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --fix", + "lint:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'modules/default/**/*.css' --fix", "lint:js": "eslint --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", - "postinstall": "node --run install-vendor && node --run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"", "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.", "server": "node ./serveronly", "start": "node --run start:x11", @@ -47,7 +44,7 @@ "test": "NODE_ENV=test jest -i --forceExit", "test:calendar": "node ./modules/default/calendar/debug.js", "test:coverage": "NODE_ENV=test jest --coverage -i --verbose false --forceExit", - "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css'", + "test:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'modules/default/**/*.css'", "test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit", "test:electron": "NODE_ENV=test jest --selectProjects electron -i --forceExit", "test:js": "eslint", @@ -62,8 +59,13 @@ "*.css": "stylelint --fix" }, "dependencies": { + "@fontsource/roboto": "^5.2.5", + "@fontsource/roboto-condensed": "^5.2.5", + "@fortawesome/fontawesome-free": "^6.7.2", "ajv": "^8.17.1", + "animate.css": "^4.1.1", "console-stamp": "^3.1.2", + "croner": "^9.0.0", "envsub": "^4.1.0", "eslint": "^9.27.0", "express": "^5.1.0", @@ -74,12 +76,15 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", + "moment-timezone": "^0.5.48", "node-ical": "^0.20.1", + "nunjucks": "^3.2.4", "pm2": "^6.0.6", "socket.io": "^4.8.1", "suncalc": "^1.9.0", "systeminformation": "^5.26.1", - "undici": "^7.10.0" + "undici": "^7.10.0", + "weathericons": "^2.1.0" }, "devDependencies": { "@stylistic/eslint-plugin": "^4.2.0", diff --git a/tests/e2e/fonts_spec.js b/tests/e2e/fonts_spec.js index 80e3e34081..e09f745a4f 100644 --- a/tests/e2e/fonts_spec.js +++ b/tests/e2e/fonts_spec.js @@ -3,7 +3,7 @@ const helpers = require("./helpers/global-setup"); describe("All font files from roboto.css should be downloadable", () => { const fontFiles = []; // Statements below filters out all 'url' lines in the CSS file - const fileContent = require("node:fs").readFileSync(`${__dirname}/../../fonts/roboto.css`, "utf8"); + const fileContent = require("node:fs").readFileSync(`${__dirname}/../../css/roboto.css`, "utf8"); const regex = /\burl\(['"]([^'"]+)['"]\)/g; let match = regex.exec(fileContent); while (match !== null) { diff --git a/tests/e2e/vendor_spec.js b/tests/e2e/vendor_spec.js index 49d3ab8517..bd4407ed4a 100644 --- a/tests/e2e/vendor_spec.js +++ b/tests/e2e/vendor_spec.js @@ -9,21 +9,13 @@ describe("Vendors", () => { }); describe("Get list vendors", () => { - const vendors = require(`${__dirname}/../../vendor/vendor.js`); + const vendors = require(`${__dirname}/../../js/vendor.js`); Object.keys(vendors).forEach((vendor) => { it(`should return 200 HTTP code for vendor "${vendor}"`, async () => { - const urlVendor = `http://localhost:8080/vendor/${vendors[vendor]}`; - const res = await fetch(urlVendor); - expect(res.status).toBe(200); - }); - }); - - Object.keys(vendors).forEach((vendor) => { - it(`should return 404 HTTP code for vendor https://localhost/"${vendor}"`, async () => { const urlVendor = `http://localhost:8080/${vendors[vendor]}`; const res = await fetch(urlVendor); - expect(res.status).toBe(404); + expect(res.status).toBe(200); }); }); }); diff --git a/vendor/package-lock.json b/vendor/package-lock.json deleted file mode 100644 index 220bc63ae2..0000000000 --- a/vendor/package-lock.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "name": "magicmirror-vendors", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "magicmirror-vendors", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@fortawesome/fontawesome-free": "^6.7.2", - "animate.css": "^4.1.1", - "croner": "^9.0.0", - "moment": "^2.30.1", - "moment-timezone": "^0.5.48", - "nunjucks": "^3.2.4", - "suncalc": "^1.9.0", - "weathericons": "^2.1.0" - } - }, - "node_modules/@fortawesome/fontawesome-free": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz", - "integrity": "sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==", - "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", - "engines": { - "node": ">=6" - } - }, - "node_modules/a-sync-waterfall": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", - "license": "MIT" - }, - "node_modules/animate.css": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", - "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==", - "license": "MIT" - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/croner": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/croner/-/croner-9.0.0.tgz", - "integrity": "sha512-onMB0OkDjkXunhdW9htFjEhqrD54+M94i6ackoUkjHKbRnXdyEyKRelp4nJ1kAz32+s27jP1FsebpJCVl0BsvA==", - "license": "MIT", - "engines": { - "node": ">=18.0" - } - }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.48", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", - "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", - "license": "MIT", - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/nunjucks": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", - "license": "BSD-2-Clause", - "dependencies": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "commander": "^5.1.0" - }, - "bin": { - "nunjucks-precompile": "bin/precompile" - }, - "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "chokidar": "^3.3.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/suncalc": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/suncalc/-/suncalc-1.9.0.tgz", - "integrity": "sha512-vMJ8Byp1uIPoj+wb9c1AdK4jpkSKVAywgHX0lqY7zt6+EWRRC3Z+0Ucfjy/0yxTVO1hwwchZe4uoFNqrIC24+A==" - }, - "node_modules/weathericons": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/weathericons/-/weathericons-2.1.0.tgz", - "integrity": "sha512-V45viuyuQQOuoePTqzxvP/wBpYALWkD695fkFvqpn+BiMyo64fFlyDbP2A8umZyFyz1cXFPNw1pWqeaSaQqJlQ==", - "license": "MIT" - } - } -} diff --git a/vendor/package.json b/vendor/package.json deleted file mode 100644 index 4f5ad3118b..0000000000 --- a/vendor/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "magicmirror-vendors", - "version": "1.0.0", - "description": "Package for vendors use by MagicMirror² core.", - "bugs": { - "url": "https://github.com/MagicMirrorOrg/MagicMirror/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/MagicMirrorOrg/MagicMirror" - }, - "license": "MIT", - "dependencies": { - "@fortawesome/fontawesome-free": "^6.7.2", - "animate.css": "^4.1.1", - "croner": "^9.0.0", - "moment": "^2.30.1", - "moment-timezone": "^0.5.48", - "nunjucks": "^3.2.4", - "suncalc": "^1.9.0", - "weathericons": "^2.1.0" - } -} From 975ee9c97d2c28a078700d30d9689f1f0647a350 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 1 Jun 2025 17:51:31 +0200 Subject: [PATCH 228/418] update dependencies (#3804) and add now required "type" to `package.json` --- CHANGELOG.md | 2 +- package-lock.json | 727 +++++++++++++++++++++++++++------------------- package.json | 23 +- 3 files changed, 435 insertions(+), 317 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c81b67c840..1f9c623af5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,7 +43,7 @@ planned for 2025-07-01 ### Updated -- [core] Update dependencies incl. electron to v36 (#3774, #3788) +- [core] Update dependencies including electron to v36 (#3774, #3788) ## [2.31.0] - 2025-04-01 diff --git a/package-lock.json b/package-lock.json index 5f77251dc9..94d48ef8f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "console-stamp": "^3.1.2", "croner": "^9.0.0", "envsub": "^4.1.0", - "eslint": "^9.27.0", + "eslint": "^9.28.0", "express": "^5.1.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -26,33 +26,33 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "moment-timezone": "^0.5.48", + "moment-timezone": "^0.6.0", "node-ical": "^0.20.1", "nunjucks": "^3.2.4", "pm2": "^6.0.6", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.26.1", + "systeminformation": "^5.27.1", "undici": "^7.10.0", "weathericons": "^2.1.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^4.2.0", + "@stylistic/eslint-plugin": "^4.4.0", "cspell": "^9.0.2", - "eslint-plugin-import-x": "^4.12.2", - "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.17", - "eslint-plugin-package-json": "^0.31.0", + "eslint-plugin-import-x": "^4.15.0", + "eslint-plugin-jest": "^28.12.0", + "eslint-plugin-jsdoc": "^50.7.0", + "eslint-plugin-package-json": "^0.33.1", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^26.1.0", - "lint-staged": "^16.0.0", + "lint-staged": "^16.1.0", "markdownlint-cli2": "^0.18.1", "playwright": "^1.52.0", "prettier": "^3.5.3", "sinon": "^20.0.0", - "stylelint": "^16.19.1", + "stylelint": "^16.20.0", "stylelint-config-standard": "^38.0.0", "stylelint-prettier": "^5.0.3" }, @@ -60,7 +60,7 @@ "node": ">=22.14.0" }, "optionalDependencies": { - "electron": "^36.3.0" + "electron": "^36.3.2" } }, "node_modules/@altano/repository-tools": { @@ -121,9 +121,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", - "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz", + "integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==", "dev": true, "license": "MIT", "engines": { @@ -131,22 +131,22 @@ } }, "node_modules/@babel/core": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", - "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", + "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helpers": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.4", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.4", + "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -172,14 +172,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", - "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", + "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.1", - "@babel/types": "^7.27.1", + "@babel/parser": "^7.27.3", + "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -230,15 +230,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", - "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -288,27 +288,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", - "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.4.tgz", + "integrity": "sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", - "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.4.tgz", + "integrity": "sha512-BRmLHGwpUqLFR2jzx9orBuX/ABDkj2jLKOXrHDTN2aOKL+jFDDKaRNo9nyYsIl9h/UE/7lMKdDjKQQyxKKDZ7g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.27.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -572,17 +572,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", - "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -601,9 +601,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", + "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", "dev": true, "license": "MIT", "dependencies": { @@ -1230,9 +1230,9 @@ } }, "node_modules/@csstools/css-calc": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.3.tgz", - "integrity": "sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", "dev": true, "funding": [ { @@ -1249,14 +1249,14 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/css-color-parser": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.9.tgz", - "integrity": "sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", + "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", "dev": true, "funding": [ { @@ -1271,20 +1271,20 @@ "license": "MIT", "dependencies": { "@csstools/color-helpers": "^5.0.2", - "@csstools/css-calc": "^2.1.3" + "@csstools/css-calc": "^2.1.4" }, "engines": { "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", "dev": true, "funding": [ { @@ -1301,13 +1301,13 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", "dev": true, "funding": [ { @@ -1325,9 +1325,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", - "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", + "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", "dev": true, "funding": [ { @@ -1344,8 +1344,8 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@csstools/selector-specificity": { @@ -1436,6 +1436,14 @@ "tslib": "^2.4.0" } }, + "node_modules/@emnapi/core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, "node_modules/@emnapi/runtime": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", @@ -1447,6 +1455,14 @@ "tslib": "^2.4.0" } }, + "node_modules/@emnapi/runtime/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, "node_modules/@emnapi/wasi-threads": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", @@ -1458,6 +1474,14 @@ "tslib": "^2.4.0" } }, + "node_modules/@emnapi/wasi-threads/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, "node_modules/@es-joy/jsdoccomment": { "version": "0.50.2", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.50.2.tgz", @@ -1639,9 +1663,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", - "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", + "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2468,12 +2492,6 @@ "node": ">=10" } }, - "node_modules/@pm2/io/node_modules/tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "license": "Apache-2.0" - }, "node_modules/@pm2/io/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -2653,13 +2671,13 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.2.0.tgz", - "integrity": "sha512-8hXezgz7jexGHdo5WN6JBEIPHCSFyyU4vgbxevu4YLVS5vl+sxqAAGyXSzfNDyR6xMNSH5H1x67nsXcYMOHtZA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.4.0.tgz", + "integrity": "sha512-bIh/d9X+OQLCAMdhHtps+frvyjvAM4B1YlSJzcEEhl7wXLIqPar3ngn9DrHhkBOrTA/z9J0bUMtctAspe0dxdQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.23.0", + "@typescript-eslint/utils": "^8.32.1", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "estraverse": "^5.3.0", @@ -2702,6 +2720,14 @@ "tslib": "^2.4.0" } }, + "node_modules/@tybys/wasm-util/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2860,9 +2886,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz", - "integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==", + "version": "22.15.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz", + "integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -2919,15 +2945,34 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz", + "integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.33.0", + "@typescript-eslint/types": "^8.33.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", - "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz", + "integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1" + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2937,10 +2982,27 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz", + "integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/@typescript-eslint/types": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", - "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz", + "integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==", "dev": true, "license": "MIT", "engines": { @@ -2952,14 +3014,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", - "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz", + "integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1", + "@typescript-eslint/project-service": "8.33.0", + "@typescript-eslint/tsconfig-utils": "8.33.0", + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2979,16 +3043,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", - "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz", + "integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.1", - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/typescript-estree": "8.32.1" + "@typescript-eslint/scope-manager": "8.33.0", + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/typescript-estree": "8.33.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3003,13 +3067,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", - "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz", + "integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/types": "8.33.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3021,9 +3085,9 @@ } }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.2.tgz", - "integrity": "sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.8.tgz", + "integrity": "sha512-rsRK8T7yxraNRDmpFLZCWqpea6OlXPNRRCjWMx24O1V86KFol7u2gj9zJCv6zB1oJjtnzWceuqdnCgOipFcJPA==", "cpu": [ "arm64" ], @@ -3035,9 +3099,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.2.tgz", - "integrity": "sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.8.tgz", + "integrity": "sha512-16yEMWa+Olqkk8Kl6Bu0ltT5OgEedkSAsxcz1B3yEctrDYp3EMBu/5PPAGhWVGnwhtf3hNe3y15gfYBAjOv5tQ==", "cpu": [ "x64" ], @@ -3049,9 +3113,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.2.tgz", - "integrity": "sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.8.tgz", + "integrity": "sha512-ST4uqF6FmdZQgv+Q73FU1uHzppeT4mhX3IIEmHlLObrv5Ep50olWRz0iQ4PWovadjHMTAmpuJAGaAuCZYb7UAQ==", "cpu": [ "x64" ], @@ -3063,9 +3127,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.2.tgz", - "integrity": "sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.8.tgz", + "integrity": "sha512-Z/A/4Rm2VWku2g25C3tVb986fY6unx5jaaCFpx1pbAj0OKkyuJ5wcQLHvNbIcJ9qhiYwXfrkB7JNlxrAbg7YFg==", "cpu": [ "arm" ], @@ -3077,9 +3141,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.2.tgz", - "integrity": "sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.8.tgz", + "integrity": "sha512-HN0p7o38qKmDo3bZUiQa6gP7Qhf0sKgJZtRfSHi6JL2Gi4NaUVF0EO1sQ1RHbeQ4VvfjUGMh3QE5dxEh06BgQQ==", "cpu": [ "arm" ], @@ -3091,9 +3155,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.2.tgz", - "integrity": "sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.8.tgz", + "integrity": "sha512-HsoVqDBt9G69AN0KWeDNJW+7i8KFlwxrbbnJffgTGpiZd6Jw+Q95sqkXp8y458KhKduKLmXfVZGnKBTNxAgPjw==", "cpu": [ "arm64" ], @@ -3105,9 +3169,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.2.tgz", - "integrity": "sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.8.tgz", + "integrity": "sha512-VfR2yTDUbUvn+e/Aw22CC9fQg9zdShHAfwWctNBdOk7w9CHWl2OtYlcMvjzMAns8QxoHQoqn3/CEnZ4Ts7hfrA==", "cpu": [ "arm64" ], @@ -3119,9 +3183,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.2.tgz", - "integrity": "sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.8.tgz", + "integrity": "sha512-xUauVQNz4uDgs4UJJiUAwMe3N0PA0wvtImh7V0IFu++UKZJhssXbKHBRR4ecUJpUHCX2bc4Wc8sGsB6P+7BANg==", "cpu": [ "ppc64" ], @@ -3133,9 +3197,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.2.tgz", - "integrity": "sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.8.tgz", + "integrity": "sha512-GqyIB+CuSHGhhc8ph5RrurtNetYJjb6SctSHafqmdGcRuGi6uyTMR8l18hMEhZFsXdFMc/MpInPLvmNV22xn+A==", "cpu": [ "riscv64" ], @@ -3147,9 +3211,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.2.tgz", - "integrity": "sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.8.tgz", + "integrity": "sha512-eEU3rWIFRv60xaAbtsgwHNWRZGD7cqkpCvNtio/f1TjEE3HfKLzPNB24fA9X/8ZXQrGldE65b7UKK3PmO4eWIQ==", "cpu": [ "riscv64" ], @@ -3161,9 +3225,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.2.tgz", - "integrity": "sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.8.tgz", + "integrity": "sha512-GVLI0f4I4TlLqEUoOFvTWedLsJEdvsD0+sxhdvQ5s+N+m2DSynTs8h9jxR0qQbKlpHWpc2Ortz3z48NHRT4l+w==", "cpu": [ "s390x" ], @@ -3175,9 +3239,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.2.tgz", - "integrity": "sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.8.tgz", + "integrity": "sha512-GX1pZ/4ncUreB0Rlp1l7bhKAZ8ZmvDIgXdeb5V2iK0eRRF332+6gRfR/r5LK88xfbtOpsmRHU6mQ4N8ZnwvGEA==", "cpu": [ "x64" ], @@ -3189,9 +3253,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.2.tgz", - "integrity": "sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.8.tgz", + "integrity": "sha512-n1N84MnsvDupzVuYqJGj+2pb9s8BI1A5RgXHvtVFHedGZVBCFjDpQVRlmsFMt6xZiKwDPaqsM16O/1isCUGt7w==", "cpu": [ "x64" ], @@ -3203,9 +3267,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.2.tgz", - "integrity": "sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.8.tgz", + "integrity": "sha512-x94WnaU5g+pCPDVedfnXzoG6lCOF2xFGebNwhtbJCWfceE94Zj8aysSxdxotlrZrxnz5D3ijtyFUYtpz04n39Q==", "cpu": [ "wasm32" ], @@ -3213,16 +3277,16 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.9" + "@napi-rs/wasm-runtime": "^0.2.10" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.2.tgz", - "integrity": "sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.8.tgz", + "integrity": "sha512-vst2u8EJZ5L6jhJ6iLis3w9rg16aYqRxQuBAMYQRVrPMI43693hLP7DuqyOBRKgsQXy9/jgh204k0ViHkqQgdg==", "cpu": [ "arm64" ], @@ -3234,9 +3298,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.2.tgz", - "integrity": "sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.8.tgz", + "integrity": "sha512-yb3LZOLMFqnA+/ShlE1E5bpYPGDsA590VHHJPB+efnyowT776GJXBoh82em6O9WmYBUq57YblGTcMYAFBm72HA==", "cpu": [ "ia32" ], @@ -3248,9 +3312,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.2.tgz", - "integrity": "sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.8.tgz", + "integrity": "sha512-hHKFx+opG5BA3/owMXon8ypwSotBGTdblG6oda/iOu9+OEYnk0cxD2uIcGyGT8jCK578kV+xMrNxqbn8Zjlpgw==", "cpu": [ "x64" ], @@ -3432,13 +3496,13 @@ } }, "node_modules/are-docs-informative": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", - "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.1.0.tgz", + "integrity": "sha512-CplVvB5za1z5Zn528h0EUogt/McTT7lvHZKFtb2NYldodL7G3u2O49Mgws3mP/TrKhpNuDjKPHYxmh8t2DGTtQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/argparse": { @@ -3519,6 +3583,12 @@ "node": ">=4" } }, + "node_modules/ast-types/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -3854,9 +3924,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", - "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "dev": true, "funding": [ { @@ -3874,8 +3944,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001716", - "electron-to-chromium": "^1.5.149", + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -4063,9 +4133,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001718", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", - "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", + "version": "1.0.30001720", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz", + "integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==", "dev": true, "funding": [ { @@ -5347,9 +5417,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "36.3.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-36.3.0.tgz", - "integrity": "sha512-xk5AJtjxfFRAmehcChWSz/duxI+bJiUCIkH2IX2z8K1SyGsWdpqg+NoJ20JRQ6dpSJw89KXH6juESp8nSyBexA==", + "version": "36.3.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-36.3.2.tgz", + "integrity": "sha512-v0/j7n22CL3OYv9BIhq6JJz2+e1HmY9H4bjTk8/WzVT9JwVX/T/21YNdR7xuQ6XDSEo9gP5JnqmjOamE+CUY8Q==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5366,9 +5436,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.156", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.156.tgz", - "integrity": "sha512-QeOqv11TSASsY/3Ft3LUyDqEiEOph5/85srEPFUo9wuGFNTb0/z5fGE/+ZzTrYvSTGoXNkdQLTw3MKRmgyOyGA==", + "version": "1.5.161", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.161.tgz", + "integrity": "sha512-hwtetwfKNZo/UlwHIVBlKZVdy7o8bIZxxKs0Mv/ROPiQQQmDgdm5a+KvKtBsxM8ZjFzTaCeLoodZ8jiBE3o9rA==", "dev": true, "license": "ISC" }, @@ -5624,9 +5694,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.10", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.10.tgz", - "integrity": "sha512-MtUbM072wlJNyeYAe0mhzrD+M6DIJa96CZAOBBrhDbgKnB4MApIKefcyAB1eOdYn8cUNZgvwBvEzdoAYsxgEIw==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.2", @@ -5656,7 +5726,9 @@ "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", + "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", @@ -5671,6 +5743,7 @@ "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -5807,9 +5880,9 @@ } }, "node_modules/eslint": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", - "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", + "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -5818,7 +5891,7 @@ "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.27.0", + "@eslint/js": "9.28.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5885,46 +5958,47 @@ } } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/eslint-import-context": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.6.tgz", + "integrity": "sha512-/e2ZNPDLCrU8niIy0pddcvXuoO2YrKjf3NAIX+60mHJBT4yv7mqCqvVdyCW2E720e25e4S/1OSVef4U6efGLFg==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "get-tsconfig": "^4.10.1", + "stable-hash": "^0.0.5" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } } }, "node_modules/eslint-plugin-import-x": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.12.2.tgz", - "integrity": "sha512-0jVUgJQipbs0yUfLe7LwYD6p8rIGqCysWZdyJFgkPzDyJgiKpuCaXlywKUAWgJ6u1nLpfrdt21B60OUkupyBrQ==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.15.0.tgz", + "integrity": "sha512-oqCESQlM8r0iRioPHmDqrblH69u11NuglErCnMIY2FcY0UfCCs7qlEuiuqkYKT0puJSQq+fXpDD0MvMTQsAhoQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.31.0", + "@typescript-eslint/types": "^8.33.0", "comment-parser": "^1.4.1", - "debug": "^4.4.0", - "eslint-import-resolver-node": "^0.3.9", - "get-tsconfig": "^4.10.0", + "debug": "^4.4.1", + "eslint-import-context": "^0.1.6", "is-glob": "^4.0.3", "minimatch": "^9.0.3 || ^10.0.1", - "semver": "^7.7.1", + "semver": "^7.7.2", "stable-hash": "^0.0.5", - "tslib": "^2.8.1", - "unrs-resolver": "^1.7.0" + "unrs-resolver": "^1.7.8" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5933,13 +6007,23 @@ "url": "https://opencollective.com/eslint-plugin-import-x" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "@typescript-eslint/utils": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "eslint-import-resolver-node": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/utils": { + "optional": true + }, + "eslint-import-resolver-node": { + "optional": true + } } }, "node_modules/eslint-plugin-jest": { - "version": "28.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.11.0.tgz", - "integrity": "sha512-QAfipLcNCWLVocVbZW8GimKn5p5iiMcgGbRzz8z/P5q7xw+cNEpYqyzFMtIF/ZgF2HLOyy+dYBut+DoYolvqig==", + "version": "28.12.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.12.0.tgz", + "integrity": "sha512-J6zmDp8WiQ9tyvYXE+3RFy7/+l4hraWLzmsabYXyehkmmDd36qV4VQFc7XzcsD8C1PTNt646MSx25bO1mdd9Yw==", "dev": true, "license": "MIT", "dependencies": { @@ -5963,21 +6047,21 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.17", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.17.tgz", - "integrity": "sha512-hq+VQylhd12l8qjexyriDsejZhqiP33WgMTy2AmaGZ9+MrMWVqPECsM87GPxgHfQn0zw+YTuhqjUfk1f+q67aQ==", + "version": "50.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.7.0.tgz", + "integrity": "sha512-fMeHWVtdxXvLfMmKLXJWObJSt57zBz31RCLZYj3bLSHBqnEsyO50N1OLDi5XP5wh+Gte5van9WTtOnemKAZrSw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.50.1", - "are-docs-informative": "^0.0.2", + "@es-joy/jsdoccomment": "~0.50.2", + "are-docs-informative": "^0.1.0", "comment-parser": "1.4.1", - "debug": "^4.3.6", + "debug": "^4.4.1", "escape-string-regexp": "^4.0.0", - "espree": "^10.1.0", + "espree": "^10.3.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", - "semver": "^7.6.3", + "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "engines": { @@ -5988,9 +6072,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.31.0.tgz", - "integrity": "sha512-4bv/QDcExDUqs9/q89rJndkNV/hA0T5PzvRJX4oLdC5xvYXIZ4zz/RBs7KHj0JLE0BhGwLqHHVCLXQ+Y+IjHPg==", + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.33.1.tgz", + "integrity": "sha512-A2bhU0MMd96VpkaPKgzPTW3zoAPYT2O/G+YfN6r+PamtfRdEA1zl1jDi+i5VkVHL7Y6lMB9lEZ6XbtKZ5yJkOg==", "dev": true, "license": "MIT", "dependencies": { @@ -6497,9 +6581,9 @@ } }, "node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", + "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -7127,9 +7211,9 @@ } }, "node_modules/globby/node_modules/ignore": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", - "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -7979,6 +8063,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -9209,28 +9305,28 @@ } }, "node_modules/lint-staged": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.0.0.tgz", - "integrity": "sha512-sUCprePs6/rbx4vKC60Hez6X10HPkpDJaGcy3D1NdwR7g1RcNkWL8q9mJMreOqmHBTs+1sNFp+wOiX9fr+hoOQ==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.1.0.tgz", + "integrity": "sha512-HkpQh69XHxgCjObjejBT3s2ILwNjFx8M3nw+tJ/ssBauDlIpkx2RpqWSi1fBgkXLSSXnbR3iEq1NkVtpvV+FLQ==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^5.4.1", - "commander": "^13.1.0", - "debug": "^4.4.0", + "commander": "^14.0.0", + "debug": "^4.4.1", "lilconfig": "^3.1.3", "listr2": "^8.3.3", "micromatch": "^4.0.8", - "nano-spawn": "^1.0.0", + "nano-spawn": "^1.0.2", "pidtree": "^0.6.0", "string-argv": "^0.3.2", - "yaml": "^2.7.1" + "yaml": "^2.8.0" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=20.18" + "node": ">=20.17" }, "funding": { "url": "https://opencollective.com/lint-staged" @@ -9249,16 +9345,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/lint-staged/node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/listr2": { "version": "8.3.3", "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", @@ -10329,9 +10415,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.48", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", - "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.0.tgz", + "integrity": "sha512-ldA5lRNm3iJCWZcBCab4pnNL3HSZYXVb/3TYr75/1WCTWYuTqYUb5f/S384pncYjJ88lbO8Z4uPDvmoluHJc8Q==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -10480,6 +10566,18 @@ "uuid": "^10.0.0" } }, + "node_modules/node-ical/node_modules/moment-timezone": { + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -11312,9 +11410,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", + "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", "dev": true, "funding": [ { @@ -11332,7 +11430,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -12001,6 +12099,12 @@ "tslib": "^2.4.0" } }, + "node_modules/rrule/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/rrweb-cssom": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", @@ -12831,6 +12935,19 @@ "node": ">= 0.8" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -13031,9 +13148,9 @@ } }, "node_modules/stylelint": { - "version": "16.19.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.19.1.tgz", - "integrity": "sha512-C1SlPZNMKl+d/C867ZdCRthrS+6KuZ3AoGW113RZCOL0M8xOGpgx7G70wq7lFvqvm4dcfdGFVLB/mNaLFChRKw==", + "version": "16.20.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.20.0.tgz", + "integrity": "sha512-B5Myu9WRxrgKuLs3YyUXLP2H0mrbejwNxPmyADlACWwFsrL8Bmor/nTSh4OMae5sHjOz6gkSeccQH34gM4/nAw==", "dev": true, "funding": [ { @@ -13057,15 +13174,15 @@ "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.3", "css-tree": "^3.1.0", - "debug": "^4.3.7", + "debug": "^4.4.1", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.0.8", + "file-entry-cache": "^10.1.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", - "ignore": "^7.0.3", + "ignore": "^7.0.4", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", "known-css-properties": "^0.36.0", @@ -13227,9 +13344,9 @@ } }, "node_modules/stylelint/node_modules/ignore": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", - "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -13361,9 +13478,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.26.1", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.26.1.tgz", - "integrity": "sha512-Nd503zsVvWKBREk5ekpCqONR6EVeualuZNm1ZS2BBCX/f/AUsOmsF32UVHUj8CUghWQle+6MdelIxRENGDvGhA==", + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.1.tgz", + "integrity": "sha512-FgkVpT6GgATtNvADgtEzDxI/SVaBisfnQ4fmgQZhCJ4335noTgt9q6O81ioHwzs9HgnJaaFSdHSEMIkneZ55iA==", "license": "MIT", "os": [ "darwin", @@ -13493,9 +13610,9 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13597,10 +13714,10 @@ } }, "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "license": "Apache-2.0" }, "node_modules/tv4": { "version": "1.3.0", @@ -13854,9 +13971,9 @@ } }, "node_modules/unrs-resolver": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz", - "integrity": "sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.8.tgz", + "integrity": "sha512-2zsXwyOXmCX9nGz4vhtZRYhe30V78heAv+KDc21A/KMdovGHbZcixeD5JHEF0DrFXzdytwuzYclcPbvp8A3Jlw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -13864,26 +13981,26 @@ "napi-postinstall": "^0.2.2" }, "funding": { - "url": "https://github.com/sponsors/JounQin" + "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-darwin-arm64": "1.7.2", - "@unrs/resolver-binding-darwin-x64": "1.7.2", - "@unrs/resolver-binding-freebsd-x64": "1.7.2", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.2", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.2", - "@unrs/resolver-binding-linux-arm64-gnu": "1.7.2", - "@unrs/resolver-binding-linux-arm64-musl": "1.7.2", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.2", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.2", - "@unrs/resolver-binding-linux-riscv64-musl": "1.7.2", - "@unrs/resolver-binding-linux-s390x-gnu": "1.7.2", - "@unrs/resolver-binding-linux-x64-gnu": "1.7.2", - "@unrs/resolver-binding-linux-x64-musl": "1.7.2", - "@unrs/resolver-binding-wasm32-wasi": "1.7.2", - "@unrs/resolver-binding-win32-arm64-msvc": "1.7.2", - "@unrs/resolver-binding-win32-ia32-msvc": "1.7.2", - "@unrs/resolver-binding-win32-x64-msvc": "1.7.2" + "@unrs/resolver-binding-darwin-arm64": "1.7.8", + "@unrs/resolver-binding-darwin-x64": "1.7.8", + "@unrs/resolver-binding-freebsd-x64": "1.7.8", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.8", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.8", + "@unrs/resolver-binding-linux-arm64-gnu": "1.7.8", + "@unrs/resolver-binding-linux-arm64-musl": "1.7.8", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.8", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.8", + "@unrs/resolver-binding-linux-riscv64-musl": "1.7.8", + "@unrs/resolver-binding-linux-s390x-gnu": "1.7.8", + "@unrs/resolver-binding-linux-x64-gnu": "1.7.8", + "@unrs/resolver-binding-linux-x64-musl": "1.7.8", + "@unrs/resolver-binding-wasm32-wasi": "1.7.8", + "@unrs/resolver-binding-win32-arm64-msvc": "1.7.8", + "@unrs/resolver-binding-win32-ia32-msvc": "1.7.8", + "@unrs/resolver-binding-win32-x64-msvc": "1.7.8" } }, "node_modules/update-browserslist-db": { diff --git a/package.json b/package.json index e2839b00ce..4bbe43ac54 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "contributors": [ "https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors" ], + "type": "", "main": "js/electron.js", "scripts": { "config:check": "node js/check_config.js", @@ -67,7 +68,7 @@ "console-stamp": "^3.1.2", "croner": "^9.0.0", "envsub": "^4.1.0", - "eslint": "^9.27.0", + "eslint": "^9.28.0", "express": "^5.1.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", @@ -76,38 +77,38 @@ "iconv-lite": "^0.6.3", "module-alias": "^2.2.3", "moment": "^2.30.1", - "moment-timezone": "^0.5.48", + "moment-timezone": "^0.6.0", "node-ical": "^0.20.1", "nunjucks": "^3.2.4", "pm2": "^6.0.6", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.26.1", + "systeminformation": "^5.27.1", "undici": "^7.10.0", "weathericons": "^2.1.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^4.2.0", + "@stylistic/eslint-plugin": "^4.4.0", "cspell": "^9.0.2", - "eslint-plugin-import-x": "^4.12.2", - "eslint-plugin-jest": "^28.11.0", - "eslint-plugin-jsdoc": "^50.6.17", - "eslint-plugin-package-json": "^0.31.0", + "eslint-plugin-import-x": "^4.15.0", + "eslint-plugin-jest": "^28.12.0", + "eslint-plugin-jsdoc": "^50.7.0", + "eslint-plugin-package-json": "^0.33.1", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jest": "^29.7.0", "jsdom": "^26.1.0", - "lint-staged": "^16.0.0", + "lint-staged": "^16.1.0", "markdownlint-cli2": "^0.18.1", "playwright": "^1.52.0", "prettier": "^3.5.3", "sinon": "^20.0.0", - "stylelint": "^16.19.1", + "stylelint": "^16.20.0", "stylelint-config-standard": "^38.0.0", "stylelint-prettier": "^5.0.3" }, "optionalDependencies": { - "electron": "^36.3.0" + "electron": "^36.3.2" }, "engines": { "node": ">=22.14.0" From 302b24c6477fc7e4d907dc652833f1d684f623b5 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 5 Jun 2025 10:18:12 +0200 Subject: [PATCH 229/418] [l10n] Complete translations (#3794) **Short description**: I completed the translations with the help of translation tools. **Long description**: I'm currently looking at the translation-tests and I noticed the e2e-test `${language} should contain all base keys, ()`. It is supposed to check whether all keys are present in each translation file, but it doesn't actually work that way. When I fix it, a lot of missing translations are reported. I have completed these translations with the help of translation tools and packed them into this PR. I have left out the modified test so that we can focus on the question if we accept such amount of automatic translations or not. rejas has already expressed in another PR (https://github.com/MagicMirrorOrg/MagicMirror/pull/3775#discussion_r2083099252) that he prefers human translators. I basically do too, but I don't see how we can manage to have all translations completed by humans. And even if a few translations are not correct, hopefully a user will get in touch. If we decide against the translations, we should at least remove the test. If we go for the tranlsations, I'll add the test. What do you think? --------- Co-authored-by: Magnus <34011212+MagMar94@users.noreply.github.com> --- CHANGELOG.md | 1 + translations/af.json | 20 +++++++++++++++++++- translations/bg.json | 18 +++++++++++++++++- translations/ca.json | 18 +++++++++++++++++- translations/cs.json | 13 ++++++++++++- translations/cv.json | 16 +++++++++++++++- translations/cy.json | 18 +++++++++++++++++- translations/da.json | 6 +++++- translations/el.json | 2 ++ translations/eo.json | 1 + translations/es.json | 13 ++++++++++++- translations/fi.json | 15 ++++++++++++++- translations/fy.json | 24 +++++++++++++++++++++++- translations/gl.json | 16 +++++++++++++--- translations/gu.json | 16 ++++++++++++++-- translations/he.json | 15 ++++++++++++++- translations/hi.json | 15 +++++++++++++-- translations/hr.json | 16 +++++++++++++++- translations/hu.json | 17 ++++++++++++++++- translations/id.json | 18 +++++++++++++++++- translations/is.json | 19 ++++++++++++++++++- translations/it.json | 16 +++++++++++++++- translations/ja.json | 25 ++++++++++++++++++++++++- translations/ko.json | 11 +++++++++-- translations/lt.json | 15 ++++++++++++++- translations/ms-my.json | 19 ++++++++++++++++++- translations/nb.json | 14 +++++++++++++- translations/nl.json | 6 +++++- translations/nn.json | 17 ++++++++++++++++- translations/pl.json | 15 ++++++++++++++- translations/pt-br.json | 18 ++++++++++++++++-- translations/pt.json | 13 ++++++++++++- translations/ro.json | 16 +++++++++++++++- translations/ru.json | 16 +++++++++++++++- translations/sk.json | 18 +++++++++++++++++- translations/sv.json | 16 +++++++++++++++- translations/th.json | 9 ++++++++- translations/tlh.json | 18 ++++++++++++++++-- translations/tr.json | 15 ++++++++++++++- translations/uk.json | 15 ++++++++++++++- translations/zh-cn.json | 16 +++++++++++++++- translations/zh-tw.json | 6 +++++- 42 files changed, 565 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f9c623af5..a44c8b2e80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ planned for 2025-07-01 - [refactor] Replace deprecated constants `fs.F_OK` and `fs.R_OK` (#3789) - [refactor] Replace `ansis` with built-in function `util.styleText` (#3793) - [core] Integrate stuff from `vendor` and `fonts` folders into main `package.json`, simplifies install and maintaining dependencies (#3795) +- [l10n] Complete translations (with the help of translation tools) (#3794) ### Fixed diff --git a/translations/af.json b/translations/af.json index 7ef2bd558c..8fb6468020 100644 --- a/translations/af.json +++ b/translations/af.json @@ -1,12 +1,14 @@ { "LOADING": "Besig om te laai …", + "DAYBEFOREYESTERDAY": "Eergister", "YESTERDAY": "Gister", "TODAY": "Vandag", "TOMORROW": "Môre", "DAYAFTERTOMORROW": "Oormôre", "RUNNING": "Eindig in", "EMPTY": "Geen komende gebeurtenisse.", + "WEEK": "Week {weekNumber}", "N": "N", "NNE": "NNO", @@ -25,8 +27,24 @@ "NW": "NW", "NNW": "NNW", + "FEELS": "Voel soos {DEGREE}", + "PRECIP_POP": "Neerslag waarskynlikheid", + "PRECIP_AMOUNT": "Neerslag hoeveelheid", + + "MODULE_CONFIG_CHANGED": "Die konfigurasie opsies vir die {MODULE_NAME} module het verander.\nGaan asseblief die dokumentasie na.", + "MODULE_CONFIG_ERROR": "Fout in die {MODULE_NAME} module. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Ongeldige URL.", + "MODULE_ERROR_NO_CONNECTION": "Geen internetverbinding.", + "MODULE_ERROR_UNAUTHORIZED": "Owerheid het misluk.", + "MODULE_ERROR_UNSPECIFIED": "Gaan die logs na vir meer besonderhede.", + + "NEWSFEED_NO_ITEMS": "Geen nuus op die oomblik.", + "UPDATE_NOTIFICATION": "MagicMirror² update beskikbaar.", "UPDATE_NOTIFICATION_MODULE": "Update beskikbaar vir {MODULE_NAME} module.", "UPDATE_INFO_SINGLE": "Die huidige installasie is {COMMIT_COUNT} commit agter op die {BRANCH_NAME} branch.", - "UPDATE_INFO_MULTIPLE": "Die huidige installasie is {COMMIT_COUNT} commits agter op die {BRANCH_NAME} branch." + "UPDATE_INFO_MULTIPLE": "Die huidige installasie is {COMMIT_COUNT} commits agter op die {BRANCH_NAME} branch.", + "UPDATE_NOTIFICATION_DONE": "Update voltooi vir {MODULE_NAME} module.", + "UPDATE_NOTIFICATION_ERROR": "Fout tydens opdatering van {MODULE_NAME} module.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror moet herbegin word." } diff --git a/translations/bg.json b/translations/bg.json index cd0c01a2df..3d742f7a4c 100644 --- a/translations/bg.json +++ b/translations/bg.json @@ -27,8 +27,24 @@ "NW": "СЗ", "NNW": "ССЗ", + "FEELS": "Усеща се като {DEGREE}", + "PRECIP_POP": "Вероятност за валежи", + "PRECIP_AMOUNT": "Количество валежи", + + "MODULE_CONFIG_CHANGED": "Променени са опциите за конфигурация на модула „{MODULE_NAME}“.\nМоля, проверете документацията.", + "MODULE_CONFIG_ERROR": "Грешка в модула „{MODULE_NAME}“. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Неправилен URL адрес.", + "MODULE_ERROR_NO_CONNECTION": "Няма интернет връзка.", + "MODULE_ERROR_UNAUTHORIZED": "Неуспешна авторизация.", + "MODULE_ERROR_UNSPECIFIED": "Проверете логовете за повече подробности.", + + "NEWSFEED_NO_ITEMS": "Няма новини в момента.", + "UPDATE_NOTIFICATION": "Налична е актуализация за MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Налична е актуализация за модула „{MODULE_NAME}“.", "UPDATE_INFO_SINGLE": "Инсталираната версия е с {COMMIT_COUNT} ревизия назад от клона „{BRANCH_NAME}“.", - "UPDATE_INFO_MULTIPLE": "Инсталираната версия е с {COMMIT_COUNT} ревизии назад от клона „{BRANCH_NAME}“." + "UPDATE_INFO_MULTIPLE": "Инсталираната версия е с {COMMIT_COUNT} ревизии назад от клона „{BRANCH_NAME}“.", + "UPDATE_NOTIFICATION_DONE": "Актуализацията на модула „{MODULE_NAME}“ е завършена.", + "UPDATE_NOTIFICATION_ERROR": "Грешка при актуализацията на модула „{MODULE_NAME}“", + "UPDATE_NOTIFICATION_NEED-RESTART": "Необходимо е рестартиране на MagicMirror." } diff --git a/translations/ca.json b/translations/ca.json index 73b8948c29..8be470ad1c 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -26,8 +26,24 @@ "NW": "NO", "NNW": "NNO", + "FEELS": "Sensació tèrmica {DEGREE}", + "PRECIP_POP": "Probabilitat de precipitació", + "PRECIP_AMOUNT": "Quantitat de precipitació", + + "MODULE_CONFIG_CHANGED": "S'ha canviat l'opció de configuració del mòdul {MODULE_NAME}.\nConsulta la documentació.", + "MODULE_CONFIG_ERROR": "S'ha produït un error al mòdul {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "L'URL és mal format.", + "MODULE_ERROR_NO_CONNECTION": "No hi ha connexió a Internet.", + "MODULE_ERROR_UNAUTHORIZED": "L'autorització ha fallat.", + "MODULE_ERROR_UNSPECIFIED": "Consulta els registres per a més detalls.", + + "NEWSFEED_NO_ITEMS": "No hi ha notícies disponibles en aquest moment.", + "UPDATE_NOTIFICATION": "MagicMirror² actualizació disponible.", "UPDATE_NOTIFICATION_MODULE": "Disponible una actualizació per al mòdul {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "La teva instal·lació actual està {COMMIT_COUNT} commit canvis darrere de la branca {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "La teva instal·lació actual està {COMMIT_COUNT} commits canvis darrere de la branca {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "La teva instal·lació actual està {COMMIT_COUNT} commits canvis darrere de la branca {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "S'ha completat l'actualització del mòdul {MODULE_NAME}.", + "UPDATE_NOTIFICATION_ERROR": "S'ha produït un error durant l'actualització del mòdul {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "És necessari reiniciar MagicMirror." } diff --git a/translations/cs.json b/translations/cs.json index 74a0896f0e..2f16ab1b6e 100644 --- a/translations/cs.json +++ b/translations/cs.json @@ -29,11 +29,22 @@ "FEELS": "Pocitově {DEGREE}", "PRECIP_POP": "Pravděpodobnost deště", + "PRECIP_AMOUNT": "Množství deště", + + "MODULE_CONFIG_CHANGED": "Konfigurační možnosti modulu {MODULE_NAME} byly změněny.\nProsím, zkontrolujte dokumentaci.", + "MODULE_CONFIG_ERROR": "Chyba v modulu {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Nesprávná URL adresa.", + "MODULE_ERROR_NO_CONNECTION": "Není připojení k internetu.", + "MODULE_ERROR_UNAUTHORIZED": "Autorizace selhala.", + "MODULE_ERROR_UNSPECIFIED": "Zkontrolujte protokoly pro více informací.", "NEWSFEED_NO_ITEMS": "Žádné zprávy.", "UPDATE_NOTIFICATION": "Dostupná aktualizace pro MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostupná aktualizace pro modul {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Současná instalace je na větvi {BRANCH_NAME} pozadu o {COMMIT_COUNT} commit.", - "UPDATE_INFO_MULTIPLE": "Současná instalace je na větvi {BRANCH_NAME} pozadu o {COMMIT_COUNT} commits." + "UPDATE_INFO_MULTIPLE": "Současná instalace je na větvi {BRANCH_NAME} pozadu o {COMMIT_COUNT} commits.", + "UPDATE_NOTIFICATION_DONE": "Aktualizace dokončena pro modul {MODULE_NAME}.", + "UPDATE_NOTIFICATION_ERROR": "Chyba aktualizace modulu {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Je třeba restartovat MagicMirror." } diff --git a/translations/cv.json b/translations/cv.json index 34fc4fc2b5..1138d766db 100644 --- a/translations/cv.json +++ b/translations/cv.json @@ -27,9 +27,23 @@ "NNW": "ҪҪА", "FEELS": "Туйӑннӑ {DEGREE}", + "PRECIP_POP": "Ҫумӑр ҫума пултарасси", + "PRECIP_AMOUNT": "Ҫумӑр виҫи", + + "MODULE_CONFIG_CHANGED": "{MODULE_NAME} модулӗн конфигураци опциялӗ пур ҫӗнтерӗ.", + "MODULE_CONFIG_ERROR": "{MODULE_NAME} модулӗнде хата. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Ҫӗҫ ҫӗнӗ URL хата.", + "MODULE_ERROR_NO_CONNECTION": "Интернет-пулла хӗҫҫӗн.", + "MODULE_ERROR_UNAUTHORIZED": "Авторизация хата.", + "MODULE_ERROR_UNSPECIFIED": "Тӗп лог ҫӗнтерӗ.", + + "NEWSFEED_NO_ITEMS": "Пулас ҫӗнтер ҫук.", "UPDATE_NOTIFICATION": "MagicMirror² валли ҫӗнетӳ пур.", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} модуль валли ҫӗнетӳ пур.", "UPDATE_INFO_SINGLE": "Ҫак инсталляци {BRANCH_NAME} commit турат {COMMIT_COUNT} коммитпа кая уйрӑлса тӑрать.", - "UPDATE_INFO_MULTIPLE": "Ҫак инсталляци {BRANCH_NAME} commit турат {COMMIT_COUNT} коммитпа кая уйрӑлса тӑрать." + "UPDATE_INFO_MULTIPLE": "Ҫак инсталляци {BRANCH_NAME} commit турат {COMMIT_COUNT} коммитпа кая уйрӑлса тӑрать.", + "UPDATE_NOTIFICATION_DONE": "{MODULE_NAME} модулӗнде валли ҫӗнетӳ пур.", + "UPDATE_NOTIFICATION_ERROR": "{MODULE_NAME} модулӗнде валли ҫӗнетӳ хата.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror перезагрузка тӗрӗҫҫӗн тӑрать." } diff --git a/translations/cy.json b/translations/cy.json index 531d811633..824d909236 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -26,8 +26,24 @@ "NW": "GoGr", "NNW": "GoGoGe", + "FEELS": "Teimlad {DEGREE}", + "PRECIP_POP": "Tebygolrwydd glawiad", + "PRECIP_AMOUNT": "Cyfanswm glawiad", + + "MODULE_CONFIG_CHANGED": "Mae'r dewisiadau ar gyfer y modiwl {MODULE_NAME} wedi newid.\nGwiriwch y ddogfennaeth.", + "MODULE_CONFIG_ERROR": "Gwall yn y modiwl {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL anghywir.", + "MODULE_ERROR_NO_CONNECTION": "Dim cysylltiad rhyngrwyd.", + "MODULE_ERROR_UNAUTHORIZED": "Methiant awdurdodi.", + "MODULE_ERROR_UNSPECIFIED": "Gwiriwch y logiau am ragor o fanylion.", + + "NEWSFEED_NO_ITEMS": "Dim newyddion ar hyn o bryd.", + "UPDATE_NOTIFICATION": "MagicMirror² mwy diweddar yn barod.", "UPDATE_NOTIFICATION_MODULE": "Mae diweddaraiad ar gyfer y modiwl {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Mae'r fersiwn bresenol {COMMIT_COUNT} commit tu ôl i'r gangen {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Mae'r fersiwn bresenol {COMMIT_COUNT} commit tu ôl i'r gangen {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Mae'r fersiwn bresenol {COMMIT_COUNT} commit tu ôl i'r gangen {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "Diweddariad wedi'i gwblhau ar gyfer y modiwl {MODULE_NAME}", + "UPDATE_NOTIFICATION_ERROR": "Gwall diweddariad ar gyfer y modiwl {MODULE_NAME}", + "UPDATE_NOTIFICATION_NEED-RESTART": "Mae angen ailgychwyn MagicMirror." } diff --git a/translations/da.json b/translations/da.json index ed32a142cd..13486bfc30 100644 --- a/translations/da.json +++ b/translations/da.json @@ -29,6 +29,7 @@ "FEELS": "Føles som {DEGREE}", "PRECIP_POP": "Sandsynlighed for nedbør", + "PRECIP_AMOUNT": "Nedbørsmængde", "MODULE_CONFIG_CHANGED": "Konfigurationsmulighederne for {MODULE_NAME} modulet er ændret.\nSe venligst dokumentationen.", "MODULE_CONFIG_ERROR": "Fejl i {MODULE_NAME} modulet. {ERROR}", @@ -42,5 +43,8 @@ "UPDATE_NOTIFICATION": "MagicMirror² opdatering tilgængelig.", "UPDATE_NOTIFICATION_MODULE": "Opdatering tilgængelig for {MODULE_NAME} modulet.", "UPDATE_INFO_SINGLE": "Den nuværende installation er {COMMIT_COUNT} commit bagud på {BRANCH_NAME} branch'en.", - "UPDATE_INFO_MULTIPLE": "Den nuværende installation er {COMMIT_COUNT} commits bagud på {BRANCH_NAME} branch'en." + "UPDATE_INFO_MULTIPLE": "Den nuværende installation er {COMMIT_COUNT} commits bagud på {BRANCH_NAME} branch'en.", + "UPDATE_NOTIFICATION_DONE": "Opdatering færdig for {MODULE_NAME} modulet", + "UPDATE_NOTIFICATION_ERROR": "Opdateringsfejl for {MODULE_NAME} modulet", + "UPDATE_NOTIFICATION_NEED-RESTART": "Genstart af MagicMirror er påkrævet." } diff --git a/translations/el.json b/translations/el.json index dd8d007cdf..2fd12c90e3 100644 --- a/translations/el.json +++ b/translations/el.json @@ -5,8 +5,10 @@ "YESTERDAY": "Χθες", "TODAY": "Σήμερα", "TOMORROW": "Αύριο", + "DAYAFTERTOMORROW": "Μεθαύριο", "RUNNING": "Λήγει σε", "EMPTY": "Δεν υπάρχουν προσεχείς εκδηλώσεις.", + "WEEK": "Εβδομάδα {weekNumber}", "N": "B", "NNE": "BBA", diff --git a/translations/eo.json b/translations/eo.json index d4579b60b6..a5730d8243 100644 --- a/translations/eo.json +++ b/translations/eo.json @@ -9,6 +9,7 @@ "RUNNING": "ankoraŭ", "EMPTY": "Neniu evento.", "WEEK": "{weekNumber}a kalendara semajno", + "WEEK_SHORT": "{weekNumber}a KS", "N": "N", "NNE": "NNOr", diff --git a/translations/es.json b/translations/es.json index 67be6ab952..4106d45d74 100644 --- a/translations/es.json +++ b/translations/es.json @@ -30,11 +30,22 @@ "FEELS": "Sensación térmica de {DEGREE}", "PRECIP_POP": "Precipitación", + "PRECIP_AMOUNT": "Cantidad de precipitación", "MODULE_CONFIG_CHANGED": "Las opciones de configuración para el módulo {MODULE_NAME} han cambiado. \nVerifique la documentación.", + "MODULE_CONFIG_ERROR": "Error en el módulo {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL mal formado.", + "MODULE_ERROR_NO_CONNECTION": "No hay conexión a Internet.", + "MODULE_ERROR_UNAUTHORIZED": "No autorizado.", + "MODULE_ERROR_UNSPECIFIED": "Por favor, consulte los registros para obtener más información.", + + "NEWSFEED_NO_ITEMS": "No hay noticias disponibles en este momento.", "UPDATE_NOTIFICATION": "MagicMirror² actualización disponible.", "UPDATE_NOTIFICATION_MODULE": "Disponible una actualización para el módulo {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Tu actual instalación está {COMMIT_COUNT} commit cambios detrás de la rama {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Tu actual instalación está {COMMIT_COUNT} commits cambios detrás de la rama {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Tu actual instalación está {COMMIT_COUNT} commits cambios detrás de la rama {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "S'ha completat l'actualització del mòdul {MODULE_NAME}.", + "UPDATE_NOTIFICATION_ERROR": "S'ha produït un error durant l'actualització del mòdul {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "És necessari reiniciar MagicMirror." } diff --git a/translations/fi.json b/translations/fi.json index 87c0ef24a8..c29ae33310 100644 --- a/translations/fi.json +++ b/translations/fi.json @@ -29,9 +29,22 @@ "FEELS": "Tuntuu kuin {DEGREE}", "PRECIP_POP": "Sateen todennäköisyys", + "PRECIP_AMOUNT": "Sateen määrä", + + "MODULE_CONFIG_CHANGED": "Moduulin {MODULE_NAME} asetukset on muutettu.\nOle hyvä ja tarkista dokumentaatio.", + "MODULE_CONFIG_ERROR": "Virhe moduulissa {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Virheellinen url.", + "MODULE_ERROR_NO_CONNECTION": "Ei internet-yhteyttä.", + "MODULE_ERROR_UNAUTHORIZED": "Valtuutus epäonnistui.", + "MODULE_ERROR_UNSPECIFIED": "Tarkista lokitiedostot saadaksesi lisätietoja.", + + "NEWSFEED_NO_ITEMS": "Ei uutisia tällä hetkellä.", "UPDATE_NOTIFICATION": "MagicMirror² päivitys saatavilla.", "UPDATE_NOTIFICATION_MODULE": "Päivitys saatavilla moduulille {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Nykyasennus on {COMMIT_COUNT} muutoksen jäljessä {BRANCH_NAME} haaraan nähden.", - "UPDATE_INFO_MULTIPLE": "Nykyasennus on {COMMIT_COUNT} muutosta jäljessä {BRANCH_NAME} haaraan nähden." + "UPDATE_INFO_MULTIPLE": "Nykyasennus on {COMMIT_COUNT} muutosta jäljessä {BRANCH_NAME} haaraan nähden.", + "UPDATE_NOTIFICATION_DONE": "Päivitys moduulille {MODULE_NAME} valmis.", + "UPDATE_NOTIFICATION_ERROR": "Virhe moduulin {MODULE_NAME} päivityksessä.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror tulee käynnistää uudelleen." } diff --git a/translations/fy.json b/translations/fy.json index ba1bc12c75..b261bd1cfd 100644 --- a/translations/fy.json +++ b/translations/fy.json @@ -7,6 +7,7 @@ "DAYAFTERTOMORROW": "Oaremoarn", "RUNNING": "Einigest oer", "EMPTY": "Gjin plande ôfspraken.", + "WEEK": "Wike {weekNumber}", "N": "N", "NNE": "NNE", @@ -23,5 +24,26 @@ "W": "W", "WNW": "WNW", "NW": "NW", - "NNW": "NNW" + "NNW": "NNW", + + "FEELS": "Voelt as {DEGREE}", + "PRECIP_POP": "Kans op rein", + "PRECIP_AMOUNT": "Hoeveelheid rein", + + "MODULE_CONFIG_CHANGED": "De konfiguraasje fan it {MODULE_NAME} module is feroare.\nSjoch de dokumintaasje foar mear ynformaasje.", + "MODULE_CONFIG_ERROR": "Fout yn it {MODULE_NAME} module. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "De URL is net jildich.", + "MODULE_ERROR_NO_CONNECTION": "Gjin ynternetferbining.", + "MODULE_ERROR_UNAUTHORIZED": "Autorisearje mislearre.", + "MODULE_ERROR_UNSPECIFIED": "Sjoch de logs foar mear ynformaasje.", + + "NEWSFEED_NO_ITEMS": "Op it stuit gjin nijsberjochten.", + + "UPDATE_NOTIFICATION": "Der is in update beskikber foar MagicMirror².", + "UPDATE_NOTIFICATION_MODULE": "Der is in update beskikber foar it {MODULE_NAME} module.", + "UPDATE_INFO_SINGLE": "Dizze ynstallaasje is {BRANCH_NAME} commit efter op {COMMIT_COUNT} commits.", + "UPDATE_INFO_MULTIPLE": "Dizze ynstallaasje is {BRANCH_NAME} commits achter op {COMMIT_COUNT} commits.", + "UPDATE_NOTIFICATION_DONE": "It {MODULE_NAME} module is bywurke.", + "UPDATE_NOTIFICATION_ERROR": "Fout by it bywurkje fan it {MODULE_NAME} module.", + "UPDATE_NOTIFICATION_NEED-RESTART": "It is nedich om MagicMirror te herstarten." } diff --git a/translations/gl.json b/translations/gl.json index 1de91d628f..8225a1a4c4 100644 --- a/translations/gl.json +++ b/translations/gl.json @@ -27,14 +27,24 @@ "NW": "NW", "NNW": "NNW", + "FEELS": "Semella como {DEGREE}", + "PRECIP_POP": "Precipitacións", + "PRECIP_AMOUNT": "Cantidade de precipitacións", + "MODULE_CONFIG_CHANGED": "Cambiaron as opcións de configuración para o módulo {MODULE_NAME}.\nPor favor, verifique a documentación.", "MODULE_CONFIG_ERROR": "Hai un erro no módulo {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL mal formado.", + "MODULE_ERROR_NO_CONNECTION": "Non hai conexión a Internet.", + "MODULE_ERROR_UNAUTHORIZED": "A autorización fallou.", + "MODULE_ERROR_UNSPECIFIED": "Verifique os rexistros para obter máis información.", + + "NEWSFEED_NO_ITEMS": "Non hai novas no momento.", "UPDATE_NOTIFICATION": "Actualización dispoñible para MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Actualización dispoñible para o módulo {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "A instalación actual está {COMMIT_COUNT} commits detrás da rama {BRANCH_NAME}.", "UPDATE_INFO_MULTIPLE": "A instalación actual está {COMMIT_COUNT} commits detrás da rama {BRANCH_NAME}.", - - "FEELS": "Semella como {DEGREE}", - "PRECIP_POP": "Precipitacións" + "UPDATE_NOTIFICATION_DONE": "Actualización feita para o módulo {MODULE_NAME}.", + "UPDATE_NOTIFICATION_ERROR": "Erro na actualización do módulo {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "É necesario reiniciar MagicMirror." } diff --git a/translations/gu.json b/translations/gu.json index 015dc3d0bd..7b55ee9078 100644 --- a/translations/gu.json +++ b/translations/gu.json @@ -1,6 +1,7 @@ { "LOADING": "લોડ થઈ રહ્યું છે …", + "DAYBEFOREYESTERDAY": "પરમ ગઇકાલે", "YESTERDAY": "ગઇકાલે", "TODAY": "આજે", "TOMORROW": "આવતી કાલે", @@ -27,12 +28,23 @@ "NNW": "ઉઉપ", "FEELS": "{DEGREE} જેવું લાગશે", - "PRECIP_POP": "PoP", + "PRECIP_POP": "વર્ષા સંભાવના", + "PRECIP_AMOUNT": "વર્ષા માત્રા", "MODULE_CONFIG_CHANGED": "{MODULE_NAME} મોડ્યુલ માટે ગોઠવણી વિકલ્પો બદલાયા છે. \nકૃપા કરીને દસ્તાવેજોને તપાસો.", + "MODULE_CONFIG_ERROR": "{MODULE_NAME} મોડ્યુલમાં ભૂલ છે. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "ખોટી URL.", + "MODULE_ERROR_NO_CONNECTION": "ઇન્ટરનેટ કનેક્શન નથી.", + "MODULE_ERROR_UNAUTHORIZED": "અધિકૃત કરવું નિષ્ફળ.", + "MODULE_ERROR_UNSPECIFIED": "વધુ વિગતો માટે લોગ તપાસો.", + + "NEWSFEED_NO_ITEMS": "હાલમાં કોઈ સમાચાર નથી.", "UPDATE_NOTIFICATION": "MagicMirror² અપડેટ ઉપલબ્ધ છે.", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} મોડ્યુલ માટે અપડેટ ઉપલબ્ધ છે.", "UPDATE_INFO_SINGLE": "વર્તમાન ઇન્સ્ટોલેશન એ {BRANCH_NAME} શાખા ની {COMMIT_COUNT} કમીટ પાછળ છે. ", - "UPDATE_INFO_MULTIPLE": "વર્તમાન ઇન્સ્ટોલેશન એ {BRANCH_NAME} શાખા ની {COMMIT_COUNT} કમીટ પાછળ છે. " + "UPDATE_INFO_MULTIPLE": "વર્તમાન ઇન્સ્ટોલેશન એ {BRANCH_NAME} શાખા ની {COMMIT_COUNT} કમીટ પાછળ છે. ", + "UPDATE_NOTIFICATION_DONE": "{MODULE_NAME} મોડ્યુલ માટે અપડેટ પૂર્ણ થયું.", + "UPDATE_NOTIFICATION_ERROR": "{MODULE_NAME} મોડ્યુલ માટે અપડેટમાં ભૂલ આવી.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror ને ફરી શરૂ કરવાની જરૂર છે." } diff --git a/translations/he.json b/translations/he.json index 1661c9cc3f..6acd490f4a 100644 --- a/translations/he.json +++ b/translations/he.json @@ -29,9 +29,22 @@ "FEELS": "מרגיש כמו {DEGREE}", "PRECIP_POP": "משקעים", + "PRECIP_AMOUNT": "כמות משקעים", + + "MODULE_CONFIG_CHANGED": "אפשרויות התצורה עבור מודול {MODULE_NAME} השתנו.\nאנא בדוק את התיעוד.", + "MODULE_CONFIG_ERROR": "שגיאה במודול {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "כתובת אתר לא תקינה.", + "MODULE_ERROR_NO_CONNECTION": "אין חיבור לאינטרנט.", + "MODULE_ERROR_UNAUTHORIZED": "הזדהות נכשלה.", + "MODULE_ERROR_UNSPECIFIED": "בדוק את היומנים לפרטים נוספים.", + + "NEWSFEED_NO_ITEMS": "אין חדשות כרגע.", "UPDATE_NOTIFICATION": "עדכון זמין ל-MagicMirror²", "UPDATE_NOTIFICATION_MODULE": "עדכון זמין ב-{MODULE_NAME} מודול", "UPDATE_INFO_SINGLE": "ההתקנה הנוכחית נמצאת מאחור הענף {BRANCH_NAME} ב-{COMMIT_COUNT} מופע", - "UPDATE_INFO_MULTIPLE": "ההתקנה הנוכחית נמצאת מאחור הענף {BRANCH_NAME} ב-{COMMIT_COUNT} מופעים" + "UPDATE_INFO_MULTIPLE": "ההתקנה הנוכחית נמצאת מאחור הענף {BRANCH_NAME} ב-{COMMIT_COUNT} מופעים", + "UPDATE_NOTIFICATION_DONE": "העדכון הסתיים עבור מודול {MODULE_NAME}", + "UPDATE_NOTIFICATION_ERROR": "שגיאת עדכון עבור מודול {MODULE_NAME}", + "UPDATE_NOTIFICATION_NEED-RESTART": "יש צורך לאתחל את ה-MagicMirror" } diff --git a/translations/hi.json b/translations/hi.json index f93d2c25b8..725a8a89f8 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -28,12 +28,23 @@ "NNW": "उउप", "FEELS": "{DEGREE} की तरह लगना", - "PRECIP_POP": "PoP", + "PRECIP_POP": "वृष्टि की संभावना", + "PRECIP_AMOUNT": "वृष्टि मात्रा", "MODULE_CONFIG_CHANGED": "{MODULE_NAME} मॉड्यूल के लिए कॉन्फ़िगरेशन विकल्प बदल गए हैं। n कृपया दस्तावेज़ देखें।", + "MODULE_CONFIG_ERROR": "{MODULE_NAME} मॉड्यूल में त्रुटि। {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "गलत URL।", + "MODULE_ERROR_NO_CONNECTION": "कोई इंटरनेट कनेक्शन नहीं।", + "MODULE_ERROR_UNAUTHORIZED": "प्राधिकरण विफल।", + "MODULE_ERROR_UNSPECIFIED": "अधिक जानकारी के लिए लॉग जांचें।", + + "NEWSFEED_NO_ITEMS": "इस समय कोई समाचार नहीं।", "UPDATE_NOTIFICATION": "MagicMirror² अपडेट उपलब्ध।", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} मॉड्यूल के लिए उपलब्ध अद्यतन।", "UPDATE_INFO_SINGLE": "वर्तमान स्थापना {COMMIT_COUNT} {BRANCH_NAME} शाखा के पीछे है।", - "UPDATE_INFO_MULTIPLE": "वर्तमान स्थापना {COMMIT_COUNT} पीछे {BRANCH_NAME} शाखा पर है।" + "UPDATE_INFO_MULTIPLE": "वर्तमान स्थापना {COMMIT_COUNT} पीछे {BRANCH_NAME} शाखा पर है।", + "UPDATE_NOTIFICATION_DONE": "{MODULE_NAME} मॉड्यूल के लिए अद्यतन पूरा।", + "UPDATE_NOTIFICATION_ERROR": "{MODULE_NAME} मॉड्यूल के लिए अद्यतन त्रुटि।", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror को पुनः आरंभ करने की आवश्यकता है।" } diff --git a/translations/hr.json b/translations/hr.json index 27b835fd7d..8964aeaa95 100644 --- a/translations/hr.json +++ b/translations/hr.json @@ -28,9 +28,23 @@ "NNW": "NNW", "FEELS": "Osjećaj {DEGREE}", + "PRECIP_POP": "Vjerojatnost padalina", + "PRECIP_AMOUNT": "Količina padalina", + + "MODULE_CONFIG_CHANGED": "Opcije konfiguracije za modul {MODULE_NAME} su promijenjene.\nMolimo provjerite dokumentaciju.", + "MODULE_CONFIG_ERROR": "Greška u modulu {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Neispravan URL.", + "MODULE_ERROR_NO_CONNECTION": "Nema internetske veze.", + "MODULE_ERROR_UNAUTHORIZED": "Autorizacija nije uspjela.", + "MODULE_ERROR_UNSPECIFIED": "Provjerite dnevnike za više informacija.", + + "NEWSFEED_NO_ITEMS": "Trenutno nema vijesti.", "UPDATE_NOTIFICATION": "Dostupna je aktualizacija MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostupna je aktualizacija modula {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Instalirana verzija {COMMIT_COUNT} commit kasni za branch-om {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Instalirana verzija {COMMIT_COUNT} commit-ova kasni za branch-om {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Instalirana verzija {COMMIT_COUNT} commit-ova kasni za branch-om {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "Ažuriranje je završeno za modul {MODULE_NAME}.", + "UPDATE_NOTIFICATION_ERROR": "Greška pri ažuriranju modula {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Potrebno je ponovno pokretanje MagicMirror-a." } diff --git a/translations/hu.json b/translations/hu.json index 7a8b3d7f76..2c31349b7b 100644 --- a/translations/hu.json +++ b/translations/hu.json @@ -1,6 +1,7 @@ { "LOADING": "Betöltés …", + "YESTERDAY": "Tegnap", "TODAY": "Ma", "TOMORROW": "Holnap", "DAYAFTERTOMORROW": "Holnapután", @@ -26,9 +27,23 @@ "NNW": "ÉÉNy", "FEELS": "Érzet {DEGREE}", + "PRECIP_POP": "Csapadék valószínűség", + "PRECIP_AMOUNT": "Csapadék mennyisége", + + "MODULE_CONFIG_CHANGED": "A(z) {MODULE_NAME} modul konfigurációs beállításai megváltoztak.\nKérjük, ellenőrizze a dokumentációt.", + "MODULE_CONFIG_ERROR": "Hiba a(z) {MODULE_NAME} modulban. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Hibás URL.", + "MODULE_ERROR_NO_CONNECTION": "Nincs internetkapcsolat.", + "MODULE_ERROR_UNAUTHORIZED": "Azonosítás sikertelen.", + "MODULE_ERROR_UNSPECIFIED": "Ellenőrizze a naplókat további részletekért.", + + "NEWSFEED_NO_ITEMS": "Jelenleg nincsenek hírek.", "UPDATE_NOTIFICATION": "MagicMirror²-hoz frissítés érhető el.", "UPDATE_NOTIFICATION_MODULE": "A {MODULE_NAME} modulhoz frissítés érhető el.", "UPDATE_INFO_SINGLE": "A jelenlegi telepítés óta {COMMIT_COUNT} új commit jelent meg a {BRANCH_NAME} ágon.", - "UPDATE_INFO_MULTIPLE": "A jelenlegi telepítés óta {COMMIT_COUNT} új commit jelent meg a {BRANCH_NAME} ágon." + "UPDATE_INFO_MULTIPLE": "A jelenlegi telepítés óta {COMMIT_COUNT} új commit jelent meg a {BRANCH_NAME} ágon.", + "UPDATE_NOTIFICATION_DONE": "A frissítés befejeződött a {MODULE_NAME} modulhoz.", + "UPDATE_NOTIFICATION_ERROR": "Hiba történt a frissítés során a {MODULE_NAME} modulhoz.", + "UPDATE_NOTIFICATION_NEED-RESTART": "A MagicMirror újraindítása szükséges." } diff --git a/translations/id.json b/translations/id.json index 439d2151f8..4bb83eb93c 100644 --- a/translations/id.json +++ b/translations/id.json @@ -26,8 +26,24 @@ "NW": "BL", "NNW": "UBL", + "FEELS": "Terasa {DEGREE}", + "PRECIP_POP": "Kemungkinan curah hujan", + "PRECIP_AMOUNT": "Jumlah curah hujan", + + "MODULE_CONFIG_CHANGED": "Opsi konfigurasi modul {MODULE_NAME} telah diubah.\nSilakan periksa dokumentasi.", + "MODULE_CONFIG_ERROR": "Terjadi kesalahan pada modul {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL tidak valid.", + "MODULE_ERROR_NO_CONNECTION": "Tidak ada koneksi internet.", + "MODULE_ERROR_UNAUTHORIZED": "Gagal otentikasi.", + "MODULE_ERROR_UNSPECIFIED": "Silakan periksa log untuk informasi lebih lanjut.", + + "NEWSFEED_NO_ITEMS": "Saat ini tidak ada berita.", + "UPDATE_NOTIFICATION": "Memperbarui MagicMirror² tersedia.", "UPDATE_NOTIFICATION_MODULE": "Memperbarui tersedia untuk modul {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Instalasi saat ini tertinggal {COMMIT_COUNT} commit pada cabang {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Instalasi saat ini tertinggal {COMMIT_COUNT} commits pada cabang {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Instalasi saat ini tertinggal {COMMIT_COUNT} commits pada cabang {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "Pembaruan modul {MODULE_NAME} selesai.", + "UPDATE_NOTIFICATION_ERROR": "Terjadi kesalahan saat memperbarui modul {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Diperlukan restart MagicMirror." } diff --git a/translations/is.json b/translations/is.json index c4da887cf7..d664a9f284 100644 --- a/translations/is.json +++ b/translations/is.json @@ -8,6 +8,7 @@ "DAYAFTERTOMORROW": "Ekki á morgun, heldur hinn", "RUNNING": "Endar eftir", "EMPTY": "Ekkert framundan.", + "WEEK": "Vika {weekNumber}", "N": "N", "NNE": "NNA", @@ -26,8 +27,24 @@ "NW": "NV", "NNW": "NNV", + "FEELS": "Kælist á {DEGREE}", + "PRECIP_POP": "Úrkoma", + "PRECIP_AMOUNT": "Magn úrkomu", + + "MODULE_CONFIG_CHANGED": "Stillingar fyrir {MODULE_NAME} module hafa breyst.\nVinsamlegast skoðaðu skjöl.", + "MODULE_CONFIG_ERROR": "Villa í {MODULE_NAME} module. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Villa í slóð.", + "MODULE_ERROR_NO_CONNECTION": "Engin nettenging.", + "MODULE_ERROR_UNAUTHORIZED": "Auðkenning mistókst.", + "MODULE_ERROR_UNSPECIFIED": "Vinsamlegast athugaðu skráningu fyrir frekari upplýsingar.", + + "NEWSFEED_NO_ITEMS": "Engar fréttir í boði núna.", + "UPDATE_NOTIFICATION": "MagicMirror² uppfærsla í boði.", "UPDATE_NOTIFICATION_MODULE": "Uppfærsla í boði fyrir {MODULE_NAME} module.", "UPDATE_INFO_SINGLE": "Núverandi kerfi er {COMMIT_COUNT} commit á eftir {BRANCH_NAME} branchinu.", - "UPDATE_INFO_MULTIPLE": "Núverandi kerfi er {COMMIT_COUNT} commits á eftir {BRANCH_NAME} branchinu." + "UPDATE_INFO_MULTIPLE": "Núverandi kerfi er {COMMIT_COUNT} commits á eftir {BRANCH_NAME} branchinu.", + "UPDATE_NOTIFICATION_DONE": "Uppfærsla lokið fyrir {MODULE_NAME} module", + "UPDATE_NOTIFICATION_ERROR": "Villa við uppfærslu fyrir {MODULE_NAME} module", + "UPDATE_NOTIFICATION_NEED-RESTART": "Endurræsa MagicMirror er nauðsynlegt." } diff --git a/translations/it.json b/translations/it.json index 79199f1a47..78051638ee 100644 --- a/translations/it.json +++ b/translations/it.json @@ -27,9 +27,23 @@ "NNW": "NNO", "FEELS": "Percepiti {DEGREE}", + "PRECIP_POP": "Probabilità di precipitazioni", + "PRECIP_AMOUNT": "Quantità di precipitazioni", + + "MODULE_CONFIG_CHANGED": "Le opzioni di configurazione del modulo {MODULE_NAME} sono state modificate.\nSi prega di consultare la documentazione.", + "MODULE_CONFIG_ERROR": "Errore nel modulo {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL non valido.", + "MODULE_ERROR_NO_CONNECTION": "Nessuna connessione a Internet.", + "MODULE_ERROR_UNAUTHORIZED": "Autenticazione non riuscita.", + "MODULE_ERROR_UNSPECIFIED": "Si prega di controllare i log per ulteriori dettagli.", + + "NEWSFEED_NO_ITEMS": "Al momento non ci sono notizie.", "UPDATE_NOTIFICATION": "E' disponibile un aggiornamento di MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "E' disponibile un aggiornamento del modulo {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "L'installazione è {COMMIT_COUNT} commit indietro rispetto all'attuale branch {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "L'installazione è {COMMIT_COUNT} commits indietro rispetto all'attuale branch {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "L'installazione è {COMMIT_COUNT} commits indietro rispetto all'attuale branch {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "L'aggiornamento del modulo {MODULE_NAME} è stato completato.", + "UPDATE_NOTIFICATION_ERROR": "Errore durante l'aggiornamento del modulo {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "E' necessario riavviare MagicMirror." } diff --git a/translations/ja.json b/translations/ja.json index a59a82bfc9..e74da77cbc 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -5,8 +5,10 @@ "YESTERDAY": "昨日", "TODAY": "今日", "TOMORROW": "明日", + "DAYAFTERTOMORROW": "明後日", "RUNNING": "で終わります", "EMPTY": "直近のイベントはありません", + "WEEK": "第 {weekNumber} 週", "N": "北", "NNE": "北北東", @@ -23,5 +25,26 @@ "W": "西", "WNW": "西北西", "NW": "北西", - "NNW": "北北西" + "NNW": "北北西", + + "FEELS": "体感温度 {DEGREE}", + "PRECIP_POP": "降水確率", + "PRECIP_AMOUNT": "降水量", + + "MODULE_CONFIG_CHANGED": "モジュール {MODULE_NAME} の設定オプションが変更されました。\nドキュメントを確認してください。", + "MODULE_CONFIG_ERROR": "モジュール {MODULE_NAME} でエラーが発生しました。{ERROR}", + "MODULE_ERROR_MALFORMED_URL": "不正なURLです。", + "MODULE_ERROR_NO_CONNECTION": "インターネット接続がありません。", + "MODULE_ERROR_UNAUTHORIZED": "認証に失敗しました。", + "MODULE_ERROR_UNSPECIFIED": "詳細はログを確認してください。", + + "NEWSFEED_NO_ITEMS": "現在ニュースはありません。", + + "UPDATE_NOTIFICATION": "MagicMirror² のアップデートが利用可能です。", + "UPDATE_NOTIFICATION_MODULE": "モジュール {MODULE_NAME} のアップデートが利用可能です。", + "UPDATE_INFO_SINGLE": "現在のインストールは {BRANCH_NAME} ブランチから {COMMIT_COUNT} コミット遅れています。", + "UPDATE_INFO_MULTIPLE": "現在のインストールは {BRANCH_NAME} ブランチから {COMMIT_COUNT} コミット遅れています。", + "UPDATE_NOTIFICATION_DONE": "モジュール {MODULE_NAME} のアップデートが完了しました。", + "UPDATE_NOTIFICATION_ERROR": "モジュール {MODULE_NAME} のアップデート中にエラーが発生しました。", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror の再起動が必要です。" } diff --git a/translations/ko.json b/translations/ko.json index 7fc8432889..0e6bbd5ed5 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -1,6 +1,7 @@ { "LOADING": "로드 중 …", + "DAYBEFOREYESTERDAY": "그저께", "YESTERDAY": "어제", "TODAY": "오늘", "TOMORROW": "내일", @@ -27,7 +28,8 @@ "NNW": "북북서풍", "FEELS": "체감온도 {DEGREE}", - "PRECIP_POP": "PoP", + "PRECIP_POP": "강수 확률", + "PRECIP_AMOUNT": "강수량", "MODULE_CONFIG_CHANGED": "모듈 {MODULE_NAME}의 설정값이 바뀌었습니다.\n매뉴얼을 참고하세요.", "MODULE_CONFIG_ERROR": "에러 : {MODULE_NAME} - {ERROR}", @@ -36,8 +38,13 @@ "MODULE_ERROR_UNAUTHORIZED": "인증이 실패했습니다.", "MODULE_ERROR_UNSPECIFIED": "상세 내용은 로그를 확인하세요.", + "NEWSFEED_NO_ITEMS": "현재 뉴스가 없습니다.", + "UPDATE_NOTIFICATION": "새로운 MagicMirror² 업데이트가 있습니다.", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} 모듈에서 사용 가능한 업데이트 입니다.", "UPDATE_INFO_SINGLE": "설치할 {COMMIT_COUNT} commit 는 {BRANCH_NAME} 분기에 해당됩니다.", - "UPDATE_INFO_MULTIPLE": "설치할 {COMMIT_COUNT} commits 는 {BRANCH_NAME} 분기에 해당됩니다." + "UPDATE_INFO_MULTIPLE": "설치할 {COMMIT_COUNT} commits 는 {BRANCH_NAME} 분기에 해당됩니다.", + "UPDATE_NOTIFICATION_DONE": "모듈 {MODULE_NAME}의 업데이트가 완료되었습니다.", + "UPDATE_NOTIFICATION_ERROR": "모듈 {MODULE_NAME}의 업데이트 중 오류가 발생했습니다.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror를 재시작해야 합니다." } diff --git a/translations/lt.json b/translations/lt.json index dc7a23af1a..b922b5193e 100644 --- a/translations/lt.json +++ b/translations/lt.json @@ -29,9 +29,22 @@ "FEELS": "Jutiminė temp. {DEGREE}", "PRECIP_POP": "Krituliai", + "PRECIP_AMOUNT": "Kritulių kiekis", + + "MODULE_CONFIG_CHANGED": "Modulio {MODULE_NAME} konfigūracijos parinktys pasikeitė.\nPrašome patikrinti dokumentaciją.", + "MODULE_CONFIG_ERROR": "Klaida modulyje {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Netinkama URL nuoroda.", + "MODULE_ERROR_NO_CONNECTION": "Nėra interneto ryšio.", + "MODULE_ERROR_UNAUTHORIZED": "Autorizacija nepavyko.", + "MODULE_ERROR_UNSPECIFIED": "Patikrinkite žurnalus, kad gautumėte daugiau informacijos.", + + "NEWSFEED_NO_ITEMS": "Šiuo metu naujienų nėra.", "UPDATE_NOTIFICATION": "Galimas MagicMirror² naujinimas.", "UPDATE_NOTIFICATION_MODULE": "Galimas {MODULE_NAME} naujinimas.", "UPDATE_INFO_SINGLE": "Šis įdiegimas atsilieka {COMMIT_COUNT} įsipareigojimu {BRANCH_NAME} šakoje.", - "UPDATE_INFO_MULTIPLE": "Šis įdiegimas atsilieka {COMMIT_COUNT} įsipareigojimais {BRANCH_NAME} šakoje." + "UPDATE_INFO_MULTIPLE": "Šis įdiegimas atsilieka {COMMIT_COUNT} įsipareigojimais {BRANCH_NAME} šakoje.", + "UPDATE_NOTIFICATION_DONE": "Naujinimas {MODULE_NAME} baigtas.", + "UPDATE_NOTIFICATION_ERROR": "Klaida atnaujinant {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Reikalingas MagicMirror perkrovimas." } diff --git a/translations/ms-my.json b/translations/ms-my.json index 07d0bb996c..d3e7a9565f 100644 --- a/translations/ms-my.json +++ b/translations/ms-my.json @@ -1,6 +1,7 @@ { "LOADING": "Tunggu Sebentar …", + "DAYBEFOREYESTERDAY": "Kelmarin", "YESTERDAY": "Semalam", "TODAY": "Hari ini", "TOMORROW": "Esok", @@ -26,8 +27,24 @@ "NW": "BL", "NNW": "UBL", + "FEELS": "Rasa seperti {DEGREE}", + "PRECIP_POP": "Kemungkinan hujan", + "PRECIP_AMOUNT": "Jumlah hujan", + + "MODULE_CONFIG_CHANGED": "Pilihan konfigurasi untuk modul {MODULE_NAME} telah berubah.\nSila rujuk dokumentasi.", + "MODULE_CONFIG_ERROR": "Ralat dalam modul {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL tidak sah.", + "MODULE_ERROR_NO_CONNECTION": "Tiada sambungan internet.", + "MODULE_ERROR_UNAUTHORIZED": "Kebenaran gagal.", + "MODULE_ERROR_UNSPECIFIED": "Sila semak log untuk maklumat lanjut.", + + "NEWSFEED_NO_ITEMS": "Tiada berita buat masa ini.", + "UPDATE_NOTIFICATION": "MagicMirror² mempunyai update terkini.", "UPDATE_NOTIFICATION_MODULE": "Modul {MODULE_NAME} mempunyai update terkini.", "UPDATE_INFO_SINGLE": "Pemasangan MagicMirror² ini mempunyai {COMMIT_COUNT} commit terkebelakang dari branch {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Pemasangan MagicMirror² ini mempunyai {COMMIT_COUNT} commit terkebelakang dari branch {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Pemasangan MagicMirror² ini mempunyai {COMMIT_COUNT} commit terkebelakang dari branch {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "Update selesai untuk modul {MODULE_NAME}", + "UPDATE_NOTIFICATION_ERROR": "Ralat update untuk modul {MODULE_NAME}", + "UPDATE_NOTIFICATION_NEED-RESTART": "Perlu restart MagicMirror." } diff --git a/translations/nb.json b/translations/nb.json index 669b2d265a..8eac3eec0f 100644 --- a/translations/nb.json +++ b/translations/nb.json @@ -31,8 +31,20 @@ "PRECIP_POP": "Sannsynlighet for nedbør", "PRECIP_AMOUNT": "Nedbørsmengde", + "MODULE_CONFIG_CHANGED": "Innstillingene for {MODULE_NAME}-modulen har endret seg.\nVennligst sjekk dokumentasjonen.", + "MODULE_CONFIG_ERROR": "Feil i {MODULE_NAME}-modulen. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Ugyldig URL.", + "MODULE_ERROR_NO_CONNECTION": "Ingen internettforbindelse.", + "MODULE_ERROR_UNAUTHORIZED": "Autentisering mislyktes.", + "MODULE_ERROR_UNSPECIFIED": "Vennligst sjekk loggene for mer informasjon.", + + "NEWSFEED_NO_ITEMS": "Ingen nyheter tilgjengelig for øyeblikket.", + "UPDATE_NOTIFICATION": "MagicMirror²-oppdatering er tilgjengelig.", "UPDATE_NOTIFICATION_MODULE": "Oppdatering tilgjengelig for modulen {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Nåværende installasjon er {COMMIT_COUNT} commit bak {BRANCH_NAME} grenen.", - "UPDATE_INFO_MULTIPLE": "Nåværende installasjon er {COMMIT_COUNT} commits bak {BRANCH_NAME} grenen." + "UPDATE_INFO_MULTIPLE": "Nåværende installasjon er {COMMIT_COUNT} commits bak {BRANCH_NAME} grenen.", + "UPDATE_NOTIFICATION_DONE": "Oppdateringen av modulen {MODULE_NAME} er fullført.", + "UPDATE_NOTIFICATION_ERROR": "Det oppstod en feil under oppdateringen av modulen {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Det er nødvendig med en omstart av MagicMirror." } diff --git a/translations/nl.json b/translations/nl.json index 8e2fbb34eb..26d55fab95 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -29,6 +29,7 @@ "FEELS": "Voelt als {DEGREE}", "PRECIP_POP": "Neerslagkans", + "PRECIP_AMOUNT": "Neerslaghoeveelheid", "MODULE_CONFIG_CHANGED": "De configuratie opties voor de module {MODULE_NAME} zijn gewijzigd.\nControleer de documentatie.", "MODULE_CONFIG_ERROR": "Fout in de {MODULE_NAME} module. {ERROR}", @@ -42,5 +43,8 @@ "UPDATE_NOTIFICATION": "MagicMirror² update beschikbaar.", "UPDATE_NOTIFICATION_MODULE": "Update beschikbaar voor {MODULE_NAME} module.", "UPDATE_INFO_SINGLE": "De huidige installatie loopt {COMMIT_COUNT} commit achter op de {BRANCH_NAME} branch.", - "UPDATE_INFO_MULTIPLE": "De huidige installatie loopt {COMMIT_COUNT} commits achter op de {BRANCH_NAME} branch." + "UPDATE_INFO_MULTIPLE": "De huidige installatie loopt {COMMIT_COUNT} commits achter op de {BRANCH_NAME} branch.", + "UPDATE_NOTIFICATION_DONE": "Update voltooid voor {MODULE_NAME} module.", + "UPDATE_NOTIFICATION_ERROR": "Fout tijdens het updaten van {MODULE_NAME} module.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror moet opnieuw worden opgestart." } diff --git a/translations/nn.json b/translations/nn.json index 609d8fc646..ce97e29bf7 100644 --- a/translations/nn.json +++ b/translations/nn.json @@ -8,6 +8,7 @@ "DAYAFTERTOMORROW": "I overmorgon", "RUNNING": "Sluttar om", "EMPTY": "Ingen komande hendingar.", + "WEEK": "Veke {weekNumber}", "N": "N", "NNE": "NNA", @@ -27,9 +28,23 @@ "NNW": "NNV", "FEELS": "Kjenst som {DEGREE}", + "PRECIP_POP": "Sannsyn for nedbør", + "PRECIP_AMOUNT": "Nedbørsmengde", + + "MODULE_CONFIG_CHANGED": "Innstillingane for {MODULE_NAME} modulen har endra seg.\nVennligst sjekk dokumentasjonen.", + "MODULE_CONFIG_ERROR": "Feil i {MODULE_NAME} modulen. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Ugyldig URL.", + "MODULE_ERROR_NO_CONNECTION": "Ingen internettforbindelse.", + "MODULE_ERROR_UNAUTHORIZED": "Autentisering mislyktes.", + "MODULE_ERROR_UNSPECIFIED": "Vennligst sjekk loggfilene for meir informasjon.", + + "NEWSFEED_NO_ITEMS": "Ingen nyhende tilgjengeleg no.", "UPDATE_NOTIFICATION": "MagicMirror² oppdatering er tilgjengeleg.", "UPDATE_NOTIFICATION_MODULE": "Oppdatering tilgjengeleg for modulen {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "noverande installasjon er {COMMIT_COUNT} commit bak {BRANCH_NAME} greinen.", - "UPDATE_INFO_MULTIPLE": "noverande installasjon er {COMMIT_COUNT} commits bak {BRANCH_NAME} greinen." + "UPDATE_INFO_MULTIPLE": "noverande installasjon er {COMMIT_COUNT} commits bak {BRANCH_NAME} greinen.", + "UPDATE_NOTIFICATION_DONE": "Oppdateringa av modulen {MODULE_NAME} er fullført.", + "UPDATE_NOTIFICATION_ERROR": "Det oppstod ein feil under oppdateringa av modulen {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Det er nødvendig med ein omstart av MagicMirror." } diff --git a/translations/pl.json b/translations/pl.json index 04fd0ca194..f12bde0abb 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -29,9 +29,22 @@ "FEELS": "Odczuwalna {DEGREE}", "PRECIP_POP": "Szansa opadów", + "PRECIP_AMOUNT": "Ilość opadów", + + "MODULE_CONFIG_CHANGED": "Opcje konfiguracji modułu {MODULE_NAME} zostały zmienione.\nProszę sprawdzić dokumentację.", + "MODULE_CONFIG_ERROR": "Błąd w module {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Nieprawidłowy adres URL.", + "MODULE_ERROR_NO_CONNECTION": "Brak połączenia z internetem.", + "MODULE_ERROR_UNAUTHORIZED": "Autoryzacja nie powiodła się.", + "MODULE_ERROR_UNSPECIFIED": "Sprawdź logi, aby uzyskać więcej informacji.", + + "NEWSFEED_NO_ITEMS": "Brak wiadomości w tej chwili.", "UPDATE_NOTIFICATION": "Dostępna jest aktualizacja MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostępna jest aktualizacja modułu {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Zainstalowana wersja odbiega o {COMMIT_COUNT} commit od gałęzi {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Zainstalowana wersja odbiega o {COMMIT_COUNT} commitów od gałęzi {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Zainstalowana wersja odbiega o {COMMIT_COUNT} commitów od gałęzi {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "Aktualizacja modułu {MODULE_NAME} zakończona.", + "UPDATE_NOTIFICATION_ERROR": "Błąd aktualizacji modułu {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Wymagany jest restart MagicMirror." } diff --git a/translations/pt-br.json b/translations/pt-br.json index 4c1a49061a..1a7ecafcb0 100644 --- a/translations/pt-br.json +++ b/translations/pt-br.json @@ -7,6 +7,7 @@ "TOMORROW": "Amanhã", "RUNNING": "Acaba em", "EMPTY": "Nenhum evento novo.", + "WEEK": "Semana {weekNumber}", "N": "N", "NNE": "NNE", @@ -26,10 +27,23 @@ "NNW": "NNO", "FEELS": "Percebida {DEGREE}", - "PRECIP_POP": "PoP", + "PRECIP_POP": "Probabilidade de precipitação", + "PRECIP_AMOUNT": "Quantidade de precipitação", + + "MODULE_CONFIG_CHANGED": "As opções de configuração do módulo {MODULE_NAME} foram alteradas.\nConsulte a documentação.", + "MODULE_CONFIG_ERROR": "Erro no módulo {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL inválido.", + "MODULE_ERROR_NO_CONNECTION": "Sem conexão com a Internet.", + "MODULE_ERROR_UNAUTHORIZED": "Falha na autenticação.", + "MODULE_ERROR_UNSPECIFIED": "Verifique os logs para mais detalhes.", + + "NEWSFEED_NO_ITEMS": "Atualmente não há notícias.", "UPDATE_NOTIFICATION": "Nova atualização para MagicMirror² disponível.", "UPDATE_NOTIFICATION_MODULE": "Atualização para o módulo {MODULE_NAME} disponível.", "UPDATE_INFO_SINGLE": "Sua versão atual é a {COMMIT_COUNT} commit dentro do seguinte branch {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Sua versão atual é a {COMMIT_COUNT} commits dentro do seguinte branch {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Sua versão atual é a {COMMIT_COUNT} commits dentro do seguinte branch {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "A atualização do módulo {MODULE_NAME} foi concluída.", + "UPDATE_NOTIFICATION_ERROR": "Ocorreu um erro ao atualizar o módulo {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "É necessário reiniciar o MagicMirror." } diff --git a/translations/pt.json b/translations/pt.json index 2b1e1cf0ff..b923a33b5e 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -29,11 +29,22 @@ "FEELS": "Sentida {DEGREE}", "PRECIP_POP": "Prob. Precipitação", + "PRECIP_AMOUNT": "Quantidade de precipitação", "MODULE_CONFIG_CHANGED": "As opções na configuração do módulo {MODULE_NAME} foram alteradas.\nPor favor, verifica a documentação.", + "MODULE_CONFIG_ERROR": "Erro no módulo {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL inválido.", + "MODULE_ERROR_NO_CONNECTION": "Sem ligação à Internet.", + "MODULE_ERROR_UNAUTHORIZED": "Autenticação falhou.", + "MODULE_ERROR_UNSPECIFIED": "Por favor, verifica os logs para mais detalhes.", + + "NEWSFEED_NO_ITEMS": "Atualmente não há notícias.", "UPDATE_NOTIFICATION": "Atualização do MagicMirror² disponível.", "UPDATE_NOTIFICATION_MODULE": "Atualização para o módulo {MODULE_NAME} disponível.", "UPDATE_INFO_SINGLE": "A instalação atual está {COMMIT_COUNT} commit atrasada no branch {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "A instalação atual está {COMMIT_COUNT} commits atrasada no branch {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "A instalação atual está {COMMIT_COUNT} commits atrasada no branch {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "A atualização do módulo {MODULE_NAME} foi concluída.", + "UPDATE_NOTIFICATION_ERROR": "Ocorreu um erro ao atualizar o módulo {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "É necessário reiniciar o MagicMirror." } diff --git a/translations/ro.json b/translations/ro.json index ce04e337a2..1dfa6f5d5e 100644 --- a/translations/ro.json +++ b/translations/ro.json @@ -28,9 +28,23 @@ "NNW": "NNW", "FEELS": "Se simte ca fiind {DEGREE}", + "PRECIP_POP": "Probabilitate de precipitații", + "PRECIP_AMOUNT": "Cantitate de precipitații", + + "MODULE_CONFIG_CHANGED": "Opțiunile de configurare pentru modulul {MODULE_NAME} s-au schimbat.\nVă rugăm să verificați documentația.", + "MODULE_CONFIG_ERROR": "Eroare în modulul {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL incorect.", + "MODULE_ERROR_NO_CONNECTION": "Fără conexiune la internet.", + "MODULE_ERROR_UNAUTHORIZED": "Autorizarea a eșuat.", + "MODULE_ERROR_UNSPECIFIED": "Verificați jurnalele pentru mai multe detalii.", + + "NEWSFEED_NO_ITEMS": "Nu există știri în acest moment.", "UPDATE_NOTIFICATION": "Un update este disponibil pentru MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Un update este disponibil pentru modulul {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Există {COMMIT_COUNT} commit-uri noi pe branch-ul {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Există {COMMIT_COUNT} commit-uri noi pe branch-ul {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Există {COMMIT_COUNT} commit-uri noi pe branch-ul {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "Update-ul a fost finalizat pentru modulul {MODULE_NAME}", + "UPDATE_NOTIFICATION_ERROR": "Eroare la update-ul modulului {MODULE_NAME}", + "UPDATE_NOTIFICATION_NEED-RESTART": "Este necesară repornirea MagicMirror." } diff --git a/translations/ru.json b/translations/ru.json index eb4c2f77be..fde2fe81e2 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -28,9 +28,23 @@ "NNW": "ССЗ", "FEELS": "По ощущению {DEGREE}", + "PRECIP_POP": "Вероятность осадков", + "PRECIP_AMOUNT": "Количество осадков", + + "MODULE_CONFIG_CHANGED": "Настройки модуля {MODULE_NAME} изменены.\nПожалуйста, проверьте документацию.", + "MODULE_CONFIG_ERROR": "Ошибка в модуле {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Неверный URL.", + "MODULE_ERROR_NO_CONNECTION": "Нет интернет-соединения.", + "MODULE_ERROR_UNAUTHORIZED": "Не удалось авторизоваться.", + "MODULE_ERROR_UNSPECIFIED": "Пожалуйста, проверьте логи для получения дополнительной информации.", + + "NEWSFEED_NO_ITEMS": "В данный момент нет новостей.", "UPDATE_NOTIFICATION": "Есть обновление для MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Есть обновление для {MODULE_NAME} модуля.", "UPDATE_INFO_SINGLE": "Данная инсталляция позади {BRANCH_NAME} commit ветки на {COMMIT_COUNT} коммитов.", - "UPDATE_INFO_MULTIPLE": "Данная инсталляция позади {BRANCH_NAME} commits ветки на {COMMIT_COUNT} коммитов." + "UPDATE_INFO_MULTIPLE": "Данная инсталляция позади {BRANCH_NAME} commits ветки на {COMMIT_COUNT} коммитов.", + "UPDATE_NOTIFICATION_DONE": "Обновление модуля {MODULE_NAME} завершено.", + "UPDATE_NOTIFICATION_ERROR": "Ошибка обновления модуля {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Требуется перезапуск MagicMirror." } diff --git a/translations/sk.json b/translations/sk.json index ef1757b85b..1736d0cc3c 100644 --- a/translations/sk.json +++ b/translations/sk.json @@ -27,8 +27,24 @@ "NW": "SZ", "NNW": "SSZ", + "FEELS": "Pocit ako {DEGREE}", + "PRECIP_POP": "Pravdepodobnosť zrážok", + "PRECIP_AMOUNT": "Množstvo zrážok", + + "MODULE_CONFIG_CHANGED": "Konfiguračné možnosti modulu {MODULE_NAME} boli zmenené.\nProsím, skontrolujte dokumentáciu.", + "MODULE_CONFIG_ERROR": "Chyba v module {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Nesprávna URL adresa.", + "MODULE_ERROR_NO_CONNECTION": "Nie je pripojenie k internetu.", + "MODULE_ERROR_UNAUTHORIZED": "Autorizácia zlyhala.", + "MODULE_ERROR_UNSPECIFIED": "Skontrolujte protokoly pre viac informácií.", + + "NEWSFEED_NO_ITEMS": "Momentálne žiadne správy.", + "UPDATE_NOTIFICATION": "Dostupná aktualizácia pre MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostupná aktualizácia pre modul {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Súčasná inštalácia je na vetve {BRANCH_NAME} pozadu o {COMMIT_COUNT} commit.", - "UPDATE_INFO_MULTIPLE": "Súčasná inštalácia je na vetve {BRANCH_NAME} pozadu o {COMMIT_COUNT} commitov." + "UPDATE_INFO_MULTIPLE": "Súčasná inštalácia je na vetve {BRANCH_NAME} pozadu o {COMMIT_COUNT} commitov.", + "UPDATE_NOTIFICATION_DONE": "Aktualizácia dokončená pre modul {MODULE_NAME}.", + "UPDATE_NOTIFICATION_ERROR": "Chyba aktualizácie modulu {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Je potrebné reštartovať MagicMirror." } diff --git a/translations/sv.json b/translations/sv.json index 0d37a1bba6..5a6961ffa4 100644 --- a/translations/sv.json +++ b/translations/sv.json @@ -28,9 +28,23 @@ "NNW": "NNV", "FEELS": "Känns som {DEGREE}", + "PRECIP_POP": "Nederbördsrisk", + "PRECIP_AMOUNT": "Nederbördsmängd", + + "MODULE_CONFIG_CHANGED": "Konfigurationsalternativen för modulen {MODULE_NAME} har ändrats.\nVänligen se dokumentationen.", + "MODULE_CONFIG_ERROR": "Fel i modulen {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Felaktig URL.", + "MODULE_ERROR_NO_CONNECTION": "Ingen internetanslutning.", + "MODULE_ERROR_UNAUTHORIZED": "Autentisering misslyckades.", + "MODULE_ERROR_UNSPECIFIED": "Vänligen kontrollera loggarna för mer information.", + + "NEWSFEED_NO_ITEMS": "Inga nyheter för tillfället.", "UPDATE_NOTIFICATION": "MagicMirror² uppdatering finns tillgänglig.", "UPDATE_NOTIFICATION_MODULE": "Uppdatering finns tillgänglig av {MODULE_NAME} modulen.", "UPDATE_INFO_SINGLE": "Denna installation ligger {COMMIT_COUNT} commit steg bakom {BRANCH_NAME} grenen.", - "UPDATE_INFO_MULTIPLE": "Denna installation ligger {COMMIT_COUNT} commits steg bakom {BRANCH_NAME} grenen." + "UPDATE_INFO_MULTIPLE": "Denna installation ligger {COMMIT_COUNT} commits steg bakom {BRANCH_NAME} grenen.", + "UPDATE_NOTIFICATION_DONE": "Uppdateringen av modulen {MODULE_NAME} har slutförts.", + "UPDATE_NOTIFICATION_ERROR": "Ett fel inträffade vid uppdateringen av modulen {MODULE_NAME}.", + "UPDATE_NOTIFICATION_NEED-RESTART": "Det krävs en omstart av MagicMirror." } diff --git a/translations/th.json b/translations/th.json index 26f472b7b9..6a9965ac45 100644 --- a/translations/th.json +++ b/translations/th.json @@ -1,8 +1,11 @@ { "LOADING": "กำลังโหลด …", + "DAYBEFOREYESTERDAY": "เมื่อวานซืน", + "YESTERDAY": "เมื่อวานนี้", "TODAY": "วันนี้", "TOMORROW": "พรุ่งนี้", + "DAYAFTERTOMORROW": "มะรืนนี้", "RUNNING": "สิ้นสุดใน", "EMPTY": "ไม่มีกิจกรรมที่กำลังจะมาถึง", "WEEK": "สัปดาห์ที่ {weekNumber}", @@ -24,6 +27,7 @@ "NW": "ต.ต.น.", "NNW": "น.ต.ต.น.", + "FEELS": "รู้สึกเหมือน {DEGREE}", "PRECIP_POP": "ความแม่นยำ", "PRECIP_AMOUNT": "ปริมาณน้ำฝน", @@ -39,5 +43,8 @@ "UPDATE_NOTIFICATION": "MagicMirror² มีการอัปเดต", "UPDATE_NOTIFICATION_MODULE": "มีการอัปเดตสำหรับโมดูล {MODULE_NAME}", "UPDATE_INFO_SINGLE": "การติดตั้งปัจจุบันถูกคอมมิท {COMMIT_COUNT} รายการในสาขา {BRANCH_NAME}", - "UPDATE_INFO_MULTIPLE": "การติดตั้งปัจจุบันคือ {COMMIT_COUNT} เป็นคอมมิทที่อยู่เบื้องหลังในสาขา {BRANCH_NAME}" + "UPDATE_INFO_MULTIPLE": "การติดตั้งปัจจุบันคือ {COMMIT_COUNT} เป็นคอมมิทที่อยู่เบื้องหลังในสาขา {BRANCH_NAME}", + "UPDATE_NOTIFICATION_DONE": "การอัปเดตเสร็จสิ้นสำหรับโมดูล {MODULE_NAME}", + "UPDATE_NOTIFICATION_ERROR": "เกิดข้อผิดพลาดในการอัปเดตโมดูล {MODULE_NAME}", + "UPDATE_NOTIFICATION_NEED-RESTART": "ต้องรีสตาร์ท MagicMirror" } diff --git a/translations/tlh.json b/translations/tlh.json index 6bcefefa55..05d24c5b1f 100644 --- a/translations/tlh.json +++ b/translations/tlh.json @@ -28,9 +28,23 @@ "NNW": "NNW", "FEELS": "jem {DEGREE}", + "PRECIP_POP": "nIHmey", + "PRECIP_AMOUNT": "nIHmey Daq", + + "MODULE_CONFIG_CHANGED": "mIghtaH {MODULE_NAME} mIghtaHmey lIjwI'pu'.\nDoHbe' yImev.", + "MODULE_CONFIG_ERROR": "{MODULE_NAME} mIghtaHmeyDaq ghobe' yImev. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL ghobe' yImev.", + "MODULE_ERROR_NO_CONNECTION": "Internet ghobe' yImev.", + "MODULE_ERROR_UNAUTHORIZED": "ghobe' yImev.", + "MODULE_ERROR_UNSPECIFIED": "logmeyDaq yImev.", + + "NEWSFEED_NO_ITEMS": "DaHghachmey ghobe' yImev.", "UPDATE_NOTIFICATION": " De'chu' MagicMirror² lI'laH.", "UPDATE_NOTIFICATION_MODULE": "bobcho' {MODULE_NAME} lI'laH De'chu.", - "UPDATE_INFO_SINGLE": "The current installation is {COMMIT_COUNT} commit behind on the {BRANCH_NAME} branch.", - "UPDATE_INFO_MULTIPLE": "The current installation is {COMMIT_COUNT} commits behind on the {BRANCH_NAME} branch." + "UPDATE_INFO_SINGLE": "{BRANCH_NAME} ghoghDaq {COMMIT_COUNT} commit lIjwI'pu'.", + "UPDATE_INFO_MULTIPLE": "{BRANCH_NAME} ghoghDaq {COMMIT_COUNT} commit lIjwI'pu'.", + "UPDATE_NOTIFICATION_DONE": "{MODULE_NAME} mIghtaHmeyDaq bobcho' lIjwI'pu'.", + "UPDATE_NOTIFICATION_ERROR": "{MODULE_NAME} mIghtaHmeyDaq bobcho' ghobe' yImev.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirrorDaq yImev." } diff --git a/translations/tr.json b/translations/tr.json index 3c03f2954c..08f0690401 100644 --- a/translations/tr.json +++ b/translations/tr.json @@ -28,9 +28,22 @@ "FEELS": "Hissedilen {DEGREE}", "PRECIP_POP": "Yağış", + "PRECIP_AMOUNT": "Yağış miktarı", + + "MODULE_CONFIG_CHANGED": "{MODULE_NAME} modülü için yapılandırma seçenekleri değiştirildi.\nLütfen belgeleri kontrol edin.", + "MODULE_CONFIG_ERROR": "{MODULE_NAME} modülünde hata. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Hatalı URL.", + "MODULE_ERROR_NO_CONNECTION": "İnternet bağlantısı yok.", + "MODULE_ERROR_UNAUTHORIZED": "Yetkilendirme başarısız.", + "MODULE_ERROR_UNSPECIFIED": "Daha fazla ayrıntı için günlükleri kontrol edin.", + + "NEWSFEED_NO_ITEMS": "Şu anda haber yok.", "UPDATE_NOTIFICATION": "MagicMirror² güncellemesi mevcut.", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} modulü için güncelleme mevcut.", "UPDATE_INFO_SINGLE": "Sahip olduğunuz kurulum {BRANCH_NAME} branchinden {COMMIT_COUNT} commit geridedir.", - "UPDATE_INFO_MULTIPLE": "Sahip olduğunuz kurulum {BRANCH_NAME} branchinden {COMMIT_COUNT} commit geridedir." + "UPDATE_INFO_MULTIPLE": "Sahip olduğunuz kurulum {BRANCH_NAME} branchinden {COMMIT_COUNT} commit geridedir.", + "UPDATE_NOTIFICATION_DONE": "Güncelleme tamamlandı.", + "UPDATE_NOTIFICATION_ERROR": "Güncelleme sırasında hata oluştu.", + "UPDATE_NOTIFICATION_NEED-RESTART": "MagicMirror'ün yeniden başlatılması gerekiyor." } diff --git a/translations/uk.json b/translations/uk.json index 3bb4284e0d..70f5a3cbac 100644 --- a/translations/uk.json +++ b/translations/uk.json @@ -29,9 +29,22 @@ "FEELS": "Відчувається як {DEGREE}", "PRECIP_POP": "Опади", + "PRECIP_AMOUNT": "Кількість опадів", + + "MODULE_CONFIG_CHANGED": "Змінились параметри конфігурації модуля {MODULE_NAME}.\nБудь ласка, перевірте документацію.", + "MODULE_CONFIG_ERROR": "Помилка в модулі {MODULE_NAME}. {ERROR}", + "MODULE_ERROR_MALFORMED_URL": "Неправильний URL.", + "MODULE_ERROR_NO_CONNECTION": "Немає підключення до Інтернету.", + "MODULE_ERROR_UNAUTHORIZED": "Авторизація не вдалася.", + "MODULE_ERROR_UNSPECIFIED": "Перевірте журнали для отримання додаткової інформації.", + + "NEWSFEED_NO_ITEMS": "Немає новин на даний момент.", "UPDATE_NOTIFICATION": "Є оновлення для MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Є оновлення для модуля {MODULE_NAME}.", "UPDATE_INFO_SINGLE": "Поточна версія на {COMMIT_COUNT} комміт позаду від гілки {BRANCH_NAME}.", - "UPDATE_INFO_MULTIPLE": "Поточна інсталяція на {COMMIT_COUNT} комітів позаду від гілки {BRANCH_NAME}." + "UPDATE_INFO_MULTIPLE": "Поточна інсталяція на {COMMIT_COUNT} комітів позаду від гілки {BRANCH_NAME}.", + "UPDATE_NOTIFICATION_DONE": "Оновлення завершено для модуля {MODULE_NAME}", + "UPDATE_NOTIFICATION_ERROR": "Помилка оновлення модуля {MODULE_NAME}", + "UPDATE_NOTIFICATION_NEED-RESTART": "Потрібен перезапуск MagicMirror." } diff --git a/translations/zh-cn.json b/translations/zh-cn.json index f4ee2562f7..7ece692365 100644 --- a/translations/zh-cn.json +++ b/translations/zh-cn.json @@ -28,9 +28,23 @@ "NNW": "北偏西风", "FEELS": "体感 {DEGREE}", + "PRECIP_POP": "降水概率", + "PRECIP_AMOUNT": "降水量", + + "MODULE_CONFIG_CHANGED": "模块{MODULE_NAME}的配置选项已更改。\n请查看文档。", + "MODULE_CONFIG_ERROR": "模块{MODULE_NAME}发生错误。{ERROR}", + "MODULE_ERROR_MALFORMED_URL": "URL格式错误。", + "MODULE_ERROR_NO_CONNECTION": "无网络连接。", + "MODULE_ERROR_UNAUTHORIZED": "授权失败。", + "MODULE_ERROR_UNSPECIFIED": "请查看日志以获取更多详细信息。", + + "NEWSFEED_NO_ITEMS": "目前没有新闻。", "UPDATE_NOTIFICATION": "MagicMirror²有新的版本。", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME}模块可更新。", "UPDATE_INFO_SINGLE": "当前已安装版本比{BRANCH_NAME}分支落后{COMMIT_COUNT}次代码更新。", - "UPDATE_INFO_MULTIPLE": "当前已安装版本比{BRANCH_NAME}分支落后{COMMIT_COUNT}次代码更新。" + "UPDATE_INFO_MULTIPLE": "当前已安装版本比{BRANCH_NAME}分支落后{COMMIT_COUNT}次代码更新。", + "UPDATE_NOTIFICATION_DONE": "{MODULE_NAME}模块更新完成。", + "UPDATE_NOTIFICATION_ERROR": "{MODULE_NAME}模块更新错误。", + "UPDATE_NOTIFICATION_NEED-RESTART": "需要重启MagicMirror。" } diff --git a/translations/zh-tw.json b/translations/zh-tw.json index 6bdd95dcb5..8b6a9dac38 100644 --- a/translations/zh-tw.json +++ b/translations/zh-tw.json @@ -29,6 +29,7 @@ "FEELS": "體感溫度 {DEGREE}", "PRECIP_POP": "降雨機率", + "PRECIP_AMOUNT": "降雨量", "MODULE_CONFIG_CHANGED": "模組 {MODULE_NAME} 的設定檔選項已更改。\n請參見說明文件。", "MODULE_CONFIG_ERROR": "{MODULE_NAME} 模組發生錯誤。{ERROR}", @@ -42,5 +43,8 @@ "UPDATE_NOTIFICATION": "MagicMirror² 有可用更新。", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} 模組有可用更新。", "UPDATE_INFO_SINGLE": "目前版本在 {BRANCH_NAME} 分支上已落後了 {COMMIT_COUNT} 次 commit。", - "UPDATE_INFO_MULTIPLE": "目前版本在 {BRANCH_NAME} 分支上已落後了 {COMMIT_COUNT} 次 commit。" + "UPDATE_INFO_MULTIPLE": "目前版本在 {BRANCH_NAME} 分支上已落後了 {COMMIT_COUNT} 次 commit。", + "UPDATE_NOTIFICATION_DONE": "{MODULE_NAME} 模組更新完成。", + "UPDATE_NOTIFICATION_ERROR": "{MODULE_NAME} 模組更新錯誤。", + "UPDATE_NOTIFICATION_NEED-RESTART": "需要重新啟動 MagicMirror。" } From 052ec1ca26d4997c5373fdb0abc685e20ecb8071 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 7 Jun 2025 13:20:01 +0200 Subject: [PATCH 230/418] remove existing folders fonts and vendor from local installations (#3805) see discussions [here](https://github.com/MagicMirrorOrg/MagicMirror/pull/3795#issuecomment-2927804743). The used command should work under windows too. I'm open to better solutions. Co-authored-by: Veeck --- CHANGELOG.md | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a44c8b2e80..e7a75093bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,7 @@ planned for 2025-07-01 - [workflow] Replace Node.js version v23 with v24 (#3770) - [refactor] Replace deprecated constants `fs.F_OK` and `fs.R_OK` (#3789) - [refactor] Replace `ansis` with built-in function `util.styleText` (#3793) -- [core] Integrate stuff from `vendor` and `fonts` folders into main `package.json`, simplifies install and maintaining dependencies (#3795) +- [core] Integrate stuff from `vendor` and `fonts` folders into main `package.json`, simplifies install and maintaining dependencies (#3795, #3805) - [l10n] Complete translations (with the help of translation tools) (#3794) ### Fixed diff --git a/package.json b/package.json index 4bbe43ac54..269ac5be38 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "lint:js": "eslint --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", + "postinstall": "git clean -df fonts vendor", "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.", "server": "node ./serveronly", "start": "node --run start:x11", From faf15ad211875347c9253de6493888d0cb30e41b Mon Sep 17 00:00:00 2001 From: Koen Konst Date: Sat, 7 Jun 2025 14:13:01 +0200 Subject: [PATCH 231/418] Refactored calendarfetcherutils to fix many of the timezone and DST related issues and make debugging way easier (#3806) Refactored calendarfetcherutils to remove as many of the date conversions as possible and use moment tz when calculating recurring events, this will make debugging a lot easier and fixes problems from the past with offsets and DST not being handled properly. Also added some tests to test the behavior of the refactored methodes to make sure the correct event dates are returned. Refactored calendar.js aswell to make sure the unix UTC start and end date of events are properly converted to a local timezone and displayed correctly for the user. This PR relates to: https://github.com/MagicMirrorOrg/MagicMirror/issues/3797 --------- Co-authored-by: Koen Konst Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> --- CHANGELOG.md | 4 + cspell.config.json | 3 + modules/default/calendar/calendar.js | 149 ++-- .../default/calendar/calendarfetcherutils.js | 717 +++++------------- tests/electron/modules/calendar_spec.js | 41 +- .../calendar/calendar_fetcher_utils_spec.js | 63 ++ 6 files changed, 339 insertions(+), 638 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7a75093bf..ac1ffbb4fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,10 @@ planned for 2025-07-01 - [refactor] Replace `ansis` with built-in function `util.styleText` (#3793) - [core] Integrate stuff from `vendor` and `fonts` folders into main `package.json`, simplifies install and maintaining dependencies (#3795, #3805) - [l10n] Complete translations (with the help of translation tools) (#3794) +- [refactor] Refactored `calendarfetcherutils` in Calendar module to handle timezones better (#3806) + - Removed as many of the date conversions as possible + - Use `moment-timezone` when calculating recurring events, this will fix problems from the past with offsets and DST not being handled properly + - Added some tests to test the behavior of the refactored methods to make sure the correct event dates are returned ### Fixed diff --git a/cspell.config.json b/cspell.config.json index e681059f84..54a78a9383 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -52,6 +52,8 @@ "dkallen", "drivelist", "DTEND", + "DTSTAMP", + "DTSTART", "Duffman", "earlman", "easyas", @@ -107,6 +109,7 @@ "jsonlint", "jupadin", "kaennchenstruggle", + "Kalenderwoche", "kenzal", "Keyport", "khassel", diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index e2f921db28..a7aad9b38b 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -77,7 +77,7 @@ Module.register("calendar", { // Define required scripts. getScripts () { - return ["calendarutils.js", "moment.js"]; + return ["calendarutils.js", "moment.js", "moment-timezone.js"]; }, // Define required translations. @@ -215,18 +215,9 @@ Module.register("calendar", { this.updateDom(this.config.animationSpeed); }, - eventEndingWithinNextFullTimeUnit (event, ONE_DAY) { - const now = new Date(); - return event.endDate - now <= ONE_DAY; - }, - // Override dom generator. getDom () { const ONE_SECOND = 1000; // 1,000 milliseconds - const ONE_MINUTE = ONE_SECOND * 60; - const ONE_HOUR = ONE_MINUTE * 60; - const ONE_DAY = ONE_HOUR * 24; - const events = this.createEventList(true); const wrapper = document.createElement("table"); wrapper.className = this.config.tableClass; @@ -258,7 +249,9 @@ Module.register("calendar", { let lastSeenDate = ""; events.forEach((event, index) => { - const dateAsString = moment(event.startDate, "x").format(this.config.dateFormat); + const eventStartDateMoment = this.timestampToMoment(event.startDate); + const eventEndDateMoment = this.timestampToMoment(event.endDate); + const dateAsString = eventStartDateMoment.format(this.config.dateFormat); if (this.config.timeFormat === "dateheaders") { if (lastSeenDate !== dateAsString) { const dateRow = document.createElement("tr"); @@ -340,7 +333,7 @@ Module.register("calendar", { repeatingCountTitle = this.countTitleForUrl(event.url); if (repeatingCountTitle !== "") { - const thisYear = new Date(parseInt(event.startDate)).getFullYear(), + const thisYear = eventStartDateMoment.year(), yearDiff = thisYear - event.firstYear; repeatingCountTitle = `, ${yearDiff} ${repeatingCountTitle}`; @@ -395,14 +388,14 @@ Module.register("calendar", { timeWrapper.className = `time light ${this.config.flipDateHeaderTitle ? "align-right " : "align-left "}${this.timeClassForUrl(event.url)}`; timeWrapper.style.paddingLeft = "2px"; timeWrapper.style.textAlign = this.config.flipDateHeaderTitle ? "right" : "left"; - timeWrapper.innerHTML = moment(event.startDate, "x").format("LT"); + timeWrapper.innerHTML = eventStartDateMoment.format("LT"); // Add endDate to dataheaders if showEnd is enabled if (this.config.showEnd) { if (this.config.showEndsOnlyWithDuration && event.startDate === event.endDate) { // no duration here, don't display end } else { - timeWrapper.innerHTML += ` - ${CalendarUtils.capFirst(moment(event.endDate, "x").format("LT"))}`; + timeWrapper.innerHTML += ` - ${CalendarUtils.capFirst(eventEndDateMoment.format("LT"))}`; } } @@ -415,44 +408,43 @@ Module.register("calendar", { const timeWrapper = document.createElement("td"); eventWrapper.appendChild(titleWrapper); - const now = new Date(); + const now = moment(); if (this.config.timeFormat === "absolute") { // Use dateFormat - timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").format(this.config.dateFormat)); + timeWrapper.innerHTML = CalendarUtils.capFirst(eventStartDateMoment.format(this.config.dateFormat)); // Add end time if showEnd if (this.config.showEnd) { // and has a duation if (event.startDate !== event.endDate) { timeWrapper.innerHTML += "-"; - timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat)); + timeWrapper.innerHTML += CalendarUtils.capFirst(eventEndDateMoment.format(this.config.dateEndFormat)); } } // For full day events we use the fullDayEventDateFormat if (event.fullDayEvent) { //subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day - event.endDate -= ONE_SECOND; - timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").format(this.config.fullDayEventDateFormat)); + eventEndDateMoment.subtract(1, "second"); + timeWrapper.innerHTML = CalendarUtils.capFirst(eventStartDateMoment.format(this.config.fullDayEventDateFormat)); // only show end if requested and allowed and the dates are different - if (this.config.showEnd && !this.config.showEndsOnlyWithDuration && moment(event.startDate, "x").format("YYYYMMDD") !== moment(event.endDate, "x").format("YYYYMMDD")) { + if (this.config.showEnd && !this.config.showEndsOnlyWithDuration && !eventStartDateMoment.isSame(eventEndDateMoment, "d")) { timeWrapper.innerHTML += "-"; - timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.fullDayEventDateFormat)); - } else - if ((moment(event.startDate, "x").format("YYYYMMDD") !== moment(event.endDate, "x").format("YYYYMMDD")) && (moment(event.startDate, "x") < moment(now, "x"))) { - timeWrapper.innerHTML = CalendarUtils.capFirst(moment(now, "x").format(this.config.fullDayEventDateFormat)); - } - } else if (this.config.getRelative > 0 && event.startDate < now) { + timeWrapper.innerHTML += CalendarUtils.capFirst(eventEndDateMoment.format(this.config.fullDayEventDateFormat)); + } else if (!eventStartDateMoment.isSame(eventEndDateMoment, "d") && eventStartDateMoment.isBefore(now)) { + timeWrapper.innerHTML = CalendarUtils.capFirst(now.format(this.config.fullDayEventDateFormat)); + } + } else if (this.config.getRelative > 0 && eventStartDateMoment.isBefore(now)) { // Ongoing and getRelative is set timeWrapper.innerHTML = CalendarUtils.capFirst( this.translate("RUNNING", { fallback: `${this.translate("RUNNING")} {timeUntilEnd}`, - timeUntilEnd: moment(event.endDate, "x").fromNow(true) + timeUntilEnd: eventEndDateMoment.fromNow(true) }) ); - } else if (this.config.urgency > 0 && event.startDate - now < this.config.urgency * ONE_DAY) { + } else if (this.config.urgency > 0 && eventStartDateMoment.diff(now, "d") < this.config.urgency) { // Within urgency days - timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").fromNow()); + timeWrapper.innerHTML = CalendarUtils.capFirst(eventStartDateMoment.fromNow()); } if (event.fullDayEvent && this.config.nextDaysRelative) { // Full days events within the next two days @@ -460,9 +452,9 @@ Module.register("calendar", { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TODAY")); } else if (event.yesterday) { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("YESTERDAY")); - } else if (event.startDate - now < ONE_DAY && event.startDate - now > 0) { + } else if (event.tomorrow) { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TOMORROW")); - } else if (event.startDate - now < 2 * ONE_DAY && event.startDate - now > 0) { + } else if (event.dayAfterTomorrow) { if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW")); } @@ -470,15 +462,15 @@ Module.register("calendar", { } } else { // Show relative times - if (event.startDate >= now || (event.fullDayEvent && this.eventEndingWithinNextFullTimeUnit(event, ONE_DAY))) { + if (eventStartDateMoment.isSameOrAfter(now) || (event.fullDayEvent && eventEndDateMoment.diff(now, "days") === 0)) { // Use relative time if (!this.config.hideTime && !event.fullDayEvent) { Log.debug("event not hidden and not fullday"); - timeWrapper.innerHTML = `${CalendarUtils.capFirst(moment(event.startDate, "x").calendar(null, { sameElse: this.config.dateFormat }))}`; + timeWrapper.innerHTML = `${CalendarUtils.capFirst(eventStartDateMoment.calendar(null, { sameElse: this.config.dateFormat }))}`; } else { Log.debug("event full day or hidden"); timeWrapper.innerHTML = `${CalendarUtils.capFirst( - moment(event.startDate, "x").calendar(null, { + eventStartDateMoment.calendar(null, { sameDay: this.config.showTimeToday ? "LT" : `[${this.translate("TODAY")}]`, nextDay: `[${this.translate("TOMORROW")}]`, nextWeek: "dddd", @@ -488,7 +480,7 @@ Module.register("calendar", { } if (event.fullDayEvent) { // Full days events within the next two days - if (event.today || (event.fullDayEvent && this.eventEndingWithinNextFullTimeUnit(event, ONE_DAY))) { + if (event.today || (event.fullDayEvent && eventEndDateMoment.diff(now, "days") === 0)) { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TODAY")); } else if (event.dayBeforeYesterday) { if (this.translate("DAYBEFOREYESTERDAY") !== "DAYBEFOREYESTERDAY") { @@ -496,25 +488,25 @@ Module.register("calendar", { } } else if (event.yesterday) { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("YESTERDAY")); - } else if (event.startDate - now < ONE_DAY && event.startDate - now > 0) { + } else if (event.tomorrow) { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TOMORROW")); - } else if (event.startDate - now < 2 * ONE_DAY && event.startDate - now > 0) { + } else if (event.dayAfterTomorrow) { if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW")); } } Log.info("event fullday"); - } else if (event.startDate - now < this.config.getRelative * ONE_HOUR) { + } else if (eventStartDateMoment.diff(now, "h") < this.config.getRelative) { Log.info("not full day but within getrelative size"); // If event is within getRelative hours, display 'in xxx' time format or moment.fromNow() - timeWrapper.innerHTML = `${CalendarUtils.capFirst(moment(event.startDate, "x").fromNow())}`; + timeWrapper.innerHTML = `${CalendarUtils.capFirst(eventStartDateMoment.fromNow())}`; } } else { // Ongoing event timeWrapper.innerHTML = CalendarUtils.capFirst( this.translate("RUNNING", { fallback: `${this.translate("RUNNING")} {timeUntilEnd}`, - timeUntilEnd: moment(event.endDate, "x").fromNow(true) + timeUntilEnd: eventEndDateMoment.fromNow(true) }) ); } @@ -593,46 +585,46 @@ Module.register("calendar", { return false; }, + /** + * converts the given timestamp to a moment with a timezone + * @param {number} timestamp timestamp from an event + * @returns {moment.Moment} moment with a timezone + */ + timestampToMoment (timestamp) { + return moment(timestamp, "x").tz(moment.tz.guess()); + }, + /** * Creates the sorted list of all events. * @param {boolean} limitNumberOfEntries Whether to filter returned events for display. * @returns {object[]} Array with events. */ createEventList (limitNumberOfEntries) { - const ONE_SECOND = 1000; // 1,000 milliseconds - const ONE_MINUTE = ONE_SECOND * 60; - const ONE_HOUR = ONE_MINUTE * 60; - const ONE_DAY = ONE_HOUR * 24; - - let now, today, future; - if (this.config.forceUseCurrentTime || this.defaults.forceUseCurrentTime) { - now = new Date(); - today = moment().startOf("day"); - future = moment().startOf("day").add(this.config.maximumNumberOfDays, "days").toDate(); - } else { - now = new Date(Date.now()); // Can use overridden time - today = moment(now).startOf("day"); - future = moment(now).startOf("day").add(this.config.maximumNumberOfDays, "days").toDate(); - } + let now = moment(); + let today = now.clone().startOf("day"); + let future = now.clone().startOf("day").add(this.config.maximumNumberOfDays, "days"); + let events = []; for (const calendarUrl in this.calendarData) { const calendar = this.calendarData[calendarUrl]; let remainingEntries = this.maximumEntriesForUrl(calendarUrl); - let maxPastDaysCompare = now - this.maximumPastDaysForUrl(calendarUrl) * ONE_DAY; + let maxPastDaysCompare = now.clone().subtract(this.maximumPastDaysForUrl(calendarUrl), "days"); let by_url_calevents = []; for (const e in calendar) { const event = JSON.parse(JSON.stringify(calendar[e])); // clone object + const eventStartDateMoment = this.timestampToMoment(event.startDate); + const eventEndDateMoment = this.timestampToMoment(event.endDate); if (this.config.hidePrivate && event.class === "PRIVATE") { // do not add the current event, skip it continue; } if (limitNumberOfEntries) { - if (event.endDate < maxPastDaysCompare) { + if (eventEndDateMoment.isBefore(maxPastDaysCompare)) { continue; } - if (this.config.hideOngoing && event.startDate < now) { + if (this.config.hideOngoing && eventStartDateMoment.isBefore(now)) { continue; } if (this.config.hideDuplicates && this.listContainsEvent(events, event)) { @@ -641,47 +633,46 @@ Module.register("calendar", { } event.url = calendarUrl; - event.today = event.startDate >= today && event.startDate < today + ONE_DAY; - event.dayBeforeYesterday = event.startDate >= today - ONE_DAY * 2 && event.startDate < today - ONE_DAY; - event.yesterday = event.startDate >= today - ONE_DAY && event.startDate < today; - event.tomorrow = !event.today && event.startDate >= today + ONE_DAY && event.startDate < today + 2 * ONE_DAY; - event.dayAfterTomorrow = !event.tomorrow && event.startDate >= today + ONE_DAY * 2 && event.startDate < today + 3 * ONE_DAY; + event.today = eventStartDateMoment.isSame(now, "d"); + event.dayBeforeYesterday = eventStartDateMoment.isSame(now.clone().subtract(2, "days"), "d"); + event.yesterday = eventStartDateMoment.isSame(now.clone().subtract(1, "days"), "d"); + event.tomorrow = eventStartDateMoment.isSame(now.clone().add(1, "days"), "d"); + event.dayAfterTomorrow = eventStartDateMoment.isSame(now.clone().add(2, "days"), "d"); /* * if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days, * otherwise, esp. in dateheaders mode it is not clear how long these events are. */ - const maxCount = Math.round((event.endDate - 1 - moment(event.startDate, "x").endOf("day").format("x")) / ONE_DAY) + 1; + const maxCount = eventEndDateMoment.diff(eventStartDateMoment, "days"); if (this.config.sliceMultiDayEvents && maxCount > 1) { const splitEvents = []; let midnight - = moment(event.startDate, "x") + = eventStartDateMoment .clone() .startOf("day") .add(1, "day") - .endOf("day") - .format("x"); + .endOf("day"); let count = 1; - while (event.endDate > midnight) { + while (eventEndDateMoment.isAfter(midnight)) { const thisEvent = JSON.parse(JSON.stringify(event)); // clone object - thisEvent.today = thisEvent.startDate >= today && thisEvent.startDate < today + ONE_DAY; - thisEvent.tomorrow = !thisEvent.today && thisEvent.startDate >= today + ONE_DAY && thisEvent.startDate < today + 2 * ONE_DAY; - thisEvent.endDate = moment(midnight, "x").clone().subtract(1, "day").format("x"); + thisEvent.today = this.timestampToMoment(thisEvent.startDate).isSame(now, "d"); + thisEvent.tomorrow = this.timestampToMoment(thisEvent.startDate).isSame(now.clone().add(1, "days"), "d"); + thisEvent.endDate = midnight.clone().subtract(1, "day").format("x"); thisEvent.title += ` (${count}/${maxCount})`; splitEvents.push(thisEvent); - event.startDate = midnight; + event.startDate = midnight.format("x"); count += 1; - midnight = moment(midnight, "x").add(1, "day").endOf("day").format("x"); // next day + midnight = midnight.clone().add(1, "day").endOf("day"); // next day } // Last day event.title += ` (${count}/${maxCount})`; - event.today += event.startDate >= today && event.startDate < today + ONE_DAY; - event.tomorrow = !event.today && event.startDate >= today + ONE_DAY && event.startDate < today + 2 * ONE_DAY; + event.today += this.timestampToMoment(event.startDate).isSame(now, "d"); + event.tomorrow = this.timestampToMoment(event.startDate).isSame(now.clone().add(1, "days"), "d"); splitEvents.push(event); for (let splitEvent of splitEvents) { - if (splitEvent.endDate > now && splitEvent.endDate <= future) { + if (this.timestampToMoment(splitEvent.endDate).isAfter(now) && this.timestampToMoment(splitEvent.endDate).isSameOrBefore(future)) { by_url_calevents.push(splitEvent); } } @@ -716,16 +707,16 @@ Module.register("calendar", { */ if (this.config.limitDays > 0) { let newEvents = []; - let lastDate = today.clone().subtract(1, "days").format("YYYYMMDD"); + let lastDate = today.clone().subtract(1, "days"); let days = 0; for (const ev of events) { - let eventDate = moment(ev.startDate, "x").format("YYYYMMDD"); + let eventDate = this.timestampToMoment(ev.startDate); /* * if date of event is later than lastdate * check if we already are showing max unique days */ - if (eventDate > lastDate) { + if (eventDate.isAfter(lastDate)) { // if the only entry in the first day is a full day event that day is not counted as unique if (!this.config.limitDaysNeverSkip && newEvents.length === 1 && days === 1 && newEvents[0].fullDayEvent) { days--; diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index 3b037f13c0..880e68b5cf 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -1,114 +1,130 @@ /** * @external Moment */ -const path = require("node:path"); -const moment = require("moment"); +const moment = require("moment-timezone"); -const zoneTable = require(path.join(__dirname, "windowsZones.json")); const Log = require("../../../js/logger"); const CalendarFetcherUtils = { /** - * Calculate the time correction, either dst/std or full day in cases where - * utc time is day before plus offset - * @param {object} event the event which needs adjustment - * @param {Date} date the date on which this event happens - * @returns {number} the necessary adjustment in hours + * Determine based on the title of an event if it should be excluded from the list of events + * TODO This seems like an overly complicated way to exclude events based on the title. + * @param {object} config the global config + * @param {string} title the title of the event + * @returns {object} excluded: true if the event should be excluded, false otherwise + * until: the date until the event should be excluded. */ - calculateTimezoneAdjustment (event, date) { - let adjustHours = 0; - // if a timezone was specified - if (!event.start.tz) { - Log.debug(" if no tz, guess based on now"); - event.start.tz = moment.tz.guess(); - } - Log.debug(`initial tz=${event.start.tz}`); - - // if there is a start date specified - if (event.start.tz) { - // if this is a windows timezone - if (event.start.tz.includes(" ")) { - // use the lookup table to get theIANA name as moment and date don't know MS timezones - let tz = CalendarFetcherUtils.getIanaTZFromMS(event.start.tz); - Log.debug(`corrected TZ=${tz}`); - // watch out for unregistered windows timezone names - // if we had a successful lookup - if (tz) { - // change the timezone to the IANA name - event.start.tz = tz; - // Log.debug("corrected timezone="+event.start.tz) - } - } - Log.debug(`corrected tz=${event.start.tz}`); - let current_offset = 0; // offset from TZ string or calculated - let mm = 0; // date with tz or offset - let start_offset = 0; // utc offset of created with tz - // if there is still an offset, lookup failed, use it - if (event.start.tz.startsWith("(")) { - const regex = /[+|-]\d*:\d*/; - const start_offsetString = event.start.tz.match(regex).toString().split(":"); - let start_offset = parseInt(start_offsetString[0]); - start_offset *= event.start.tz[1] === "-" ? -1 : 1; - adjustHours = start_offset; - Log.debug(`defined offset=${start_offset} hours`); - current_offset = start_offset; - event.start.tz = ""; - Log.debug(`ical offset=${current_offset} date=${date}`); - mm = moment(date); - let x = moment(new Date()).utcOffset(); - Log.debug(`net mins=${current_offset * 60 - x}`); - - mm = mm.add(x - current_offset * 60, "minutes"); - adjustHours = (current_offset * 60 - x) / 60; - event.start = mm.toDate(); - Log.debug(`adjusted date=${event.start}`); - } else { - // get the start time in that timezone - let es = moment(event.start); - // check for start date prior to start of daylight changing date - if (es.format("YYYY") < 2007) { - es.set("year", 2013); // if so, use a closer date + shouldEventBeExcluded (config, title) { + let filter = { + excluded: false, + until: null + }; + for (let f in config.excludedEvents) { + let filter = config.excludedEvents[f], + testTitle = title.toLowerCase(), + until = null, + useRegex = false, + regexFlags = "g"; + + if (filter instanceof Object) { + if (typeof filter.until !== "undefined") { + until = filter.until; } - Log.debug(`start date/time=${es.toDate()}`); - start_offset = moment.tz(es, event.start.tz).utcOffset(); - Log.debug(`start offset=${start_offset}`); - Log.debug(`start date/time w tz =${moment.tz(moment(event.start), event.start.tz).toDate()}`); + if (typeof filter.regex !== "undefined") { + useRegex = filter.regex; + } - // get the specified date in that timezone - mm = moment.tz(moment(date), event.start.tz); - Log.debug(`event date=${mm.toDate()}`); - current_offset = mm.utcOffset(); - } - Log.debug(`event offset=${current_offset} hour=${mm.format("H")} event date=${mm.toDate()}`); - - // if the offset is greater than 0, east of london - if (current_offset !== start_offset) { - // big offset - Log.debug("offset"); - let h = parseInt(mm.format("H")); - // check if the event time is less than the offset - if (h > 0 && h < Math.abs(current_offset) / 60) { - // if so, rrule created a wrong date (utc day, oops, with utc yesterday adjusted time) - // we need to fix that - //adjustHours = 24; - // Log.debug("adjusting date") + // If additional advanced filtering is added in, this section + // must remain last as we overwrite the filter object with the + // filterBy string + if (filter.caseSensitive) { + filter = filter.filterBy; + testTitle = title; + } else if (useRegex) { + filter = filter.filterBy; + testTitle = title; + regexFlags += "i"; + } else { + filter = filter.filterBy.toLowerCase(); } - //-300 > -240 - //if (Math.abs(current_offset) > Math.abs(start_offset)){ - if (current_offset > start_offset) { - adjustHours -= 1; - Log.debug("adjust down 1 hour dst change"); - //} else if (Math.abs(current_offset) < Math.abs(start_offset)) { - } else if (current_offset < start_offset) { - adjustHours += 1; - Log.debug("adjust up 1 hour dst change"); + } else { + filter = filter.toLowerCase(); + } + + if (CalendarFetcherUtils.titleFilterApplies(testTitle, filter, useRegex, regexFlags)) { + if (until) { + filter.until = until; + } else { + filter.excluded = true; } + break; } } - Log.debug(`adjustHours=${adjustHours}`); - return adjustHours; + return filter; + }, + + /** + * Get local timezone. + * This method makes it easier to test if different timezones cause problems by changing this implementation. + * @returns {string} timezone + */ + getLocalTimezone () { + return moment.tz.guess(); + }, + + /** + * This function returns a list of moments for a recurring event. + * @param {object} event the current event which is a recurring event + * @param {moment.Moment} pastLocalMoment The past date to search for recurring events + * @param {moment.Moment} futureLocalMoment The future date to search for recurring events + * @param {number} durationInMs the duration of the event, this is used to take into account currently running events + * @returns {moment.Moment[]} All moments for the recurring event + */ + getMomentsFromRecurringEvent (event, pastLocalMoment, futureLocalMoment, durationInMs) { + const rule = event.rrule; + + // can cause problems with e.g. birthdays before 1900 + if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) { + rule.origOptions.dtstart.setYear(1900); + rule.options.dtstart.setYear(1900); + } + + // subtract the max of the duration of this event or 1 day to find events in the past that are currently still running and should therefor be displayed. + const oneDayInMs = 24 * 60 * 60000; + let searchFromDate = pastLocalMoment.clone().subtract(Math.max(durationInMs, oneDayInMs), "milliseconds").toDate(); + let searchToDate = futureLocalMoment.clone().add(1, "days").toDate(); + Log.debug(`Search for recurring events between: ${searchFromDate} and ${searchToDate}`); + + // if until is set, and its a full day event, force the time to midnight. rrule gets confused with non-00 offset + // looks like MS Outlook sets the until time incorrectly for fullday events + if ((rule.options.until !== undefined) && CalendarFetcherUtils.isFullDayEvent(event)) { + Log.debug("fixup rrule until"); + rule.options.until = moment(rule.options.until).clone().startOf("day").add(1, "day") + .toDate(); + } + + Log.debug("fix rrule start=", rule.options.dtstart); + Log.debug("event before rrule.between=", JSON.stringify(event, null, 2), "exdates=", event.exdate); + + Log.debug(`RRule: ${rule.toString()}`); + rule.options.tzid = null; // RRule gets *very* confused with timezones + + let dates = rule.between(searchFromDate, searchToDate, true, () => { + return true; + }); + + Log.debug(`Title: ${event.summary}, with dates: \n\n${JSON.stringify(dates)}\n`); + + // shouldn't need this anymore, as RRULE not passed junk + dates = dates.filter((d) => { + return JSON.stringify(d) !== "null"; + }); + + // Dates are returned in UTC timezone but with localdatetime because tzid is null. + // So we map the date to a moment using the original timezone of the event. + return dates.map((d) => (event.start.tz ? moment.tz(d, "UTC").tz(event.start.tz, true) : moment.tz(d, "UTC").tz(CalendarFetcherUtils.getLocalTimezone(), true))); }, /** @@ -120,34 +136,33 @@ const CalendarFetcherUtils = { filterEvents (data, config) { const newEvents = []; - // limitFunction doesn't do much limiting, see comment re: the dates - // array in rrule section below as to why we need to do the filtering - // ourselves - const limitFunction = function (date, i) { - return true; - }; - const eventDate = function (event, time) { - return CalendarFetcherUtils.isFullDayEvent(event) ? moment(event[time]).startOf("day") : moment(event[time]); + const startMoment = event[time].tz ? moment.tz(event[time], event[time].tz) : moment.tz(event[time], CalendarFetcherUtils.getLocalTimezone()); + return CalendarFetcherUtils.isFullDayEvent(event) ? startMoment.startOf("day") : startMoment; }; Log.debug(`There are ${Object.entries(data).length} calendar entries.`); - const now = new Date(Date.now()); - const todayLocal = moment(now).startOf("day").toDate(); - const futureLocalDate - = moment(now) + const now = moment(); + const pastLocalMoment = config.includePastEvents ? now.clone().startOf("day").subtract(config.maximumNumberOfDays, "days") : now; + const futureLocalMoment + = now + .clone() .startOf("day") .add(config.maximumNumberOfDays, "days") - .subtract(1, "seconds") // Subtract 1 second so that events that start on the middle of the night will not repeat. - .toDate(); + // 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]) => { Log.debug("Processing entry..."); - let pastLocalDate = todayLocal; - if (config.includePastEvents) { - pastLocalDate = moment(now).startOf("day").subtract(config.maximumNumberOfDays, "days").toDate(); + const title = CalendarFetcherUtils.getTitleFromEvent(event); + Log.debug(`title: ${title}`); + + // Return quickly if event should be excluded. + let { excluded, eventFilterUntil } = this.shouldEventBeExcluded(config, title); + if (excluded) { + return; } // FIXME: Ugly fix to solve the facebook birthday issue. @@ -161,218 +176,47 @@ const CalendarFetcherUtils = { if (event.type === "VEVENT") { Log.debug(`Event:\n${JSON.stringify(event, null, 2)}`); - let startMoment = eventDate(event, "start"); - let endMoment; + let eventStartMoment = eventDate(event, "start"); + let eventEndMoment; if (typeof event.end !== "undefined") { - endMoment = eventDate(event, "end"); + eventEndMoment = eventDate(event, "end"); } else if (typeof event.duration !== "undefined") { - endMoment = startMoment.clone().add(moment.duration(event.duration)); + eventEndMoment = eventStartMoment.clone().add(moment.duration(event.duration)); } else { if (!isFacebookBirthday) { // make copy of start date, separate storage area - endMoment = moment(startMoment.valueOf()); + eventEndMoment = eventStartMoment.clone(); } else { - endMoment = moment(startMoment).add(1, "days"); + eventEndMoment = eventStartMoment.clone().add(1, "days"); } } - Log.debug(`start: ${startMoment.toDate()}`); - Log.debug(`end:: ${endMoment.toDate()}`); + Log.debug(`start: ${eventStartMoment.toDate()}`); + Log.debug(`end:: ${eventEndMoment.toDate()}`); // Calculate the duration of the event for use with recurring events. - const durationMs = endMoment.valueOf() - startMoment.valueOf(); + const durationMs = eventEndMoment.valueOf() - eventStartMoment.valueOf(); Log.debug(`duration: ${durationMs}`); - // FIXME: Since the parsed json object from node-ical comes with time information - // this check could be removed (?) - if (event.start.length === 8) { - startMoment = startMoment.startOf("day"); - } - - const title = CalendarFetcherUtils.getTitleFromEvent(event); - Log.debug(`title: ${title}`); - - let excluded = false, - dateFilter = null; - - for (let f in config.excludedEvents) { - let filter = config.excludedEvents[f], - testTitle = title.toLowerCase(), - until = null, - useRegex = false, - regexFlags = "g"; - - if (filter instanceof Object) { - if (typeof filter.until !== "undefined") { - until = filter.until; - } - - if (typeof filter.regex !== "undefined") { - useRegex = filter.regex; - } - - // If additional advanced filtering is added in, this section - // must remain last as we overwrite the filter object with the - // filterBy string - if (filter.caseSensitive) { - filter = filter.filterBy; - testTitle = title; - } else if (useRegex) { - filter = filter.filterBy; - testTitle = title; - regexFlags += "i"; - } else { - filter = filter.filterBy.toLowerCase(); - } - } else { - filter = filter.toLowerCase(); - } - - if (CalendarFetcherUtils.titleFilterApplies(testTitle, filter, useRegex, regexFlags)) { - if (until) { - dateFilter = until; - } else { - excluded = true; - } - break; - } - } - - if (excluded) { - return; - } - const location = event.location || false; const geo = event.geo || false; const description = event.description || false; - let d1; - let d2; + // TODO This should be a seperate function. if (event.rrule && typeof event.rrule !== "undefined" && !isFacebookBirthday) { - const rule = event.rrule; - - const pastMoment = moment(pastLocalDate); - const futureMoment = moment(futureLocalDate); - - // can cause problems with e.g. birthdays before 1900 - if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) { - rule.origOptions.dtstart.setYear(1900); - rule.options.dtstart.setYear(1900); - } - - // For recurring events, get the set of start dates that fall within the range - // of dates we're looking for. - - let pastLocal; - let futureLocal; - - if (CalendarFetcherUtils.isFullDayEvent(event)) { - Log.debug("fullday"); - // if full day event, only use the date part of the ranges - pastLocal = pastMoment.toDate(); - futureLocal = futureMoment.toDate(); - - Log.debug(`pastLocal: ${pastLocal}`); - Log.debug(`futureLocal: ${futureLocal}`); - } else { - // if we want past events - if (config.includePastEvents) { - // use the calculated past time for the between from - pastLocal = pastMoment.toDate(); - } else { - // otherwise use NOW.. cause we shouldn't use any before now - pastLocal = moment(now).toDate(); //now - } - futureLocal = futureMoment.toDate(); // future - } - const oneDayInMs = 24 * 60 * 60 * 1000; - d1 = new Date(new Date(pastLocal.valueOf() - oneDayInMs).getTime()); - d2 = new Date(new Date(futureLocal.valueOf() + oneDayInMs).getTime()); - Log.debug(`Search for recurring events between: ${d1} and ${d2}`); - - event.start = rule.options.dtstart; - - // if until is set, and its a full day event, force the time to midnight. rrule gets confused with non-00 offset - // looks like MS Outlook sets the until time incorrectly for fullday events - if ((rule.options.until !== undefined) && CalendarFetcherUtils.isFullDayEvent(event)) { - Log.debug("fixup rrule until"); - rule.options.until = new Date(new Date(moment(rule.options.until).startOf("day").add(1, "day")).getTime()); - } - - Log.debug("fix rrule start=", rule.options.dtstart); - Log.debug("event before rrule.between=", JSON.stringify(event, null, 2), "exdates=", event.exdate); - // fixup the exdate and recurrence date to local time too for post between() handling - CalendarFetcherUtils.fixEventtoLocal(event); - - Log.debug(`RRule: ${rule.toString()}`); - rule.options.tzid = null; // RRule gets *very* confused with timezones - - let dates = rule.between(d1, d2, true, () => { return true; }); - - Log.debug(`Title: ${event.summary}, with dates: \n\n${JSON.stringify(dates)}\n`); + // Recurring event. + let moments = CalendarFetcherUtils.getMomentsFromRecurringEvent(event, pastLocalMoment, futureLocalMoment, durationMs); - // shouldn't need this anymore, as RRULE not passed junk - dates = dates.filter((d) => { - if (JSON.stringify(d) === "null") return false; - else return true; - }); - - // go thru all the rrule.between() dates and put back the tz offset removed so rrule.between would work - let datesLocal = []; - let offset = d1.getTimezoneOffset(); - Log.debug("offset =", offset); - dates.forEach((d) => { - let dtext = d.toISOString().slice(0, -5); - Log.debug(" date text form without tz=", dtext); - let dLocal = new Date(d.valueOf() + (offset * 60000)); - let offset2 = dLocal.getTimezoneOffset(); - Log.debug("date after offset applied=", dLocal); - if (offset !== offset2) { - // woops, dst/std switch - let delta = offset - offset2; - Log.debug("offset delta=", delta); - dLocal = new Date(d.valueOf() + ((offset - delta) * 60000)); - Log.debug("corrected normalized date=", dLocal); - } else Log.debug(" neutralized date=", dLocal); - datesLocal.push(dLocal); - }); - dates = datesLocal; - - - // The "dates" array contains the set of dates within our desired date range range that are valid - // for the recurrence rule. *However*, it's possible for us to have a specific recurrence that - // had its date changed from outside the range to inside the range. For the time being, - // we'll handle this by adding *all* recurrence entries into the set of dates that we check, - // because the logic below will filter out any recurrences that don't actually belong within - // our display range. - // Would be great if there was a better way to handle this. - // - // i don't think we will ever see this anymore (oct 2024) due to code fixes for rrule.between() - // - Log.debug("event.recurrences:", event.recurrences); - if (event.recurrences !== undefined) { - for (let dateKey in event.recurrences) { - // Only add dates that weren't already in the range we added from the rrule so that - // we don't double-add those events. - let d = new Date(dateKey); - if (!moment(d).isBetween(d1, d2)) { - Log.debug("adding recurring event not found in between list =", d, " should not happen now using local dates oct 17,24"); - dates.push(d); - } - } - } - - // Loop through the set of date entries to see which recurrences should be added to our event list. - for (let d in dates) { - let date = dates[d]; + // Loop through the set of moment entries to see which recurrences should be added to our event list. + // TODO This should create an event per moment so we can change anything we want. + for (let m in moments) { let curEvent = event; - let curDurationMs = durationMs; let showRecurrence = true; + let recurringEventStartMoment = moments[m].tz(CalendarFetcherUtils.getLocalTimezone()).clone(); + let recurringEventEndMoment = recurringEventStartMoment.clone().add(durationMs, "ms"); - let startMoment = moment(date); - - let dateKey = CalendarFetcherUtils.getDateKeyFromDate(date); + let dateKey = recurringEventStartMoment.tz("UTC").format("YYYY-MM-DD"); Log.debug("event date dateKey=", dateKey); // For each date that we're checking, it's possible that there is a recurrence override for that one day. @@ -382,12 +226,17 @@ const CalendarFetcherUtils = { Log.debug("have a recurrence match for dateKey=", dateKey); // We found an override, so for this recurrence, use a potentially different title, start date, and duration. curEvent = curEvent.recurrences[dateKey]; - curEvent.start = new Date(new Date(curEvent.start.valueOf()).getTime()); - curEvent.end = new Date(new Date(curEvent.end.valueOf()).getTime()); - startMoment = CalendarFetcherUtils.getAdjustedStartMoment(curEvent.start, event); - endMoment = CalendarFetcherUtils.getAdjustedStartMoment(curEvent.end, event); - date = curEvent.start; - curDurationMs = new Date(endMoment).valueOf() - startMoment.valueOf(); + // Some event start/end dates don't have timezones + if (curEvent.start.tz) { + recurringEventStartMoment = moment(curEvent.start).tz(curEvent.start.tz).tz(CalendarFetcherUtils.getLocalTimezone()); + } else { + recurringEventStartMoment = moment(curEvent.start).tz(CalendarFetcherUtils.getLocalTimezone()); + } + if (curEvent.end.tz) { + recurringEventEndMoment = moment(curEvent.end).tz(curEvent.end.tz).tz(CalendarFetcherUtils.getLocalTimezone()); + } else { + recurringEventEndMoment = moment(curEvent.end).tz(CalendarFetcherUtils.getLocalTimezone()); + } } else { Log.debug("recurrence key ", dateKey, " doesn't match"); } @@ -400,25 +249,20 @@ const CalendarFetcherUtils = { showRecurrence = false; } } - Log.debug(`duration: ${curDurationMs}`); - startMoment = CalendarFetcherUtils.getAdjustedStartMoment(date, event); - - endMoment = moment(startMoment.valueOf() + curDurationMs); - - if (startMoment.valueOf() === endMoment.valueOf()) { - endMoment = endMoment.endOf("day"); + if (recurringEventStartMoment.valueOf() === recurringEventEndMoment.valueOf()) { + recurringEventEndMoment = recurringEventEndMoment.endOf("day"); } const recurrenceTitle = CalendarFetcherUtils.getTitleFromEvent(curEvent); // If this recurrence ends before the start of the date range, or starts after the end of the date range, don"t add // it to the event list. - if (endMoment.isBefore(pastLocal) || startMoment.isAfter(futureLocal)) { + if (recurringEventEndMoment.isBefore(pastLocalMoment) || recurringEventStartMoment.isAfter(futureLocalMoment)) { showRecurrence = false; } - if (CalendarFetcherUtils.timeFilterApplies(now, endMoment, dateFilter)) { + if (CalendarFetcherUtils.timeFilterApplies(now, recurringEventEndMoment, eventFilterUntil)) { showRecurrence = false; } @@ -426,8 +270,8 @@ const CalendarFetcherUtils = { Log.debug(`saving event: ${recurrenceTitle}`); newEvents.push({ title: recurrenceTitle, - startDate: startMoment.format("x"), - endDate: endMoment.format("x"), + startDate: recurringEventStartMoment.format("x"), + endDate: recurringEventEndMoment.format("x"), fullDayEvent: CalendarFetcherUtils.isFullDayEvent(event), recurringEvent: true, class: event.class, @@ -437,7 +281,7 @@ const CalendarFetcherUtils = { description: description }); } else { - Log.debug("not saving event ", recurrenceTitle, new Date(startMoment)); + Log.debug("not saving event ", recurrenceTitle, eventStartMoment); } Log.debug(" "); } @@ -448,47 +292,41 @@ const CalendarFetcherUtils = { // Log.debug("full day event") // if the start and end are the same, then make end the 'end of day' value (start is at 00:00:00) - if (fullDayEvent && startMoment.valueOf() === endMoment.valueOf()) { - endMoment = endMoment.endOf("day"); + if (fullDayEvent && eventStartMoment.valueOf() === eventEndMoment.valueOf()) { + eventEndMoment = eventEndMoment.endOf("day"); } if (config.includePastEvents) { // Past event is too far in the past, so skip. - if (endMoment < pastLocalDate) { + if (eventEndMoment < pastLocalMoment) { return; } } else { // It's not a fullday event, and it is in the past, so skip. - if (!fullDayEvent && endMoment < now) { + if (!fullDayEvent && eventEndMoment < now) { return; } // It's a fullday event, and it is before today, So skip. - if (fullDayEvent && endMoment <= todayLocal) { + if (fullDayEvent && eventEndMoment <= now.startOf("day")) { return; } } // It exceeds the maximumNumberOfDays limit, so skip. - if (startMoment > futureLocalDate) { + if (eventStartMoment > futureLocalMoment) { return; } - if (CalendarFetcherUtils.timeFilterApplies(now, endMoment, dateFilter)) { + if (CalendarFetcherUtils.timeFilterApplies(now, eventEndMoment, eventFilterUntil)) { return; } - // get correction for date saving and dst change between now and then - let adjustHours = CalendarFetcherUtils.calculateTimezoneAdjustment(event, startMoment.toDate()); - // This shouldn't happen - if (adjustHours) { - Log.warn(`Unexpected timezone adjustment of ${adjustHours} hours on non-recurring event`); - } // Every thing is good. Add it to the list. newEvents.push({ title: title, - startDate: startMoment.add(adjustHours, "hours").format("x"), - endDate: endMoment.add(adjustHours, "hours").format("x"), + startDate: eventStartMoment.format("x"), + endDate: eventEndMoment.format("x"), fullDayEvent: fullDayEvent, recurringEvent: false, class: event.class, @@ -508,213 +346,6 @@ const CalendarFetcherUtils = { return newEvents; }, - /** - * Fixes the event fields that have dates to use local time - * before calling rrule.between. - * @param {object} event - The event being processed. - * @returns {void} - */ - fixEventtoLocal (event) { - // if there are excluded dates, their date is incorrect and possibly key as well. - if (event.exdate !== undefined) { - Object.keys(event.exdate).forEach((dateKey) => { - // get the date - let exdate = event.exdate[dateKey]; - Log.debug("exdate w key=", exdate); - //exdate=CalendarFetcherUtils.convertDateToLocalTime(exdate, event.end.tz) - exdate = new Date(new Date(exdate.valueOf() - ((120 * 60 * 1000))).getTime()); - Log.debug("new exDate item=", exdate, " with old key=", dateKey); - let newkey = exdate.toISOString().slice(0, 10); - if (newkey !== dateKey) { - Log.debug("new exDate item=", exdate, ` key=${newkey}`); - event.exdate[newkey] = exdate; - //delete event.exdate[dateKey] - } - }); - Log.debug("updated exdate list=", event.exdate); - } - if (event.recurrences) { - Object.keys(event.recurrences).forEach((dateKey) => { - let exdate = event.recurrences[dateKey]; - //exdate=new Date(new Date(exdate.valueOf()-(60*60*1000)).getTime()) - Log.debug("new recurrence item=", exdate, " with old key=", dateKey); - exdate.start = CalendarFetcherUtils.convertDateToLocalTime(exdate.start, exdate.start.tz); - exdate.end = CalendarFetcherUtils.convertDateToLocalTime(exdate.end, exdate.end.tz); - Log.debug("adjusted recurringEvent start=", exdate.start, " end=", exdate.end); - }); - } - Log.debug("modified recurrences before rrule.between", event.recurrences); - }, - - /** - * convert a UTC date to local time - * BEFORE calling rrule.between - * @param {Date} date The date to convert - * @param {string} tz The timezone string to convert the date to. - * @returns {Date} updated date object - */ - convertDateToLocalTime (date, tz) { - let delta_tz_offset = 0; - let now_offset = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(moment.tz.guess()); - let event_offset = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(tz); - Log.debug("date to convert=", date); - if (Math.sign(now_offset) !== Math.sign(event_offset)) { - delta_tz_offset = Math.abs(now_offset) + Math.abs(event_offset); - } else { - // signs are the same - // if negative - if (Math.sign(now_offset) === -1) { - // la looking at chicago - if (now_offset < event_offset) { // 5 -7 - delta_tz_offset = now_offset - event_offset; - } - else { //7 -5 , chicago looking at LA - delta_tz_offset = event_offset - now_offset; - } - } - else { - // berlin looking at sydney - if (now_offset < event_offset) { // 5 -7 - delta_tz_offset = event_offset - now_offset; - Log.debug("less delta=", delta_tz_offset); - } - else { // 11 - 2, sydney looking at berlin - delta_tz_offset = -(now_offset - event_offset); - Log.debug("more delta=", delta_tz_offset); - } - } - } - const newdate = new Date(new Date(date.valueOf() + (delta_tz_offset * 60 * 1000)).getTime()); - Log.debug("modified date =", newdate); - return newdate; - }, - - /** - * get the exdate/recurrence hash key from the date object - * BEFORE calling rrule.between - * @param {Date} date The date of the event - * @returns {string} date key in the format YYYY-MM-DD - */ - getDateKeyFromDate (date) { - // get our runtime timezone offset - const nowDiff = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(moment.tz.guess()); - let startday = date.getDate(); - let adjustment = 0; - Log.debug(" day of month=", (`0${startday}`).slice(-2), " nowDiff=", nowDiff, ` start time=${date.toString().split(" ")[4].slice(0, 2)}`); - Log.debug("date string= ", date.toString()); - Log.debug("date iso string ", date.toISOString()); - // if the dates are different - if (date.toString().slice(8, 10) < date.toISOString().slice(8, 10)) { - startday = date.toString().slice(8, 10); - Log.debug("< ", startday); - } else { // tostring is more - if (date.toString().slice(8, 10) > date.toISOString().slice(8, 10)) { - startday = date.toISOString().slice(8, 10); - Log.debug("> ", startday); - } - } - return date.toISOString().substring(0, 8) + (`0${startday}`).slice(-2); - }, - - /** - * get the timezone offset from the timezone string - * @param {string} timeZone The timezone string - * @returns {number} The numerical offset in minutes from UTC. - */ - getTimezoneOffsetFromTimezone (timeZone) { - const str = new Date().toLocaleString("en", { timeZone, timeZoneName: "longOffset" }); - Log.debug("tz offset=", str); - const [_, h, m] = str.match(/([+-]\d+):(\d+)$/) || ["", "+00", "00"]; - return h * 60 + (h > 0 ? +m : -m); - }, - - /** - * fixup the date start moment after rrule.between returns date array - * @param {Date} date object from rrule.between results - * the event object it came from - * @param {object} event - The event object it came from. - * @returns {Moment} moment object - */ - getAdjustedStartMoment (date, event) { - - let startMoment = moment(date); - - Log.debug("startMoment pre=", startMoment); - // get our runtime timezone offset - const nowDiff = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(moment.tz.guess()); // 10/18 16:49, 300 - let eventDiff = CalendarFetcherUtils.getTimezoneOffsetFromTimezone(event.end.tz); // watch out, start tz is cleared to handle rrule 120 23:49 - - Log.debug("tz diff event=", eventDiff, " local=", nowDiff, " end event timezone=", event.end.tz); - - // if the diffs are different (not same tz for processing as event) - if (nowDiff !== eventDiff) { - // if signs are different - if (Math.sign(nowDiff) !== Math.sign(eventDiff)) { - // its the accumulated total - Log.debug("diff signs, accumulate"); - eventDiff = Math.abs(eventDiff) + Math.abs(nowDiff); - // sign of diff depends on where you are looking at which event. - // australia looking at US, add to get same time - Log.debug("new different event diff=", eventDiff); - if (Math.sign(nowDiff) === -1) { - eventDiff *= -1; - // US looking at australia event have to subtract - Log.debug("new diff, same sign, total event diff=", eventDiff); - } - } - else { - // signs are the same, all east of UTC or all west of UTC - // if the signs are negative (west of UTC) - Log.debug("signs are the same"); - if (Math.sign(eventDiff) === -1) { - //if west, looking at more west - // -350 <-300 - if (nowDiff < eventDiff) { - //-600 -420 - //300 -300 -360 +300 - eventDiff = nowDiff - eventDiff; //-180 - Log.debug("now looking back east delta diff=", eventDiff); - } - else { - Log.debug("now looking more west"); - eventDiff = Math.abs(eventDiff - nowDiff); - } - } else { - Log.debug("signs are both positive"); - // signs are positive (east of UTC) - // berlin < sydney - if (nowDiff < eventDiff) { - // germany vs australia - eventDiff = -(eventDiff - nowDiff); - } - else { - // australia vs germany - //eventDiff = eventDiff; //- nowDiff - } - } - } - startMoment = moment.tz(new Date(date.valueOf() + (eventDiff * (60 * 1000))), event.end.tz); - } else { - Log.debug("same tz event and display"); - eventDiff = 0; - startMoment = moment.tz(new Date(date.valueOf() - (eventDiff * (60 * 1000))), event.end.tz); - } - Log.debug("startMoment post=", startMoment); - return startMoment; - }, - - /** - * Lookup iana tz from windows - * @param {string} msTZName the timezone name to lookup - * @returns {string|null} the iana name or null of none is found - */ - getIanaTZFromMS (msTZName) { - // Get hash entry - const he = zoneTable[msTZName]; - // If found return iana name, else null - return he ? he.iana[0] : null; - }, - /** * Gets the title from the event. * @param {object} event The event object to check. @@ -754,8 +385,8 @@ const CalendarFetcherUtils = { /** * Determines if the user defined time filter should apply - * @param {Date} now Date object using previously created object for consistency - * @param {Moment} endDate Moment object representing the event end date + * @param {moment.Moment} now Date object using previously created object for consistency + * @param {moment.Moment} endDate Moment object representing the event end date * @param {string} filter The time to subtract from the end date to determine if an event should be shown * @returns {boolean} True if the event should be filtered out, false otherwise */ @@ -766,7 +397,7 @@ const CalendarFetcherUtils = { increment = until[1].slice(-1) === "s" ? until[1] : `${until[1]}s`, // Massage the data for moment js filterUntil = moment(endDate.format()).subtract(value, increment); - return now < filterUntil.toDate(); + return now < filterUntil; } return false; diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index b819d2dc97..2a9845ae18 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -22,6 +22,19 @@ describe("Calendar module", () => { return await loc.count(); }; + /** + * Use this for debugging broken tests, it will console log the text of the calendar module + * @returns {Promise} + */ + const logAllText = async () => { + expect(global.page).not.toBeNull(); + const loc = await global.page.locator(".calendar .event"); + const elem = loc.first(); + await elem.waitFor(); + expect(elem).not.toBeNull(); + console.log(await loc.allInnerTexts()); + }; + const first = 0; const second = 1; const third = 2; @@ -153,19 +166,6 @@ describe("Calendar module", () => { * RRULE TESTS: * Add any tests that check rrule functionality here. */ - describe("sliceMultiDayEvents", () => { - it("Issue #3452 split multiday in Europe", async () => { - await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", [], "Europe/Berlin"); - expect(global.page).not.toBeNull(); - const loc = await global.page.locator(".calendar .event"); - const elem = loc.first(); - await elem.waitFor(); - expect(elem).not.toBeNull(); - const cnt = await loc.count(); - expect(cnt).toBe(6); - }); - }); - describe("sliceMultiDayEvents direct count", () => { it("Issue #3452 split multiday in Europe", async () => { await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", [], "Europe/Berlin"); @@ -197,21 +197,30 @@ describe("Calendar module", () => { describe("berlin late in day event moved, viewed from berlin", () => { it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "Europe/Berlin"); - await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 23:00-00:00", last)).resolves.toBe(true); + await expect(doTestCount()).resolves.toBe(3); + await expect(doTestTableContent(".calendar .event", ".time", "22nd.Oct, 23:00-00:00", first)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "23rd.Oct, 23:00-00:00", second)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 23:00-00:00", third)).resolves.toBe(true); }); }); describe("berlin late in day event moved, viewed from sydney", () => { it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "Australia/Sydney"); - await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 01:00-02:00", last)).resolves.toBe(true); + await expect(doTestCount()).resolves.toBe(3); + await expect(doTestTableContent(".calendar .event", ".time", "23rd.Oct, 08:00-09:00", first)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 08:00-09:00", second)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 08:00-09:00", third)).resolves.toBe(true); }); }); describe("berlin late in day event moved, viewed from chicago", () => { it("Issue #unknown rrule ETC+2 close to timezone edge", async () => { await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", [], "America/Chicago"); - await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 16:00-17:00", last)).resolves.toBe(true); + await expect(doTestCount()).resolves.toBe(3); + await expect(doTestTableContent(".calendar .event", ".time", "22nd.Oct, 16:00-17:00", first)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "23rd.Oct, 16:00-17:00", second)).resolves.toBe(true); + await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 16:00-17:00", third)).resolves.toBe(true); }); }); diff --git a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js index 344e11d576..db8861807d 100644 --- a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js +++ b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js @@ -1,5 +1,8 @@ global.moment = require("moment-timezone"); +const ical = require("node-ical"); +const { expect } = require("playwright/test"); +const moment = require("moment-timezone"); const CalendarFetcherUtils = require("../../../../../modules/default/calendar/calendarfetcherutils"); describe("Calendar fetcher utils test", () => { @@ -49,5 +52,65 @@ describe("Calendar fetcher utils test", () => { expect(filteredEvents[0].title).toBe("ongoingEvent"); expect(filteredEvents[1].title).toBe("upcomingEvent"); }); + + it("should return the correct times when recurring events pass through daylight saving time", () => { + const data = ical.parseICS(`BEGIN:VEVENT +DTSTART;TZID=Europe/Amsterdam:20250311T090000 +DTEND;TZID=Europe/Amsterdam:20250311T091500 +RRULE:FREQ=WEEKLY;BYDAY=FR,MO,TH,TU,WE,SA,SU +DTSTAMP:20250531T091103Z +ORGANIZER;CN=test:mailto:test@test.com +UID:67e65a1d-b889-4451-8cab-5518cecb9c66 +CREATED:20230111T114612Z +DESCRIPTION:Test +LAST-MODIFIED:20250528T071312Z +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:Test +TRANSP:OPAQUE +END:VEVENT`); + + const filteredEvents = CalendarFetcherUtils.filterEvents(data, defaultConfig); + + const januaryFirst = filteredEvents.filter((event) => moment(event.startDate, "x").format("MM-DD") === "01-01"); + const julyFirst = filteredEvents.filter((event) => moment(event.startDate, "x").format("MM-DD") === "07-01"); + + let januaryMoment = moment(`${moment(januaryFirst[0].startDate, "x").format("YYYY")}-01-01T09:00:00`) + .tz("Europe/Amsterdam", true) // Convert to Europe/Amsterdam timezone (see event ical) but keep 9 o'clock + .tz(moment.tz.guess()); // Convert to guessed timezone as that is used in the filterEvents + + let julyMoment = moment(`${moment(julyFirst[0].startDate, "x").format("YYYY")}-07-01T09:00:00`) + .tz("Europe/Amsterdam", true) // Convert to Europe/Amsterdam timezone (see event ical) but keep 9 o'clock + .tz(moment.tz.guess()); // Convert to guessed timezone as that is used in the filterEvents + + expect(januaryFirst[0].startDate).toEqual(januaryMoment.format("x")); + expect(julyFirst[0].startDate).toEqual(julyMoment.format("x")); + }); + + it("should return the correct moments based on the timezone given", () => { + const data = ical.parseICS(`BEGIN:VEVENT +DTSTART;TZID=Europe/Amsterdam:20250311T090000 +DTEND;TZID=Europe/Amsterdam:20250311T091500 +RRULE:FREQ=WEEKLY;BYDAY=FR,MO,TH,TU,WE,SA,SU +DTSTAMP:20250531T091103Z +ORGANIZER;CN=test:mailto:test@test.com +UID:67e65a1d-b889-4451-8cab-5518cecb9c66 +CREATED:20230111T114612Z +DESCRIPTION:Test +LAST-MODIFIED:20250528T071312Z +SEQUENCE:1 +STATUS:CONFIRMED +SUMMARY:Test +TRANSP:OPAQUE +END:VEVENT`); + + const moments = CalendarFetcherUtils.getMomentsFromRecurringEvent(data["67e65a1d-b889-4451-8cab-5518cecb9c66"], moment(), moment().add(365, "days")); + + const januaryFirst = moments.filter((m) => m.format("MM-DD") === "01-01"); + const julyFirst = moments.filter((m) => m.format("MM-DD") === "07-01"); + + expect(januaryFirst[0].toISOString(true)).toContain("09:00:00.000+01:00"); + expect(julyFirst[0].toISOString(true)).toContain("09:00:00.000+02:00"); + }); }); }); From 2194ffd92976c233cd4ee19a2b2d66ece072dc14 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:56:22 +0200 Subject: [PATCH 232/418] [tests] Fix and refactor e2e test "Same keys" in "translations_spec.js" (#3809) While working on the translations (in #3792 and #3794) I realised that the e2e "Same keys" tests were not working entirely. There was also a TODO entry for this in the test, as well as a try-catch-block workaround. I therefore fixed and refactored it. I also sorted the translations in `translations/translations.js`, so that the test outputs are alphabetically. --- CHANGELOG.md | 1 + tests/e2e/translations_spec.js | 106 +++++++++++++++++---------------- translations/translations.js | 62 +++++++++---------- 3 files changed, 86 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac1ffbb4fe..431f60dde2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ planned for 2025-07-01 - [calendar] fix fullday event rrule until with timezone offset (#3781) - [feat] Add rule `no-undef` in config file validation to fix #3785 (#3786) - [fonts] Fix `roboto.css` to avoid error message `Unknown descriptor 'var(' in @font-face rule.` in firefox console (#3787) +- [tests] Fix and refactor e2e test `Same keys` in `translations_spec.js` (#3809) ### Updated diff --git a/tests/e2e/translations_spec.js b/tests/e2e/translations_spec.js index 07a99e218c..4f7f01a3a5 100644 --- a/tests/e2e/translations_spec.js +++ b/tests/e2e/translations_spec.js @@ -154,77 +154,79 @@ describe("Translations", () => { describe("Same keys", () => { let base; - let missing = []; - beforeAll(() => { - return new Promise((done) => { - const dom = new JSDOM( - `\ - \ - \ - \ - `, - { runScripts: "dangerously", resources: "usable" } - ); + // Create a new JSDOM instance for each test + dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" }); + + // Mock the necessary global objects + dom.window.Log = { log: jest.fn(), error: jest.fn() }; + dom.window.Translator = {}; + dom.window.config = { language: "de" }; + + // Load class.js and module.js content directly + const classJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "class.js"), "utf-8"); + const moduleJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "module.js"), "utf-8"); + + // Execute the scripts in the JSDOM context + dom.window.eval(classJs); + dom.window.eval(moduleJs); }); - it("should load translation file", () => { - return new Promise((done) => { - dom.window.onload = async () => { - const { Translator, Module, config } = dom.window; - config.language = "en"; - Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); + it("should load translation file", async () => { + await new Promise((resolve) => { + dom.window.onload = resolve; + }); - Module.register("name", { getTranslations: () => translations }); - const MMM = Module.create("name"); + const { Translator, Module, config } = dom.window; + config.language = "en"; + Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); - await MMM.loadTranslations(); + Module.register("name", { getTranslations: () => translations }); + const MMM = Module.create("name"); - expect(Translator.load.args).toHaveLength(1); - expect(Translator.load.calledWith(MMM, "translations/en.json", false)).toBe(true); + await MMM.loadTranslations(); - done(); - }; - }); + expect(Translator.load.args).toHaveLength(1); + expect(Translator.load.calledWith(MMM, "translations/en.json", false)).toBe(true); }); - it("should load translation + fallback file", () => { - return new Promise((done) => { - dom.window.onload = async () => { - const { Translator, Module } = dom.window; - Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); + it("should load translation + fallback file", async () => { + await new Promise((resolve) => { + dom.window.onload = resolve; + }); - Module.register("name", { getTranslations: () => translations }); - const MMM = Module.create("name"); + const { Translator, Module } = dom.window; + Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); - await MMM.loadTranslations(); + Module.register("name", { getTranslations: () => translations }); + const MMM = Module.create("name"); - expect(Translator.load.args).toHaveLength(2); - expect(Translator.load.calledWith(MMM, "translations/de.json", false)).toBe(true); - expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true); + await MMM.loadTranslations(); - done(); - }; - }); + expect(Translator.load.args).toHaveLength(2); + expect(Translator.load.calledWith(MMM, "translations/de.json", false)).toBe(true); + expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true); }); - it("should load translation fallback file", () => { - return new Promise((done) => { - dom.window.onload = async () => { - const { Translator, Module, config } = dom.window; - config.language = "--"; - Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); + it("should load translation fallback file", async () => { + await new Promise((resolve) => { + dom.window.onload = resolve; + }); - Module.register("name", { getTranslations: () => translations }); - const MMM = Module.create("name"); + const { Translator, Module, config } = dom.window; + config.language = "--"; + Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); - await MMM.loadTranslations(); + Module.register("name", { getTranslations: () => translations }); + const MMM = Module.create("name"); - expect(Translator.load.args).toHaveLength(1); - expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true); + await MMM.loadTranslations(); - done(); - }; - }); + expect(Translator.load.args).toHaveLength(1); + expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true); }); - it("should load no file", () => { - return new Promise((done) => { - dom.window.onload = async () => { - const { Translator, Module } = dom.window; - Translator.load = sinon.stub(); + it("should load no file", async () => { + await new Promise((resolve) => { + dom.window.onload = resolve; + }); - Module.register("name", {}); - const MMM = Module.create("name"); + const { Translator, Module } = dom.window; + Translator.load = sinon.stub(); - await MMM.loadTranslations(); + Module.register("name", {}); + const MMM = Module.create("name"); - expect(Translator.load.callCount).toBe(0); + await MMM.loadTranslations(); - done(); - }; - }); + expect(Translator.load.callCount).toBe(0); }); }); @@ -130,29 +132,30 @@ describe("Translations", () => { } }; - describe("Parsing language files through the Translator class", () => { - for (let language in translations) { - it(`should parse ${language}`, () => { - return new Promise((done) => { - const dom = new JSDOM( - `\ - \ - \ - \ - \ - - - + + diff --git a/jest.config.js b/jest.config.js index ee51664fc9..bb4942cf4b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -31,7 +31,7 @@ const config = { collectCoverageFrom: [ "/clientonly/**/*.js", "/js/**/*.js", - "/modules/default/**/*.js", + "/defaultmodules/**/*.js", "/serveronly/**/*.js" ], coverageReporters: ["lcov", "text"], diff --git a/js/app.js b/js/app.js index 85baed381f..a67bf1b8cd 100644 --- a/js/app.js +++ b/js/app.js @@ -13,7 +13,6 @@ global.root_path = path.resolve(`${__dirname}/../`); const Server = require(`${__dirname}/server`); const Utils = require(`${__dirname}/utils`); -const defaultModules = require(`${global.root_path}/modules/default/defaultmodules`); // used to control fetch timeout for node_helpers const { setGlobalDispatcher, Agent } = require("undici"); const { getEnvVarsAsObj, getConfigFilePath } = require("#server_functions"); @@ -57,6 +56,7 @@ process.on("uncaughtException", function (err) { function App () { let nodeHelpers = []; let httpServer; + let defaultModules; /** * Loads the config file. Combines it with the defaults and returns the config @@ -185,7 +185,7 @@ function App () { let moduleFolder = path.resolve(`${global.root_path}/${env.modulesDir}`, module); if (defaultModules.includes(moduleName)) { - const defaultModuleFolder = path.resolve(`${global.root_path}/modules/default/`, module); + const defaultModuleFolder = path.resolve(`${global.root_path}/${global.defaultModulesDir}/`, module); if (!global.mmTestMode) { moduleFolder = defaultModuleFolder; } else { @@ -291,6 +291,9 @@ function App () { this.start = async function () { config = await loadConfig(); + global.defaultModulesDir = config.defaultModulesDir; + defaultModules = require(`${global.root_path}/${global.defaultModulesDir}/defaultmodules`); + Log.setLogLevel(config.logLevel); // get the used module positions diff --git a/js/defaults.js b/js/defaults.js index 469a172b37..88a706d7e4 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -20,6 +20,7 @@ const defaults = { zoom: 1, customCss: "css/custom.css", foreignModulesDir: "modules", + defaultModulesDir: "defaultmodules", // httpHeaders used by helmet, see https://helmetjs.github.io/. You can add other/more object values by overriding this in config.js, // e.g. you need to add `frameguard: false` for embedding MagicMirror in another website, see https://github.com/MagicMirrorOrg/MagicMirror/issues/2847 httpHeaders: { contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false }, diff --git a/js/loader.js b/js/loader.js index b3cfd71910..dac0b5f56b 100644 --- a/js/loader.js +++ b/js/loader.js @@ -17,6 +17,7 @@ const Loader = (function () { const getEnvVarsFromConfig = function () { return { modulesDir: config.foreignModulesDir || "modules", + defaultModulesDir: config.defaultModulesDir || "defaultmodules", customCss: config.customCss || "css/custom.css" }; }; @@ -103,7 +104,7 @@ const Loader = (function () { let moduleFolder = `${envVars.modulesDir}/${module}`; if (defaultModules.indexOf(moduleName) !== -1) { - const defaultModuleFolder = `modules/default/${module}`; + const defaultModuleFolder = `${envVars.defaultModulesDir}/${module}`; if (window.name !== "jsdom") { moduleFolder = defaultModuleFolder; } else { diff --git a/js/server.js b/js/server.js index 2caaad60f7..e96a6cc862 100644 --- a/js/server.js +++ b/js/server.js @@ -89,7 +89,7 @@ function Server (config) { app.use(helmet(config.httpHeaders)); app.use("/js", express.static(__dirname)); - let directories = ["/config", "/css", "/favicon.svg", "/modules", "/node_modules/animate.css", "/node_modules/@fontsource", "/node_modules/@fortawesome", "/translations", "/tests/configs", "/tests/mocks"]; + 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)) { const dirArr = value.split("/"); if (dirArr[0] === "node_modules") directories.push(`/${dirArr[0]}/${dirArr[1]}`); diff --git a/js/server_functions.js b/js/server_functions.js index a7eba8c358..aedf6fa43c 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -162,7 +162,7 @@ function getUserAgent () { * @returns {object} environment variables key: values */ function getEnvVarsAsObj () { - const obj = { modulesDir: `${config.foreignModulesDir}`, customCss: `${config.customCss}` }; + const obj = { modulesDir: `${config.foreignModulesDir}`, defaultModulesDir: `${config.defaultModulesDir}`, customCss: `${config.customCss}` }; if (process.env.MM_MODULES_DIR) { obj.modulesDir = process.env.MM_MODULES_DIR.replace(`${global.root_path}/`, ""); } diff --git a/modules/.gitkeep b/modules/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package.json b/package.json index e2eaa69597..9af69d78f2 100644 --- a/package.json +++ b/package.json @@ -40,10 +40,10 @@ "main": "js/electron.js", "scripts": { "config:check": "node js/check_config.js", - "postinstall": "git clean -df fonts vendor", + "postinstall": "git clean -df fonts vendor modules/default", "install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev", "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier && npx playwright install chromium", - "lint:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'modules/default/**/*.css' --fix", + "lint:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'defaultmodules/**/*.css' --fix", "lint:js": "eslint --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", @@ -59,9 +59,9 @@ "start:x11": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js", "start:x11:dev": "node --run start:x11 -- dev", "test": "vitest run", - "test:calendar": "node ./modules/default/calendar/debug.js", + "test:calendar": "node ./defaultmodules/calendar/debug.js", "test:coverage": "vitest run --coverage", - "test:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'modules/default/**/*.css'", + "test:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'defaultmodules/**/*.css'", "test:e2e": "vitest run tests/e2e", "test:electron": "vitest run tests/electron", "test:js": "eslint", diff --git a/tests/e2e/modules/newsfeed_spec.js b/tests/e2e/modules/newsfeed_spec.js index 4cee4a75b4..4a86d4af24 100644 --- a/tests/e2e/modules/newsfeed_spec.js +++ b/tests/e2e/modules/newsfeed_spec.js @@ -80,7 +80,7 @@ describe("Newsfeed module", () => { describe("Newsfeed module located in config directory", () => { beforeAll(() => { - fs.cpSync(`${global.root_path}/modules/default/newsfeed`, `${global.root_path}/config/newsfeed`, { recursive: true }); + fs.cpSync(`${global.root_path}/${global.defaultModulesDir}/newsfeed`, `${global.root_path}/config/newsfeed`, { recursive: true }); process.env.MM_MODULES_DIR = "config"; }); diff --git a/tests/unit/functions/updatenotification_spec.js b/tests/unit/functions/updatenotification_spec.js index ebf7580b81..09b39b18cb 100644 --- a/tests/unit/functions/updatenotification_spec.js +++ b/tests/unit/functions/updatenotification_spec.js @@ -19,7 +19,8 @@ async function createGitHelper (fsStatSyncMockRef, loggerMockRef, execShellSpyRe vi.doMock("logger", () => loggerMockRef.current); - const gitHelperModule = await import("../../../modules/default/updatenotification/git_helper"); + const defaults = await import("../../../js/defaults"); + const gitHelperModule = await import(`../../../${defaults.defaultModulesDir}/updatenotification/git_helper`); const GitHelper = gitHelperModule.default || gitHelperModule; const instance = new GitHelper(); execShellSpyRef.current = vi.spyOn(instance, "execShell"); diff --git a/tests/unit/global_vars/defaults_modules_spec.js b/tests/unit/global_vars/defaults_modules_spec.js index 465e2232d0..993dcb63ee 100644 --- a/tests/unit/global_vars/defaults_modules_spec.js +++ b/tests/unit/global_vars/defaults_modules_spec.js @@ -1,14 +1,15 @@ const fs = require("node:fs"); const path = require("node:path"); +const defaults = require("../../../js/defaults"); const root_path = path.join(__dirname, "../../.."); -describe("Default modules set in modules/default/defaultmodules.js", () => { - const expectedDefaultModules = require(`${root_path}/modules/default/defaultmodules`); +describe("Default modules set in defaultmodules/defaultmodules.js", () => { + const expectedDefaultModules = require(`${root_path}/${defaults.defaultModulesDir}/defaultmodules`); for (const defaultModule of expectedDefaultModules) { - it(`contains a folder for modules/default/${defaultModule}"`, () => { - expect(fs.existsSync(path.join(root_path, "modules/default", defaultModule))).toBe(true); + it(`contains a folder for defaultmodules/${defaultModule}"`, () => { + expect(fs.existsSync(path.join(root_path, "defaultmodules", defaultModule))).toBe(true); }); } }); diff --git a/tests/unit/modules/default/calendar/calendar_fetcher_utils_bad_rrule.js b/tests/unit/modules/default/calendar/calendar_fetcher_utils_bad_rrule.js index 4475c65c26..6b4a8dc651 100644 --- a/tests/unit/modules/default/calendar/calendar_fetcher_utils_bad_rrule.js +++ b/tests/unit/modules/default/calendar/calendar_fetcher_utils_bad_rrule.js @@ -1,6 +1,8 @@ global.moment = require("moment-timezone"); -const CalendarFetcherUtils = require("../../../../../modules/default/calendar/calendarfetcherutils"); +const defaults = require("../../../js/defaults"); + +const CalendarFetcherUtils = require(`../../../../../${defaults.defaultModulesDir}/calendar/calendarfetcherutils`); describe("Calendar fetcher utils test", () => { const defaultConfig = { diff --git a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js index 8f5ab5bc67..31a179a520 100644 --- a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js +++ b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js @@ -2,7 +2,9 @@ global.moment = require("moment-timezone"); const ical = require("node-ical"); const moment = require("moment-timezone"); -const CalendarFetcherUtils = require("../../../../../modules/default/calendar/calendarfetcherutils"); +const defaults = require("../../../../../js/defaults"); + +const CalendarFetcherUtils = require(`../../../../../${defaults.defaultModulesDir}/calendar/calendarfetcherutils`); describe("Calendar fetcher utils test", () => { const defaultConfig = { diff --git a/tests/unit/modules/default/calendar/calendar_utils_spec.js b/tests/unit/modules/default/calendar/calendar_utils_spec.js index ff37299fe9..77d358ddfa 100644 --- a/tests/unit/modules/default/calendar/calendar_utils_spec.js +++ b/tests/unit/modules/default/calendar/calendar_utils_spec.js @@ -1,6 +1,8 @@ global.moment = require("moment"); -const CalendarUtils = require("../../../../../modules/default/calendar/calendarutils"); +const defaults = require("../../../../../js/defaults"); + +const CalendarUtils = require(`../../../../../${defaults.defaultModulesDir}/calendar/calendarutils`); describe("Calendar utils tests", () => { describe("capFirst", () => { diff --git a/tests/unit/modules/default/compliments/compliments_spec.js b/tests/unit/modules/default/compliments/compliments_spec.js index 8d3aef3011..c1b76fcc09 100644 --- a/tests/unit/modules/default/compliments/compliments_spec.js +++ b/tests/unit/modules/default/compliments/compliments_spec.js @@ -16,12 +16,13 @@ describe("Compliments module", () => { global.Cron = vi.fn(); // Load the module - require("../../../../../modules/default/compliments/compliments"); + const defaults = require("../../../../../js/defaults"); + require(`../../../../../${defaults.defaultModulesDir}/compliments/compliments`); // Setup module instance complimentsModule.config = { ...complimentsModule.defaults }; complimentsModule.name = "compliments"; - complimentsModule.file = vi.fn((path) => `http://localhost:8080/modules/default/compliments/${path}`); + complimentsModule.file = vi.fn((path) => `http://localhost:8080/${defaults.defaultModulesDir}/compliments/${path}`); }); afterEach(() => { @@ -144,7 +145,7 @@ describe("Compliments module", () => { await complimentsModule.loadComplimentFile(); const calledUrl = fetch.mock.calls[0][0]; - expect(calledUrl).toBe("http://localhost:8080/modules/default/compliments/compliments.json"); + expect(calledUrl).toBe("http://localhost:8080/defaultmodules/compliments/compliments.json"); expect(calledUrl).not.toContain("dummy="); }); }); diff --git a/tests/unit/modules/default/utils_spec.js b/tests/unit/modules/default/utils_spec.js index 9677f3df20..4af7db6765 100644 --- a/tests/unit/modules/default/utils_spec.js +++ b/tests/unit/modules/default/utils_spec.js @@ -1,5 +1,7 @@ global.moment = require("moment-timezone"); -const { performWebRequest, formatTime } = require("../../../../modules/default/utils"); +const defaults = require("../../../../js/defaults"); + +const { performWebRequest, formatTime } = require(`../../../../${defaults.defaultModulesDir}/utils`); describe("Default modules utils tests", () => { describe("performWebRequest", () => { diff --git a/tests/unit/modules/default/weather/weather_object_spec.js b/tests/unit/modules/default/weather/weather_object_spec.js index 2bc87d78e3..cef65bfe4e 100644 --- a/tests/unit/modules/default/weather/weather_object_spec.js +++ b/tests/unit/modules/default/weather/weather_object_spec.js @@ -1,4 +1,6 @@ -const WeatherObject = require("../../../../../modules/default/weather/weatherobject"); +const defaults = require("../../../../../js/defaults"); + +const WeatherObject = require(`../../../../../${defaults.defaultModulesDir}/weather/weatherobject`); global.moment = require("moment-timezone"); global.SunCalc = require("suncalc"); diff --git a/tests/unit/modules/default/weather/weather_utils_spec.js b/tests/unit/modules/default/weather/weather_utils_spec.js index da3979cdb7..5f21121994 100644 --- a/tests/unit/modules/default/weather/weather_utils_spec.js +++ b/tests/unit/modules/default/weather/weather_utils_spec.js @@ -1,5 +1,7 @@ -const weather = require("../../../../../modules/default/weather/weatherutils"); -const WeatherUtils = require("../../../../../modules/default/weather/weatherutils"); +const defaults = require("../../../../../js/defaults"); + +const weather = require(`../../../../../${defaults.defaultModulesDir}/weather/weatherutils`); +const WeatherUtils = require(`../../../../../${defaults.defaultModulesDir}/weather/weatherutils`); describe("Weather utils tests", () => { describe("temperature conversion to imperial", () => { diff --git a/vitest.config.mjs b/vitest.config.mjs index 83d857ccf0..75808c82fc 100644 --- a/vitest.config.mjs +++ b/vitest.config.mjs @@ -45,7 +45,7 @@ export default defineConfig({ setupFiles: ["./tests/utils/vitest-setup.js"], include: [ "tests/unit/**/*_spec.js", - "tests/unit/modules/default/calendar/calendar_fetcher_utils_bad_rrule.js" + "tests/unit/defaultmodules/calendar/calendar_fetcher_utils_bad_rrule.js" ], testTimeout: 20000, hookTimeout: 10000 @@ -82,7 +82,7 @@ export default defineConfig({ include: [ "clientonly/**/*.js", "js/**/*.js", - "modules/default/**/*.js", + "defaultmodules/**/*.js", "serveronly/**/*.js" ], exclude: [ From 43503e8fff3715300d54266853da1fb9a848da00 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:31:35 +0100 Subject: [PATCH 354/418] chore: update dependencies (#4021) This includes a new version of `node-ical` which should resolve a calendar issue that was reported [here](https://github.com/MagicMirrorOrg/MagicMirror/pull/4016#issuecomment-3787073856) and [here](https://github.com/MagicMirrorOrg/MagicMirror/pull/4010#issuecomment-3798857137). --- package-lock.json | 652 +++++++++++++++++++++++----------------------- package.json | 12 +- 2 files changed, 339 insertions(+), 325 deletions(-) diff --git a/package-lock.json b/package-lock.json index b55ab00fd7..85df3d0c03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,13 +27,13 @@ "ipaddr.js": "^2.3.0", "moment": "^2.30.1", "moment-timezone": "^0.6.0", - "node-ical": "^0.23.1", + "node-ical": "^0.24.0", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.30.5", - "undici": "^7.19.0", + "systeminformation": "^5.30.6", + "undici": "^7.19.1", "weathericons": "^2.1.0" }, "devDependencies": { @@ -41,11 +41,11 @@ "@vitest/coverage-v8": "^4.0.18", "@vitest/eslint-plugin": "^1.6.6", "@vitest/ui": "^4.0.18", - "cspell": "^9.6.0", + "cspell": "^9.6.2", "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-jsdoc": "^62.4.0", + "eslint-plugin-jsdoc": "^62.4.1", "eslint-plugin-package-json": "^0.88.2", - "eslint-plugin-playwright": "^2.5.0", + "eslint-plugin-playwright": "^2.5.1", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jsdom": "^27.4.0", @@ -260,9 +260,9 @@ } }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.6.0.tgz", - "integrity": "sha512-gLNe9bB+5gMsTEhR9YPE0Wt122HR2EV+Q1j9W+MbwbeBJmpTWrgAP1ZdpvHOg+6LF6x/bD/EC9HfWdd/om8wXA==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.6.2.tgz", + "integrity": "sha512-s5u/3nhQUftKibPIbRLLAf4M5JG1NykqkPCxS0STMmri0hzVMZbAOCyHjdLoOCqPUn0xZzLA8fgeYg3b7QuHpg==", "dev": true, "license": "MIT", "dependencies": { @@ -282,15 +282,15 @@ "@cspell/dict-dotnet": "^5.0.11", "@cspell/dict-elixir": "^4.0.8", "@cspell/dict-en_us": "^4.4.27", - "@cspell/dict-en-common-misspellings": "^2.1.11", + "@cspell/dict-en-common-misspellings": "^2.1.12", "@cspell/dict-en-gb-mit": "^3.1.16", "@cspell/dict-filetypes": "^3.0.15", "@cspell/dict-flutter": "^1.1.1", "@cspell/dict-fonts": "^4.0.5", "@cspell/dict-fsharp": "^1.1.1", - "@cspell/dict-fullstack": "^3.2.7", + "@cspell/dict-fullstack": "^3.2.8", "@cspell/dict-gaming-terms": "^1.1.2", - "@cspell/dict-git": "^3.0.7", + "@cspell/dict-git": "^3.1.0", "@cspell/dict-golang": "^6.0.26", "@cspell/dict-google": "^1.0.9", "@cspell/dict-haskell": "^4.0.6", @@ -300,14 +300,14 @@ "@cspell/dict-julia": "^1.1.1", "@cspell/dict-k8s": "^1.0.12", "@cspell/dict-kotlin": "^1.1.1", - "@cspell/dict-latex": "^4.0.4", + "@cspell/dict-latex": "^5.0.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-monkeyc": "^1.0.12", - "@cspell/dict-node": "^5.0.8", - "@cspell/dict-npm": "^5.2.29", + "@cspell/dict-node": "^5.0.9", + "@cspell/dict-npm": "^5.2.31", "@cspell/dict-php": "^4.1.1", "@cspell/dict-powershell": "^5.0.15", "@cspell/dict-public-licenses": "^2.0.15", @@ -331,22 +331,32 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.6.0.tgz", - "integrity": "sha512-5sY1lgAXS5xEOsjT5rREMADj7pHIt56XOL7xR80nNl0TwlpZbeBHhoB2aH5sirVTeodJFN5iraXNbVOYPPupPw==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.6.2.tgz", + "integrity": "sha512-8TCD7KOG9ppo5BoJOe2diACfB6I6UpJmYmjLOxMy0o8y3ruWFoDKaDEsf5tIi4T7cdVb8MjGbHjw9ksCwRRMjA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.6.0" + "@cspell/cspell-types": "9.6.2" }, "engines": { "node": ">=20" } }, + "node_modules/@cspell/cspell-performance-monitor": { + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-performance-monitor/-/cspell-performance-monitor-9.6.2.tgz", + "integrity": "sha512-MZuhYy59zFCVsX3PzW02/3TqPsPw87MELOJuZfpWDcGgxrweTrVjMdmJ0/w7COJ6zEAqtgGjNMAEmK4xJnrQjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18" + } + }, "node_modules/@cspell/cspell-pipe": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.6.0.tgz", - "integrity": "sha512-YNuY8NNXfE+8Qzknm2ps6QbrZLZu6rSZTZr3dYW3K6TK7+IFVlJ6e2Z9iKJTqp6aZ4AGU/r9QYGmNX4Oq4gZ0A==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.6.2.tgz", + "integrity": "sha512-Wt6Cf4b/E0QJ/TkbOMjXSGrccASgbc8xZq3c+8+kCXM5JT92NP2Lx67m3UA1g+BDv7E4DNPuwm1fM7o/2zum5w==", "dev": true, "license": "MIT", "engines": { @@ -354,9 +364,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.6.0.tgz", - "integrity": "sha512-Gb2UWNmRpTOQGpYL4Q/LMw+b50KcRZcf/wJg6w0Yl3IT+F/uDNhNh1f5rHuTyGsbMsMxHJhsb2AoP+73GlbIfw==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.6.2.tgz", + "integrity": "sha512-u7P4ErApEcSP+Si2HaeotFQXjuCopAa+wPF1fDzuJzpotPxsDwNDanGGn2qUMjOyVI4UiI84MPI6ZuGLj5EDyQ==", "dev": true, "license": "MIT", "dependencies": { @@ -367,9 +377,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.6.0.tgz", - "integrity": "sha512-DCuKKkySTEB8MPLTdoPMdmakYcx7XCsHz1YEMbzOcLqJCxXsRlRZg4qE9kRBee/2QY7eYA2kaYNgn/TDMooa4g==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.6.2.tgz", + "integrity": "sha512-T4LBWe3NYpKPD/fIkYAL56z5pr8Cgh//UZDl4afDTJNuTkdE6ZL93MBAUXggONHqY8B9dRXlQKrD4PD+kHabtw==", "dev": true, "license": "MIT", "engines": { @@ -377,15 +387,28 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.6.0.tgz", - "integrity": "sha512-JTqrD47tV+rWc1y2W8T0NTfWLQMlSWX4OF64/Jf3WbsOD+4UXVIfjRlzPry7+1Zekm6pa38+23jkDBytYpu8yw==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.6.2.tgz", + "integrity": "sha512-RsUFrSB0oQHEBnR8yarKIReUPwSu2ROpbjhdVKi4T/nQhMaS+TnIQPBwkMtb2r8A1KS2Hijw4D/4bV/XHoFQWw==", "dev": true, "license": "MIT", "engines": { "node": ">=20" } }, + "node_modules/@cspell/cspell-worker": { + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-worker/-/cspell-worker-9.6.2.tgz", + "integrity": "sha512-1xq8jmt6YZ7MVPESydjYJ3p67vi+YWgi5qow1xyZzeQWFXVCCFi9pQSxC0bzGQwWrYGNWSAIbYZB3Sq5ntYz4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cspell-lib": "9.6.2" + }, + "engines": { + "node": ">=20.18" + } + }, "node_modules/@cspell/dict-ada": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.1.1.tgz", @@ -502,9 +525,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.1.11.tgz", - "integrity": "sha512-2jcY494If1udvzd7MT2z/QH/RACUo/I02vIY4ttNdZhgYvUmRKhg8OBdrbzYo0lJOcc7XUb8rhIFQRHzxOSVeA==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.1.12.tgz", + "integrity": "sha512-14Eu6QGqyksqOd4fYPuRb58lK1Va7FQK9XxFsRKnZU8LhL3N+kj7YKDW+7aIaAN/0WGEqslGP6lGbQzNti8Akw==", "dev": true, "license": "CC BY-SA 4.0" }, @@ -544,9 +567,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-fullstack": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.7.tgz", - "integrity": "sha512-IxEk2YAwAJKYCUEgEeOg3QvTL4XLlyArJElFuMQevU1dPgHgzWElFevN5lsTFnvMFA1riYsVinqJJX0BanCFEg==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.8.tgz", + "integrity": "sha512-J6EeoeThvx/DFrcA2rJiCA6vfqwJMbkG0IcXhlsmRZmasIpanmxgt90OEaUazbZahFiuJT8wrhgQ1QgD1MsqBw==", "dev": true, "license": "MIT" }, @@ -558,9 +581,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-git": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.7.tgz", - "integrity": "sha512-odOwVKgfxCQfiSb+nblQZc4ErXmnWEnv8XwkaI4sNJ7cNmojnvogYVeMqkXPjvfrgEcizEEA4URRD2Ms5PDk1w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.1.0.tgz", + "integrity": "sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ==", "dev": true, "license": "MIT" }, @@ -628,9 +651,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-latex": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.4.tgz", - "integrity": "sha512-YdTQhnTINEEm/LZgTzr9Voz4mzdOXH7YX+bSFs3hnkUHCUUtX/mhKgf1CFvZ0YNM2afjhQcmLaR9bDQVyYBvpA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-5.0.0.tgz", + "integrity": "sha512-HUrIqUVohM6P0+5b7BsdAdb0STIv0aaFBvguI7pLcreljlcX3FSPUxea7ticzNlCNeVrEaiEn/ws9m6rYUeuNw==", "dev": true, "license": "MIT" }, @@ -676,16 +699,16 @@ "license": "MIT" }, "node_modules/@cspell/dict-node": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.8.tgz", - "integrity": "sha512-AirZcN2i84ynev3p2/1NCPEhnNsHKMz9zciTngGoqpdItUb2bDt1nJBjwlsrFI78GZRph/VaqTVFwYikmncpXg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.9.tgz", + "integrity": "sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.29", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.29.tgz", - "integrity": "sha512-ZAef8JpYmbuHFT1zekj/YyImLPvZevjECw663EmG5GPePyNo4AfH8Dd2fFhaOyQ3P5I5LrkAhGwypnOfUxcssw==", + "version": "5.2.31", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.31.tgz", + "integrity": "sha512-+HoFoFe53pL0wDuSHRs5L+CcDMaG5sLfjKLPT4H0VdwNzho3HLOohTCZr6cYt7OEbXf3xi4YXBkamCy38xOpjA==", "dev": true, "license": "MIT" }, @@ -812,13 +835,13 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.6.0.tgz", - "integrity": "sha512-Lkn82wyGj2ltxeYfH2bEjshdes1fx3ouYUZxeW5i6SBBvEVJoSmr43AygI8A317UMIQxVj59qVBorrtGYcRI1w==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.6.2.tgz", + "integrity": "sha512-DY/X6lsdK4aeJ4erPVZoU1ccEXqtnYqWCMUXZOsMeIsZlXwZz/ocNNd09A4ga9IzGj1lYsB13UG4GVe8lSMAXQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.6.0", + "@cspell/url": "9.6.2", "import-meta-resolve": "^4.2.0" }, "engines": { @@ -826,9 +849,9 @@ } }, "node_modules/@cspell/filetypes": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.6.0.tgz", - "integrity": "sha512-CaWyk5j20H6sr+HCArtUY95jUQb7A/6W0GC4B4umnqoWvgqwR72duowLFa+w1K2C7tZg3GoV4Wf2cUn9jjt5FA==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.6.2.tgz", + "integrity": "sha512-XYAuGZoRCUf4Y12YP+K0BpU3QUMj4Z4SkKpi08Dwx/bQlq/NqycHKkUWYhlViHLav1+MJbWxcvDIHxGNv0UIaA==", "dev": true, "license": "MIT", "engines": { @@ -836,9 +859,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.6.0.tgz", - "integrity": "sha512-9g8LCLv/2RrprGeGnFAaBETWq7ESnBcoMbvgNu+vZE58iF+pbFvP0qGgKvVeKEEpc2LZhNuHLsUH37MUS6DOQg==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.6.2.tgz", + "integrity": "sha512-7zpnLkpT91wsH4aU3oAprnzrURvBWKq97j5i/SWXGuNKf36XNEO4HaeaPp6L2oVq4OzdUOdm0tUK1gB0HhMWSg==", "dev": true, "license": "MIT", "engines": { @@ -846,9 +869,9 @@ } }, "node_modules/@cspell/url": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.6.0.tgz", - "integrity": "sha512-257WOxh9vOYHAVgBNXRCdLEd+ldzlVbzcc9u+6DYoCDCNGe0OvOWOGsAfnUbMc9xEw48XgBlDYgOlPbjWGLOTg==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.6.2.tgz", + "integrity": "sha512-625EiP1jUOQZ6UQuTUV1XB8Bxa18z3EtC1qA6PJyM3TqUD8PD8Tz183j9av6d/Dq52+7w0F4ovuqjUcTXTfD6g==", "dev": true, "license": "MIT", "engines": { @@ -951,9 +974,9 @@ } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.25.tgz", - "integrity": "sha512-g0Kw9W3vjx5BEBAF8c5Fm2NcB/Fs8jJXh85aXqwEXiL+tqtOut07TWgyaGzAAfTM+gKckrrncyeGEZPcaRgm2Q==", + "version": "1.0.26", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.26.tgz", + "integrity": "sha512-6boXK0KkzT5u5xOgF6TKB+CLq9SOpEGmkZw0g5n9/7yg85wab3UzSxB8TxhLJ31L4SGJ6BCFRw/iftTha1CJXA==", "dev": true, "funding": [ { @@ -965,10 +988,7 @@ "url": "https://opencollective.com/csstools" } ], - "license": "MIT-0", - "engines": { - "node": ">=18" - } + "license": "MIT-0" }, "node_modules/@csstools/css-tokenizer": { "version": "3.0.4", @@ -1137,15 +1157,15 @@ "optional": true }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.82.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.82.0.tgz", - "integrity": "sha512-xs3OTxPefjTZaoDS7H1X2pV33enAmZg+8YldjmeYk7XZnq420phdnp6o0JtrsHBdSRJ5+RTocgyED9TL3epgpw==", + "version": "0.83.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.83.0.tgz", + "integrity": "sha512-e1MHSEPJ4m35zkBvNT6kcdeH1SvMaJDsPC3Xhfseg3hvF50FUE3f46Yn36jgbrPYYXezlWUQnevv23c+lx2MCA==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.53.1", - "comment-parser": "1.4.4", + "comment-parser": "1.4.5", "esquery": "^1.7.0", "jsdoc-type-pratt-parser": "~7.1.0" }, @@ -1153,16 +1173,6 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@es-joy/jsdoccomment/node_modules/comment-parser": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.4.tgz", - "integrity": "sha512-0D6qSQ5IkeRrGJFHRClzaMOenMeT0gErz3zIw3AprKMqhRN6LNU2jQOdkPG/FZ+8bCgXE1VidrgSzlBBDZRr8A==", - "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", @@ -1816,9 +1826,9 @@ } }, "node_modules/@exodus/bytes": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.9.0.tgz", - "integrity": "sha512-lagqsvnk09NKogQaN/XrtlWeUF8SRhT12odMvbTIIaVObqzwAogL6jhR4DAp0gPuKoM1AOVrKUshJpRdpMFrww==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.10.0.tgz", + "integrity": "sha512-tf8YdcbirXdPnJ+Nd4UN1EXnz+IP2DI45YVEr3vvzcVTOyrApkmIB4zvOQVd3XPr7RXnfBtAx+PXImXOIU0Ajg==", "dev": true, "license": "MIT", "engines": { @@ -2486,9 +2496,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz", - "integrity": "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.0.tgz", + "integrity": "sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA==", "cpu": [ "arm" ], @@ -2500,9 +2510,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz", - "integrity": "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.0.tgz", + "integrity": "sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg==", "cpu": [ "arm64" ], @@ -2514,9 +2524,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz", - "integrity": "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.0.tgz", + "integrity": "sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg==", "cpu": [ "arm64" ], @@ -2528,9 +2538,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz", - "integrity": "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.0.tgz", + "integrity": "sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA==", "cpu": [ "x64" ], @@ -2542,9 +2552,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz", - "integrity": "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.0.tgz", + "integrity": "sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g==", "cpu": [ "arm64" ], @@ -2556,9 +2566,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz", - "integrity": "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.0.tgz", + "integrity": "sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA==", "cpu": [ "x64" ], @@ -2570,9 +2580,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz", - "integrity": "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.0.tgz", + "integrity": "sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q==", "cpu": [ "arm" ], @@ -2584,9 +2594,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz", - "integrity": "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.0.tgz", + "integrity": "sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA==", "cpu": [ "arm" ], @@ -2598,9 +2608,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz", - "integrity": "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.0.tgz", + "integrity": "sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw==", "cpu": [ "arm64" ], @@ -2612,9 +2622,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz", - "integrity": "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.0.tgz", + "integrity": "sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw==", "cpu": [ "arm64" ], @@ -2626,9 +2636,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz", - "integrity": "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.0.tgz", + "integrity": "sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q==", "cpu": [ "loong64" ], @@ -2640,9 +2650,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz", - "integrity": "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.0.tgz", + "integrity": "sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ==", "cpu": [ "loong64" ], @@ -2654,9 +2664,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz", - "integrity": "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.0.tgz", + "integrity": "sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ==", "cpu": [ "ppc64" ], @@ -2668,9 +2678,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz", - "integrity": "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.0.tgz", + "integrity": "sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA==", "cpu": [ "ppc64" ], @@ -2682,9 +2692,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz", - "integrity": "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.0.tgz", + "integrity": "sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ==", "cpu": [ "riscv64" ], @@ -2696,9 +2706,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz", - "integrity": "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.0.tgz", + "integrity": "sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ==", "cpu": [ "riscv64" ], @@ -2710,9 +2720,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz", - "integrity": "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.0.tgz", + "integrity": "sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg==", "cpu": [ "s390x" ], @@ -2724,9 +2734,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz", - "integrity": "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.0.tgz", + "integrity": "sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A==", "cpu": [ "x64" ], @@ -2738,9 +2748,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz", - "integrity": "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.0.tgz", + "integrity": "sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw==", "cpu": [ "x64" ], @@ -2752,9 +2762,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz", - "integrity": "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.0.tgz", + "integrity": "sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw==", "cpu": [ "x64" ], @@ -2766,9 +2776,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz", - "integrity": "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.0.tgz", + "integrity": "sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA==", "cpu": [ "arm64" ], @@ -2780,9 +2790,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz", - "integrity": "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.0.tgz", + "integrity": "sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ==", "cpu": [ "arm64" ], @@ -2794,9 +2804,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz", - "integrity": "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.0.tgz", + "integrity": "sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA==", "cpu": [ "ia32" ], @@ -2808,9 +2818,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz", - "integrity": "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.0.tgz", + "integrity": "sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA==", "cpu": [ "x64" ], @@ -2822,9 +2832,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz", - "integrity": "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.0.tgz", + "integrity": "sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ==", "cpu": [ "x64" ], @@ -3016,9 +3026,9 @@ "license": "MIT" }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", "license": "MIT", "optional": true }, @@ -3096,14 +3106,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.1.tgz", - "integrity": "sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz", + "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.53.1", - "@typescript-eslint/types": "^8.53.1", + "@typescript-eslint/tsconfig-utils": "^8.54.0", + "@typescript-eslint/types": "^8.54.0", "debug": "^4.4.3" }, "engines": { @@ -3118,14 +3128,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz", - "integrity": "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz", + "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1" + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3136,9 +3146,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.1.tgz", - "integrity": "sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz", + "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==", "dev": true, "license": "MIT", "engines": { @@ -3153,9 +3163,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", - "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz", + "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==", "dev": true, "license": "MIT", "engines": { @@ -3167,16 +3177,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz", - "integrity": "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz", + "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.53.1", - "@typescript-eslint/tsconfig-utils": "8.53.1", - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1", + "@typescript-eslint/project-service": "8.54.0", + "@typescript-eslint/tsconfig-utils": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", @@ -3195,16 +3205,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.1.tgz", - "integrity": "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz", + "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.53.1", - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/typescript-estree": "8.53.1" + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3219,13 +3229,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz", - "integrity": "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz", + "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/types": "8.54.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -4811,27 +4821,29 @@ } }, "node_modules/cspell": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.6.0.tgz", - "integrity": "sha512-Mpf0oT2KAHTIb3YPAXWhW64/4CZKW5Lka4j1YxCLK3jM3nenmIsY/ocrJvqCMF4+1eejRF0N55sT3XmrijI5YQ==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.6.2.tgz", + "integrity": "sha512-EmkSGhStMbSh2BcyMqbVDOF48fSPWL3adjqajUVCwfnlZD7mzUWPx9pR8pt2dOQaFEE47rlOQGXdd3wTqL5dnQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "9.6.0", - "@cspell/cspell-pipe": "9.6.0", - "@cspell/cspell-types": "9.6.0", - "@cspell/dynamic-import": "9.6.0", - "@cspell/url": "9.6.0", + "@cspell/cspell-json-reporter": "9.6.2", + "@cspell/cspell-performance-monitor": "9.6.2", + "@cspell/cspell-pipe": "9.6.2", + "@cspell/cspell-types": "9.6.2", + "@cspell/cspell-worker": "9.6.2", + "@cspell/dynamic-import": "9.6.2", + "@cspell/url": "9.6.2", "ansi-regex": "^6.2.2", "chalk": "^5.6.2", "chalk-template": "^1.1.2", "commander": "^14.0.2", - "cspell-config-lib": "9.6.0", - "cspell-dictionary": "9.6.0", - "cspell-gitignore": "9.6.0", - "cspell-glob": "9.6.0", - "cspell-io": "9.6.0", - "cspell-lib": "9.6.0", + "cspell-config-lib": "9.6.2", + "cspell-dictionary": "9.6.2", + "cspell-gitignore": "9.6.2", + "cspell-glob": "9.6.2", + "cspell-io": "9.6.2", + "cspell-lib": "9.6.2", "fast-json-stable-stringify": "^2.1.0", "flatted": "^3.3.3", "semver": "^7.7.3", @@ -4842,20 +4854,20 @@ "cspell-esm": "bin.mjs" }, "engines": { - "node": ">=20" + "node": ">=20.18" }, "funding": { "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" } }, "node_modules/cspell-config-lib": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.6.0.tgz", - "integrity": "sha512-5ztvheawkmFXNHGN82iOOntU3T5mmlQBP/plgoKdBZ6+lSYrOJLkOyqxYyi7MrUBDtWrXPzFllkBrPNRDlbX/A==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.6.2.tgz", + "integrity": "sha512-VQB+xmqGqCJrt5k/o0rRG9v0X0CA96CEd9FsmBAm5+9DvNiRzXOqewZSdsOM2Y0SX7YKcvG82PfRsujhYltcfQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.6.0", + "@cspell/cspell-types": "9.6.2", "comment-json": "^4.5.1", "smol-toml": "^1.6.0", "yaml": "^2.8.2" @@ -4865,15 +4877,16 @@ } }, "node_modules/cspell-dictionary": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.6.0.tgz", - "integrity": "sha512-wW0m1kLrbK6bRY/GrLUGKUUJ1Z4ZUgIb8LD4zNaECcvGviv9V7VcR3mEwUip3ZjoHa3ClzEoWgQ9gXrtac80Wg==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.6.2.tgz", + "integrity": "sha512-J55/9+AtkRzfSVn+KaqoWxsS4O66szKP6LrDW0O2qWnuvVvO1BoAMsINynD845IIzrd1n1yTOHS/DbjmHd4//A==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.6.0", - "@cspell/cspell-types": "9.6.0", - "cspell-trie-lib": "9.6.0", + "@cspell/cspell-performance-monitor": "9.6.2", + "@cspell/cspell-pipe": "9.6.2", + "@cspell/cspell-types": "9.6.2", + "cspell-trie-lib": "9.6.2", "fast-equals": "^6.0.0" }, "engines": { @@ -4881,15 +4894,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.6.0.tgz", - "integrity": "sha512-8GfmJuRBBvibyPHnNE2wYJAiQ/ceDYLD1X1sUQaCyj6hPMR7ChJiVhFPtS11hMqkjZ46OBMYTMGWqO792L9fEQ==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.6.2.tgz", + "integrity": "sha512-vtwc9AAA9m3aZPtbvPPRTLXIqwryljxEgQTkpr92mFZaGftvnLfNVb2z++NvWbXq9azGKN/7oiLjecb9dhYnfA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.6.0", - "cspell-glob": "9.6.0", - "cspell-io": "9.6.0" + "@cspell/url": "9.6.2", + "cspell-glob": "9.6.2", + "cspell-io": "9.6.2" }, "bin": { "cspell-gitignore": "bin.mjs" @@ -4899,13 +4912,13 @@ } }, "node_modules/cspell-glob": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.6.0.tgz", - "integrity": "sha512-KmEbKN0qdEamsEYbkFu7zjLYfw3hMmn9kmeh94IHr2kq6vWq5vNP5l1BuqmrUeFZlbNd07vj08IKAZHYsoGheQ==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.6.2.tgz", + "integrity": "sha512-5j+g4JzcWjW16ZAtcPHpG138CEfpp1YmuYJoYtze3lIZLgttt+k2gXJsqyWaP/6MdVknI0Q1afGSKYRtH8mLRA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.6.0", + "@cspell/url": "9.6.2", "picomatch": "^4.0.3" }, "engines": { @@ -4913,14 +4926,14 @@ } }, "node_modules/cspell-grammar": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.6.0.tgz", - "integrity": "sha512-jZVIM5/3eB9rWURDq+VXdYip+DmPuFzO+bqaRtzqT8w6YoOIGYbiIxdwvyyA9xdH7SmW8uqHJP5x4pzZju1lNQ==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.6.2.tgz", + "integrity": "sha512-JTH92+1VGFPb3UsDT+Ezur/ouR8t+XOZkETUkk8eoSBzli9hWgPHW7kl2T8Chcn+Dq/6FLlvezYbBvhSauqJRw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.6.0", - "@cspell/cspell-types": "9.6.0" + "@cspell/cspell-pipe": "9.6.2", + "@cspell/cspell-types": "9.6.2" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4930,41 +4943,42 @@ } }, "node_modules/cspell-io": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.6.0.tgz", - "integrity": "sha512-wZuZzKOYIb698kVEINYjGaNFQu+AFZ945TORM3hapmPjez+vsHwl8m/pPpCHeGMpQtHMEDkX84AbQ7R55MRIwg==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.6.2.tgz", + "integrity": "sha512-VRBkAfUdbaq5yDYoVMvodQF3bIdBL6Gy4tiMvf+UI9C16am47AuThg1gGXRzwi5hCEXnCfevAmuVdaQP3onkow==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "9.6.0", - "@cspell/url": "9.6.0" + "@cspell/cspell-service-bus": "9.6.2", + "@cspell/url": "9.6.2" }, "engines": { "node": ">=20" } }, "node_modules/cspell-lib": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.6.0.tgz", - "integrity": "sha512-m9rIv8hkQ3Dio4s80HQbM9cdxENcd6pS8j2AHWL50OSjJf3Xhw6/wMrIAGbwLHP15K6QZVU2eJ/abCzIJwjA4w==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.6.2.tgz", + "integrity": "sha512-LvValIwqDAwVp2Www+7PPJ7UbVurYtKGPddpGH7GN+0u+UWzR4oUXR80gY8lHgSrIQ3EkdLhFAItPcyMjGjzIg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "9.6.0", - "@cspell/cspell-pipe": "9.6.0", - "@cspell/cspell-resolver": "9.6.0", - "@cspell/cspell-types": "9.6.0", - "@cspell/dynamic-import": "9.6.0", - "@cspell/filetypes": "9.6.0", - "@cspell/strong-weak-map": "9.6.0", - "@cspell/url": "9.6.0", + "@cspell/cspell-bundled-dicts": "9.6.2", + "@cspell/cspell-performance-monitor": "9.6.2", + "@cspell/cspell-pipe": "9.6.2", + "@cspell/cspell-resolver": "9.6.2", + "@cspell/cspell-types": "9.6.2", + "@cspell/dynamic-import": "9.6.2", + "@cspell/filetypes": "9.6.2", + "@cspell/strong-weak-map": "9.6.2", + "@cspell/url": "9.6.2", "clear-module": "^4.1.2", - "cspell-config-lib": "9.6.0", - "cspell-dictionary": "9.6.0", - "cspell-glob": "9.6.0", - "cspell-grammar": "9.6.0", - "cspell-io": "9.6.0", - "cspell-trie-lib": "9.6.0", + "cspell-config-lib": "9.6.2", + "cspell-dictionary": "9.6.2", + "cspell-glob": "9.6.2", + "cspell-grammar": "9.6.2", + "cspell-io": "9.6.2", + "cspell-trie-lib": "9.6.2", "env-paths": "^3.0.0", "gensequence": "^8.0.8", "import-fresh": "^3.3.1", @@ -4978,16 +4992,16 @@ } }, "node_modules/cspell-trie-lib": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.6.0.tgz", - "integrity": "sha512-L7GSff5F9cF60QT78WsebVlb3sppi6jbvTHwsw7WF1jUN/ioAo7OzBYtYB7xkYeejcdVEpqfvf/ZOXPDp8x2Wg==", + "version": "9.6.2", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.6.2.tgz", + "integrity": "sha512-JpCHpMdxo680yEkb6U1y3wrhZGHltgCnaQ8Zj6yKE8KE0BTLVl9UQGisP5De1wlFn4GtpPCf7WtQ8+M5aqq3YQ==", "dev": true, "license": "MIT", "engines": { "node": ">=20" }, "peerDependencies": { - "@cspell/cspell-types": "9.6.0" + "@cspell/cspell-types": "9.6.2" } }, "node_modules/cspell/node_modules/chalk": { @@ -6067,13 +6081,13 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "62.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.4.0.tgz", - "integrity": "sha512-SmwVS4QCSsBRmOfAn1J2CyCO4chqZtSU5olBCiHZ0RnxZVjIBTgm/1ZBFwFDUiV5/llFZcuSHEJK5DjHCDcGPw==", + "version": "62.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.4.1.tgz", + "integrity": "sha512-HgX2iN4j104D/mCUqRbhtzSZbph+KO9jfMHiIJjJ19Q+IwLQ5Na2IqvOJYq4S+4kgvEk1w6KYF4vVus6H2wcHg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.82.0", + "@es-joy/jsdoccomment": "~0.83.0", "@es-joy/resolve.exports": "1.2.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.5", @@ -6153,9 +6167,9 @@ } }, "node_modules/eslint-plugin-playwright": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.5.0.tgz", - "integrity": "sha512-1ckFw7Abdz+l23wtw5Tg4GTK3Y+MgEQQNjEr7FTJP3wwmIOj8DkbJ6G655aPc09c0Kfn/NoGA4xpMZzeSO4NWw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.5.1.tgz", + "integrity": "sha512-q7oqVQTTfa3VXJQ8E+ln0QttPGrs/XmSO1FjOMzQYBMYF3btih4FIrhEYh34JF184GYDmq3lJ/n7CMa49OHBvA==", "dev": true, "license": "MIT", "dependencies": { @@ -8376,9 +8390,9 @@ } }, "node_modules/katex": { - "version": "0.16.27", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.27.tgz", - "integrity": "sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==", + "version": "0.16.28", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.28.tgz", + "integrity": "sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==", "dev": true, "funding": [ "https://opencollective.com/katex", @@ -8575,9 +8589,9 @@ } }, "node_modules/lru-cache": { - "version": "11.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", - "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "version": "11.2.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", + "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -9670,9 +9684,9 @@ } }, "node_modules/node-ical": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.23.1.tgz", - "integrity": "sha512-4+FON2u++r7vU9VfTCris9hgxS5darN4P7aQZOJkzDazXLRS7cExb0G5OWO3CzRs8gHd5um1fdSMF0e45f7xAg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.24.0.tgz", + "integrity": "sha512-kBnxTUozR+vukiTaGzliasrnCXimhyvEw97ALVLoPO6xFED8V67O1/ZJbrlZ9ujMfZfiAhBkKLeJ/hU7oB5zAw==", "license": "Apache-2.0", "dependencies": { "@js-temporal/polyfill": "^0.5.1", @@ -11085,9 +11099,9 @@ } }, "node_modules/rollup": { - "version": "4.56.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz", - "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==", + "version": "4.57.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz", + "integrity": "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==", "dev": true, "license": "MIT", "dependencies": { @@ -11101,31 +11115,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.56.0", - "@rollup/rollup-android-arm64": "4.56.0", - "@rollup/rollup-darwin-arm64": "4.56.0", - "@rollup/rollup-darwin-x64": "4.56.0", - "@rollup/rollup-freebsd-arm64": "4.56.0", - "@rollup/rollup-freebsd-x64": "4.56.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", - "@rollup/rollup-linux-arm-musleabihf": "4.56.0", - "@rollup/rollup-linux-arm64-gnu": "4.56.0", - "@rollup/rollup-linux-arm64-musl": "4.56.0", - "@rollup/rollup-linux-loong64-gnu": "4.56.0", - "@rollup/rollup-linux-loong64-musl": "4.56.0", - "@rollup/rollup-linux-ppc64-gnu": "4.56.0", - "@rollup/rollup-linux-ppc64-musl": "4.56.0", - "@rollup/rollup-linux-riscv64-gnu": "4.56.0", - "@rollup/rollup-linux-riscv64-musl": "4.56.0", - "@rollup/rollup-linux-s390x-gnu": "4.56.0", - "@rollup/rollup-linux-x64-gnu": "4.56.0", - "@rollup/rollup-linux-x64-musl": "4.56.0", - "@rollup/rollup-openbsd-x64": "4.56.0", - "@rollup/rollup-openharmony-arm64": "4.56.0", - "@rollup/rollup-win32-arm64-msvc": "4.56.0", - "@rollup/rollup-win32-ia32-msvc": "4.56.0", - "@rollup/rollup-win32-x64-gnu": "4.56.0", - "@rollup/rollup-win32-x64-msvc": "4.56.0", + "@rollup/rollup-android-arm-eabi": "4.57.0", + "@rollup/rollup-android-arm64": "4.57.0", + "@rollup/rollup-darwin-arm64": "4.57.0", + "@rollup/rollup-darwin-x64": "4.57.0", + "@rollup/rollup-freebsd-arm64": "4.57.0", + "@rollup/rollup-freebsd-x64": "4.57.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.0", + "@rollup/rollup-linux-arm-musleabihf": "4.57.0", + "@rollup/rollup-linux-arm64-gnu": "4.57.0", + "@rollup/rollup-linux-arm64-musl": "4.57.0", + "@rollup/rollup-linux-loong64-gnu": "4.57.0", + "@rollup/rollup-linux-loong64-musl": "4.57.0", + "@rollup/rollup-linux-ppc64-gnu": "4.57.0", + "@rollup/rollup-linux-ppc64-musl": "4.57.0", + "@rollup/rollup-linux-riscv64-gnu": "4.57.0", + "@rollup/rollup-linux-riscv64-musl": "4.57.0", + "@rollup/rollup-linux-s390x-gnu": "4.57.0", + "@rollup/rollup-linux-x64-gnu": "4.57.0", + "@rollup/rollup-linux-x64-musl": "4.57.0", + "@rollup/rollup-openbsd-x64": "4.57.0", + "@rollup/rollup-openharmony-arm64": "4.57.0", + "@rollup/rollup-win32-arm64-msvc": "4.57.0", + "@rollup/rollup-win32-ia32-msvc": "4.57.0", + "@rollup/rollup-win32-x64-gnu": "4.57.0", + "@rollup/rollup-win32-x64-msvc": "4.57.0", "fsevents": "~2.3.2" } }, @@ -11794,9 +11808,9 @@ "license": "MIT" }, "node_modules/sort-package-json": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.6.0.tgz", - "integrity": "sha512-fyJsPLhWvY7u2KsKPZn1PixbXp+1m7V8NWqU8CvgFRbMEX41Ffw1kD8n0CfJiGoaSfoAvbrqRRl/DcHO8omQOQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.6.1.tgz", + "integrity": "sha512-Chgejw1+10p2D0U2tB7au1lHtz6TkFnxmvZktyBCRyV0GgmF6nl1IxXxAsPtJVsUyg/fo+BfCMAVVFUVRkAHrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12459,9 +12473,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.30.5", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.5.tgz", - "integrity": "sha512-DpWmpCckhwR3hG+6udb6/aQB7PpiqVnvSljrjbKxNSvTRsGsg7NVE3/vouoYf96xgwMxXFKcS4Ux+cnkFwYM7A==", + "version": "5.30.6", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.6.tgz", + "integrity": "sha512-LEIyK1aEv5P3BhAPW3swdlIyCihxwEq/Gki+kcONieU4PIeRCSLDuGkk0Va/56PSBgjVgEksOM88dmY6YqOyfQ==", "license": "MIT", "os": [ "darwin", @@ -12778,9 +12792,9 @@ } }, "node_modules/type-fest": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.1.tgz", - "integrity": "sha512-xygQcmneDyzsEuKZrFbRMne5HDqMs++aFzefrJTgEIKjQ3rekM+RPfFCVq2Gp1VIDqddoYeppCj4Pcb+RZW0GQ==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.2.tgz", + "integrity": "sha512-FLEenlVYf7Zcd34ISMLo3ZzRE1gRjY1nMDTp+bQRBiPsaKyIW8K3Zr99ioHDUgA9OGuGGJPyYpNcffGmBhJfGg==", "dev": true, "license": "(MIT OR CC0-1.0)", "dependencies": { @@ -12935,9 +12949,9 @@ } }, "node_modules/undici": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.0.tgz", - "integrity": "sha512-Heho1hJD81YChi+uS2RkSjcVO+EQLmLSyUlHyp7Y/wFbxQaGb4WXVKD073JytrjXJVkSZVzoE2MCSOKugFGtOQ==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.1.tgz", + "integrity": "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg==", "license": "MIT", "engines": { "node": ">=20.18.1" diff --git a/package.json b/package.json index 9af69d78f2..e383d9862e 100644 --- a/package.json +++ b/package.json @@ -95,13 +95,13 @@ "ipaddr.js": "^2.3.0", "moment": "^2.30.1", "moment-timezone": "^0.6.0", - "node-ical": "^0.23.1", + "node-ical": "^0.24.0", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.30.5", - "undici": "^7.19.0", + "systeminformation": "^5.30.6", + "undici": "^7.19.1", "weathericons": "^2.1.0" }, "devDependencies": { @@ -109,11 +109,11 @@ "@vitest/coverage-v8": "^4.0.18", "@vitest/eslint-plugin": "^1.6.6", "@vitest/ui": "^4.0.18", - "cspell": "^9.6.0", + "cspell": "^9.6.2", "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-jsdoc": "^62.4.0", + "eslint-plugin-jsdoc": "^62.4.1", "eslint-plugin-package-json": "^0.88.2", - "eslint-plugin-playwright": "^2.5.0", + "eslint-plugin-playwright": "^2.5.1", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jsdom": "^27.4.0", From 6324ec2116f93c60f758251f6bb71a8e37be365d Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 28 Jan 2026 10:50:25 +0100 Subject: [PATCH 355/418] move custom.css from css to config (#4020) This is another change to cleanup structure, already mentioned in https://github.com/MagicMirrorOrg/MagicMirror/pull/4019#issuecomment-3792953018 After separating default and 3rd-party modules this PR moves the `custom.css` from the mm-owned directory `css` into user owned directory `config`. It has a built-in function which moves the `css/custom.css` to the new location `config/custom.css` (if the target not exists). Let me know if there's a majority in favor of this change. --- .github/workflows/automated-tests.yaml | 2 +- .gitignore | 10 ++-------- {css => config}/custom.css.sample | 0 js/app.js | 13 ++++++++++++- js/defaults.js | 2 +- js/loader.js | 8 ++++---- package.json | 4 ++-- tests/e2e/helpers/global-setup.js | 2 +- 8 files changed, 23 insertions(+), 18 deletions(-) rename {css => config}/custom.css.sample (100%) diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 5685ff335c..086c8bf4f8 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -69,7 +69,7 @@ jobs: sudo chmod 4755 ./node_modules/electron/dist/chrome-sandbox # Start labwc WLR_BACKENDS=headless WLR_LIBINPUT_NO_DEVICES=1 WLR_RENDERER=pixman labwc & - touch css/custom.css + touch config/custom.css - name: "Run tests" run: | export WAYLAND_DISPLAY=wayland-0 diff --git a/.gitignore b/.gitignore index 027400d386..e1365c2fe6 100644 --- a/.gitignore +++ b/.gitignore @@ -57,16 +57,10 @@ Temporary Items # Ignore all modules /modules/* -# Ignore changes to the custom css files but keep the sample and main. -/css/* -!/css/custom.css.sample -!/css/font-awesome.css -!/css/main.css -!/css/roboto.css - -# Ignore users config file but keep the sample. +# Ignore users config file but keep the samples. config !config/config.js.sample +!config/custom.css.sample # Vim ## swap diff --git a/css/custom.css.sample b/config/custom.css.sample similarity index 100% rename from css/custom.css.sample rename to config/custom.css.sample diff --git a/js/app.js b/js/app.js index a67bf1b8cd..3d7e35d101 100644 --- a/js/app.js +++ b/js/app.js @@ -57,6 +57,7 @@ function App () { let nodeHelpers = []; let httpServer; let defaultModules; + let env; /** * Loads the config file. Combines it with the defaults and returns the config @@ -181,7 +182,6 @@ function App () { function loadModule (module) { const elements = module.split("/"); const moduleName = elements[elements.length - 1]; - const env = getEnvVarsAsObj(); let moduleFolder = path.resolve(`${global.root_path}/${env.modulesDir}`, module); if (defaultModules.includes(moduleName)) { @@ -296,6 +296,17 @@ function App () { Log.setLogLevel(config.logLevel); + env = getEnvVarsAsObj(); + // check for deprecated css/custom.css and move it to new location + if ((!fs.existsSync(`${global.root_path}/${env.customCss}`)) && (fs.existsSync(`${global.root_path}/css/custom.css`))) { + 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) { + Log.warn("WARNING! Your custom css file is currently located in the css folder. Please move it to the config folder!"); + } + } + // get the used module positions Utils.getModulePositions(); diff --git a/js/defaults.js b/js/defaults.js index 88a706d7e4..58e930a38d 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -18,7 +18,7 @@ const defaults = { timeFormat: 24, units: "metric", zoom: 1, - customCss: "css/custom.css", + customCss: "config/custom.css", foreignModulesDir: "modules", defaultModulesDir: "defaultmodules", // httpHeaders used by helmet, see https://helmetjs.github.io/. You can add other/more object values by overriding this in config.js, diff --git a/js/loader.js b/js/loader.js index dac0b5f56b..b6db83869b 100644 --- a/js/loader.js +++ b/js/loader.js @@ -18,7 +18,7 @@ const Loader = (function () { return { modulesDir: config.foreignModulesDir || "modules", defaultModulesDir: config.defaultModulesDir || "defaultmodules", - customCss: config.customCss || "css/custom.css" + customCss: config.customCss || "config/custom.css" }; }; @@ -262,7 +262,7 @@ const Loader = (function () { /** * Load a file (script or stylesheet). - * Prevent double loading and search for files in the vendor folder. + * Prevent double loading and search for files defined in js/vendor.js. * @param {string} fileName Path of the file we want to load. * @param {Module} module The module that calls the loadFile function. * @returns {Promise} resolved when the file is loaded @@ -281,8 +281,8 @@ const Loader = (function () { } if (vendor[fileName] !== undefined) { - // This file is available in the vendor folder. - // Load it from this vendor folder. + // This file is defined in js/vendor.js. + // Load it from its location. loadedFiles.push(fileName.toLowerCase()); return loadFile(`${vendor[fileName]}`); } diff --git a/package.json b/package.json index e383d9862e..2510ea872d 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "postinstall": "git clean -df fonts vendor modules/default", "install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev", "install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier && npx playwright install chromium", - "lint:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'defaultmodules/**/*.css' --fix", + "lint:css": "stylelint 'css/**/*.css' 'defaultmodules/**/*.css' --fix", "lint:js": "eslint --fix", "lint:markdown": "markdownlint-cli2 . --fix", "lint:prettier": "prettier . --write", @@ -61,7 +61,7 @@ "test": "vitest run", "test:calendar": "node ./defaultmodules/calendar/debug.js", "test:coverage": "vitest run --coverage", - "test:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'defaultmodules/**/*.css'", + "test:css": "stylelint 'css/**/*.css' 'defaultmodules/**/*.css'", "test:e2e": "vitest run tests/e2e", "test:electron": "vitest run tests/electron", "test:js": "eslint", diff --git a/tests/e2e/helpers/global-setup.js b/tests/e2e/helpers/global-setup.js index ee1a381815..8bbb810b7b 100644 --- a/tests/e2e/helpers/global-setup.js +++ b/tests/e2e/helpers/global-setup.js @@ -7,7 +7,7 @@ const { chromium } = require("playwright"); global.root_path = path.resolve(`${__dirname}/../../../`); const indexFile = `${global.root_path}/index.html`; -const cssFile = `${global.root_path}/css/custom.css`; +const cssFile = `${global.root_path}/config/custom.css`; const sampleCss = [ ".region.row3 {", " top: 0;", From 2b55b8e0f458cc2d38ce8097988af90e7d760347 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 28 Jan 2026 20:48:47 +0100 Subject: [PATCH 356/418] refactor(clientonly): modernize code structure and add comprehensive tests (#4022) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR improves `clientonly` start option with better code structure, validation, and comprehensive test coverage. ### Changes **Refactoring:** - Improved parameter handling with explicit function parameter passing instead of closure - Added port validation (1-65535) with proper NaN handling - Removed unnecessary IIFE wrapper (Node.js modules are already scoped) - Extracted `getCommandLineParameter` as a reusable top-level function - Enhanced error reporting with better error messages - Added connection logging for debugging **Testing:** - Added comprehensive e2e tests for parameter validation - Test coverage for missing/incomplete parameters - Test coverage for local address rejection (localhost, 127.0.0.1, ::1, ::ffff:127.0.0.1) - Test coverage for port validation (invalid ranges, non-numeric values) - Test coverage for TLS flag parsing - Integration test with running server ### Testing All tests pass: ```bash npm test -- tests/e2e/clientonly_spec.js # ✓ 18 tests passed --- clientonly/index.js | 277 +++++++++++++++++++---------------- tests/e2e/clientonly_spec.js | 179 ++++++++++++++++++++++ 2 files changed, 333 insertions(+), 123 deletions(-) create mode 100644 tests/e2e/clientonly_spec.js diff --git a/clientonly/index.js b/clientonly/index.js index e1ad59c5de..bf6d6cdf87 100644 --- a/clientonly/index.js +++ b/clientonly/index.js @@ -1,136 +1,167 @@ "use strict"; -// Use separate scope to prevent global scope pollution -(function () { +const http = require("node:http"); +const https = require("node:https"); + +/** + * Get command line parameters + * Assumes that a cmdline parameter is defined with `--key [value]` + * + * example: `node clientonly --address localhost --port 8080 --use-tls` + * @param {string} key key to look for at the command line + * @param {string} defaultValue value if no key is given at the command line + * @returns {string} the value of the parameter + */ +function getCommandLineParameter (key, defaultValue = undefined) { + const index = process.argv.indexOf(`--${key}`); + const value = index > -1 ? process.argv[index + 1] : undefined; + return value !== undefined ? String(value) : defaultValue; +} + +/** + * Helper function to get server address/hostname from either the commandline or env + * @returns {object} config object containing address, port, and tls properties + */ +function getServerParameters () { const config = {}; - /** - * Helper function to get server address/hostname from either the commandline or env - */ - function getServerAddress () { - - /** - * Get command line parameters - * Assumes that a cmdline parameter is defined with `--key [value]` - * @param {string} key key to look for at the command line - * @param {string} defaultValue value if no key is given at the command line - * @returns {string} the value of the parameter - */ - function getCommandLineParameter (key, defaultValue = undefined) { - const index = process.argv.indexOf(`--${key}`); - const value = index > -1 ? process.argv[index + 1] : undefined; - return value !== undefined ? String(value) : defaultValue; - } - - // Prefer command line arguments over environment variables - ["address", "port"].forEach((key) => { - config[key] = getCommandLineParameter(key, process.env[key.toUpperCase()]); - }); - - // determine if "--use-tls"-flag was provided - config.tls = process.argv.indexOf("--use-tls") > 0; - } - - /** - * Gets the config from the specified server url - * @param {string} url location where the server is running. - * @returns {Promise} the config - */ - function getServerConfig (url) { - // Return new pending promise - return new Promise((resolve, reject) => { - // Select http or https module, depending on requested url - const lib = url.startsWith("https") ? require("node:https") : require("node:http"); - const request = lib.get(url, (response) => { - let configData = ""; - - // Gather incoming data - response.on("data", function (chunk) { - configData += chunk; - }); - // Resolve promise at the end of the HTTP/HTTPS stream - response.on("end", function () { + // Prefer command line arguments over environment variables + config.address = getCommandLineParameter("address", process.env.ADDRESS); + const portValue = getCommandLineParameter("port", process.env.PORT); + config.port = portValue ? parseInt(portValue, 10) : undefined; + + // determine if "--use-tls"-flag was provided + config.tls = process.argv.includes("--use-tls"); + + return config; +} + +/** + * Gets the config from the specified server url + * @param {string} url location where the server is running. + * @returns {Promise} the config + */ +function getServerConfig (url) { + // Return new pending promise + return new Promise((resolve, reject) => { + // Select http or https module, depending on requested url + const lib = url.startsWith("https") ? https : http; + const request = lib.get(url, (response) => { + let configData = ""; + + // Gather incoming data + response.on("data", function (chunk) { + configData += chunk; + }); + // Resolve promise at the end of the HTTP/HTTPS stream + response.on("end", function () { + try { resolve(JSON.parse(configData)); - }); + } catch (parseError) { + reject(new Error(`Failed to parse server response as JSON: ${parseError.message}`)); + } }); + }); - request.on("error", function (error) { - reject(new Error(`Unable to read config from server (${url} (${error.message}`)); - }); + request.on("error", function (error) { + reject(new Error(`Unable to read config from server (${url}) (${error.message})`)); }); + }); +} + +/** + * Print a message to the console in case of errors + * @param {string} message error message to print + * @param {number} code error code for the exit call + */ +function fail (message, code = 1) { + if (message !== undefined && typeof message === "string") { + console.error(message); + } else { + console.error("Usage: 'node clientonly --address 192.168.1.10 --port 8080 [--use-tls]'"); } - - /** - * Print a message to the console in case of errors - * @param {string} message error message to print - * @param {number} code error code for the exit call - */ - function fail (message, code = 1) { - if (message !== undefined && typeof message === "string") { - console.log(message); + process.exit(code); +} + +/** + * Starts the client by connecting to the server and launching the Electron application + * @param {object} config server configuration + * @param {string} prefix http or https prefix + * @async + */ +async function startClient (config, prefix) { + try { + const serverUrl = `${prefix}${config.address}:${config.port}/config/`; + console.log(`Client: Connecting to server at ${serverUrl}`); + const configReturn = await getServerConfig(serverUrl); + console.log("Client: Successfully retrieved config from server"); + + // check environment for DISPLAY or WAYLAND_DISPLAY + const elecParams = ["js/electron.js"]; + if (process.env.WAYLAND_DISPLAY) { + console.log(`Client: Using WAYLAND_DISPLAY=${process.env.WAYLAND_DISPLAY}`); + elecParams.push("--enable-features=UseOzonePlatform"); + elecParams.push("--ozone-platform=wayland"); + } else if (process.env.DISPLAY) { + console.log(`Client: Using DISPLAY=${process.env.DISPLAY}`); } else { - console.log("Usage: 'node clientonly --address 192.168.1.10 --port 8080 [--use-tls]'"); + fail("Error: Requires environment variable WAYLAND_DISPLAY or DISPLAY, none is provided."); } - process.exit(code); - } - getServerAddress(); - - (config.address && config.port) || fail(); - const prefix = config.tls ? "https://" : "http://"; - - // Only start the client if a non-local server was provided - if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].indexOf(config.address) === -1) { - getServerConfig(`${prefix}${config.address}:${config.port}/config/`) - .then(function (configReturn) { - // check environment for DISPLAY or WAYLAND_DISPLAY - const elecParams = ["js/electron.js"]; - if (process.env.WAYLAND_DISPLAY) { - console.log(`Client: Using WAYLAND_DISPLAY=${process.env.WAYLAND_DISPLAY}`); - elecParams.push("--enable-features=UseOzonePlatform"); - elecParams.push("--ozone-platform=wayland"); - } else if (process.env.DISPLAY) { - console.log(`Client: Using DISPLAY=${process.env.DISPLAY}`); - } else { - fail("Error: Requires environment variable WAYLAND_DISPLAY or DISPLAY, none is provided."); - } - // Pass along the server config via an environment variable - const env = Object.create(process.env); - env.clientonly = true; // set to pass to electron.js - const options = { env: env }; - configReturn.address = config.address; - configReturn.port = config.port; - configReturn.tls = config.tls; - env.config = JSON.stringify(configReturn); - - // Spawn electron application - const electron = require("electron"); - const child = require("node:child_process").spawn(electron, elecParams, options); - - // Pipe all child process output to current stdout - child.stdout.on("data", function (buf) { - process.stdout.write(`Client: ${buf}`); - }); - - // Pipe all child process errors to current stderr - child.stderr.on("data", function (buf) { - process.stderr.write(`Client: ${buf}`); - }); - - child.on("error", function (err) { - process.stdout.write(`Client: ${err}`); - }); - - child.on("close", (code) => { - if (code !== 0) { - console.log(`There something wrong. The clientonly is not running code ${code}`); - } - }); - }) - .catch(function (reason) { - fail(`Unable to connect to server: (${reason})`); - }); - } else { - fail(); + // Pass along the server config via an environment variable + const env = { ...process.env }; + env.clientonly = true; + const options = { env: env }; + configReturn.address = config.address; + configReturn.port = config.port; + configReturn.tls = config.tls; + env.config = JSON.stringify(configReturn); + + // Spawn electron application + const electron = require("electron"); + const child = require("node:child_process").spawn(electron, elecParams, options); + + // Pipe all child process output to current stdout + child.stdout.on("data", function (buf) { + process.stdout.write(`Client: ${buf}`); + }); + + // Pipe all child process errors to current stderr + child.stderr.on("data", function (buf) { + process.stderr.write(`Client: ${buf}`); + }); + + child.on("error", function (err) { + process.stderr.write(`Client: ${err}`); + }); + + child.on("close", (code) => { + if (code !== 0) { + fail(`There is something wrong. The clientonly process exited with code ${code}.`); + } + }); + } catch (reason) { + fail(`Unable to connect to server: (${reason})`); } -}()); +} + +// Main execution +const config = getServerParameters(); +const prefix = config.tls ? "https://" : "http://"; + +// Validate port +if (config.port !== undefined && (isNaN(config.port) || config.port < 1 || config.port > 65535)) { + fail(`Invalid port number: ${config.port}. Port must be between 1 and 65535.`); +} + +// Only start the client if a non-local server was provided and address/port are set +const LOCAL_ADDRESSES = ["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1"]; +if ( + config.address + && config.port + && !LOCAL_ADDRESSES.includes(config.address) +) { + startClient(config, prefix); +} else { + fail(); +} diff --git a/tests/e2e/clientonly_spec.js b/tests/e2e/clientonly_spec.js new file mode 100644 index 0000000000..6df9a3c325 --- /dev/null +++ b/tests/e2e/clientonly_spec.js @@ -0,0 +1,179 @@ +const { spawnSync, spawn } = require("node:child_process"); + +const delay = (time) => { + return new Promise((resolve) => setTimeout(resolve, time)); +}; + +/** + * Run clientonly with given arguments and return result + * @param {string[]} args command line arguments + * @param {object} env environment variables to merge (replaces process.env) + * @returns {object} result with status and stderr + */ +const runClientOnly = (args = [], env = {}) => { + // Start with minimal env and merge provided env + const testEnv = { + PATH: process.env.PATH, + NODE_PATH: process.env.NODE_PATH, + ...env + }; + const result = spawnSync("node", ["clientonly/index.js", ...args], { + env: testEnv, + encoding: "utf-8", + timeout: 5000 + }); + return result; +}; + +describe("Clientonly parameter handling", () => { + + describe("Missing parameters", () => { + it("should fail without any parameters", () => { + const result = runClientOnly(); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Usage:"); + }); + + it("should fail with only address parameter", () => { + const result = runClientOnly(["--address", "192.168.1.10"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Usage:"); + }); + + it("should fail with only port parameter", () => { + const result = runClientOnly(["--port", "8080"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Usage:"); + }); + }); + + describe("Local address rejection", () => { + it("should fail with localhost address", () => { + const result = runClientOnly(["--address", "localhost", "--port", "8080"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Usage:"); + }); + + it("should fail with 127.0.0.1 address", () => { + const result = runClientOnly(["--address", "127.0.0.1", "--port", "8080"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Usage:"); + }); + + it("should fail with ::1 address", () => { + const result = runClientOnly(["--address", "::1", "--port", "8080"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Usage:"); + }); + + it("should fail with ::ffff:127.0.0.1 address", () => { + const result = runClientOnly(["--address", "::ffff:127.0.0.1", "--port", "8080"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Usage:"); + }); + }); + + describe("Port validation", () => { + it("should fail with port 0", () => { + const result = runClientOnly(["--address", "192.168.1.10", "--port", "0"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Invalid port number"); + }); + + it("should fail with negative port", () => { + const result = runClientOnly(["--address", "192.168.1.10", "--port", "-1"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Invalid port number"); + }); + + it("should fail with port above 65535", () => { + const result = runClientOnly(["--address", "192.168.1.10", "--port", "65536"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Invalid port number"); + }); + + it("should fail with non-numeric port", () => { + const result = runClientOnly(["--address", "192.168.1.10", "--port", "abc"]); + expect(result.status).toBe(1); + expect(result.stderr).toContain("Invalid port number"); + }); + + it("should accept valid port 8080", () => { + const result = runClientOnly(["--address", "192.168.1.10", "--port", "8080"]); + // Should not fail on port validation (will fail on connection or display) + expect(result.stderr).not.toContain("Invalid port number"); + }); + + it("should accept valid port 1", () => { + const result = runClientOnly(["--address", "192.168.1.10", "--port", "1"]); + expect(result.stderr).not.toContain("Invalid port number"); + }); + + it("should accept valid port 65535", () => { + const result = runClientOnly(["--address", "192.168.1.10", "--port", "65535"]); + expect(result.stderr).not.toContain("Invalid port number"); + }); + }); + + describe("TLS flag parsing", () => { + // Note: These tests verify the flag is parsed, not the actual connection behavior + // Connection tests would timeout as they try to reach unreachable addresses + + it("should not fail on port validation when using --use-tls", () => { + // Verify --use-tls doesn't interfere with other parameter parsing + const result = runClientOnly(["--address", "192.168.1.10", "--port", "443", "--use-tls"]); + expect(result.stderr).not.toContain("Invalid port number"); + }); + + it("should accept --use-tls flag with valid parameters", () => { + const result = runClientOnly(["--address", "192.168.1.10", "--port", "443", "--use-tls"]); + // Should not fail on parameter parsing (will fail on connection or display) + expect(result.stderr).not.toContain("Usage:"); + }); + }); + + describe("Display environment check", () => { + it("should fail without DISPLAY or WAYLAND_DISPLAY when connecting to valid server", async () => { + // This test needs a running server to get past the connection phase + // Without DISPLAY, it should fail with display error + // For now, we just verify it fails (connection error comes first without server) + const result = runClientOnly(["--address", "192.168.1.10", "--port", "1"]); + // Either exits with code 1 or times out (null status means killed/timeout) + expect(result.status === 1 || result.status === null).toBe(true); + }); + }); +}); + +describe("Clientonly with running server", () => { + let serverProcess; + const testPort = 8081; + + beforeAll(async () => { + process.env.MM_CONFIG_FILE = "tests/configs/default.js"; + process.env.MM_PORT = testPort.toString(); + serverProcess = spawn("node", ["--run", "server"], { + env: process.env, + detached: true + }); + // Wait for server to start + await delay(2000); + }); + + afterAll(async () => { + if (serverProcess && serverProcess.pid) { + try { + process.kill(-serverProcess.pid); + } catch { + // Process may already be dead + } + } + }); + + it("should be able to fetch config from server", async () => { + const res = await fetch(`http://localhost:${testPort}/config/`); + expect(res.status).toBe(200); + const config = await res.json(); + expect(config).toBeDefined(); + expect(typeof config).toBe("object"); + }); +}); From 5c1cc476f378d6e89d1f6cb96be355bd4353b244 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 29 Jan 2026 19:41:59 +0100 Subject: [PATCH 357/418] [newsfeed] refactor: migrate to centralized HTTPFetcher (#4023) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This migrates the Newsfeed module to use the centralized HTTPFetcher class (introduced in #4016), following the same pattern as the Calendar module. This continues the refactoring effort to centralize HTTP error handling across all modules. ## Changes **NewsfeedFetcher:** - Refactored from function constructor to ES6 class (like the calendar module in #3959) - Replaced manual fetch() + timer handling with HTTPFetcher composition - Uses structured error objects with translation keys - Inherits smart retry strategies (401/403, 429, 5xx backoff) - Inherits timeout handling (30s) and AbortController **node_helper.js:** - Updated error handler to use `errorInfo.translationKey` - Simplified property access (`fetcher.url`, `fetcher.items`) **Cleanup:** - Removed `js/module_functions.js` (`scheduleTimer` no longer needed) - Removed `#module_functions` import from package.json ## Related Part of the HTTPFetcher migration effort started in #4016. Next candidate: Weather module (client-side → server-side migration). --- defaultmodules/newsfeed/newsfeedfetcher.js | 212 ++++++++++----------- defaultmodules/newsfeed/node_helper.js | 14 +- js/module_functions.js | 18 -- package.json | 3 - 4 files changed, 108 insertions(+), 139 deletions(-) delete mode 100644 js/module_functions.js diff --git a/defaultmodules/newsfeed/newsfeedfetcher.js b/defaultmodules/newsfeed/newsfeedfetcher.js index d06f8cf332..12febd6a35 100644 --- a/defaultmodules/newsfeed/newsfeedfetcher.js +++ b/defaultmodules/newsfeed/newsfeedfetcher.js @@ -4,41 +4,71 @@ const FeedMe = require("feedme"); const iconv = require("iconv-lite"); const { htmlToText } = require("html-to-text"); const Log = require("logger"); -const NodeHelper = require("node_helper"); -const { getUserAgent } = require("#server_functions"); -const { scheduleTimer } = require("#module_functions"); +const HTTPFetcher = require("#http_fetcher"); /** - * Responsible for requesting an update on the set interval and broadcasting the data. - * @param {string} url URL of the news feed. - * @param {number} reloadInterval Reload interval in milliseconds. - * @param {string} encoding Encoding of the feed. - * @param {boolean} logFeedWarnings If true log warnings when there is an error parsing a news article. - * @param {boolean} useCorsProxy If true cors proxy is used for article url's. + * NewsfeedFetcher - Fetches and parses RSS/Atom feed data + * Uses HTTPFetcher for HTTP handling with intelligent error handling * @class */ -const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings, useCorsProxy) { - let reloadTimer = null; - let items = []; - let reloadIntervalMS = reloadInterval; +class NewsfeedFetcher { - let fetchFailedCallback = function () {}; - let itemsReceivedCallback = function () {}; + /** + * Creates a new NewsfeedFetcher instance + * @param {string} url - The URL of the news feed to fetch + * @param {number} reloadInterval - Time in ms between fetches + * @param {string} encoding - Encoding of the feed (e.g., 'UTF-8') + * @param {boolean} logFeedWarnings - If true log warnings when there is an error parsing a news article + * @param {boolean} useCorsProxy - If true cors proxy is used for article url's + */ + constructor (url, reloadInterval, encoding, logFeedWarnings, useCorsProxy) { + this.url = url; + this.encoding = encoding; + this.logFeedWarnings = logFeedWarnings; + this.useCorsProxy = useCorsProxy; + this.items = []; + this.fetchFailedCallback = () => {}; + this.itemsReceivedCallback = () => {}; + + // Use HTTPFetcher for HTTP handling (Composition) + this.httpFetcher = new HTTPFetcher(url, { + reloadInterval: Math.max(reloadInterval, 1000), + headers: { + "Cache-Control": "max-age=0, no-cache, no-store, must-revalidate", + Pragma: "no-cache" + } + }); - if (reloadIntervalMS < 1000) { - reloadIntervalMS = 1000; + // Wire up HTTPFetcher events + this.httpFetcher.on("response", (response) => this.#handleResponse(response)); + this.httpFetcher.on("error", (errorInfo) => this.fetchFailedCallback(this, errorInfo)); } - /* private methods */ - /** - * Request the new items. + * Creates a parse error info object + * @param {string} message - Error message + * @param {Error} error - Original error + * @returns {object} Error info object */ - const fetchNews = () => { - clearTimeout(reloadTimer); - reloadTimer = null; - items = []; + #createParseError (message, error) { + return { + message, + status: null, + errorType: "PARSE_ERROR", + translationKey: "MODULE_ERROR_UNSPECIFIED", + retryAfter: this.httpFetcher.reloadInterval, + retryCount: 0, + url: this.url, + originalError: error + }; + } + /** + * Handles successful HTTP response + * @param {Response} response - The fetch Response object + */ + #handleResponse (response) { + this.items = []; const parser = new FeedMe(); parser.on("item", (item) => { @@ -58,15 +88,15 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings ] }); - items.push({ - title: title, - description: description, - pubdate: pubdate, - url: url, - useCorsProxy: useCorsProxy, + this.items.push({ + title, + description, + pubdate, + url, + useCorsProxy: this.useCorsProxy, hash: crypto.createHash("sha256").update(`${pubdate} :: ${title} :: ${url}`).digest("hex") }); - } else if (logFeedWarnings) { + } else if (this.logFeedWarnings) { Log.warn("Can't parse feed item:", item); Log.warn(`Title: ${title}`); Log.warn(`Description: ${description}`); @@ -74,102 +104,64 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings } }); - parser.on("end", () => { - this.broadcastItems(); - }); + parser.on("end", () => this.broadcastItems()); parser.on("error", (error) => { - fetchFailedCallback(this, error); - scheduleTimer(reloadTimer, reloadIntervalMS, fetchNews); - }); - - //"end" event is not broadcast if the feed is empty but "finish" is used for both - parser.on("finish", () => { - scheduleTimer(reloadTimer, reloadIntervalMS, fetchNews); + Log.error(`${this.url} - Feed parsing failed: ${error.message}`); + this.fetchFailedCallback(this, this.#createParseError(`Feed parsing failed: ${error.message}`, error)); }); parser.on("ttl", (minutes) => { - try { - // 86400000 = 24 hours is mentioned in the docs as maximum value: - const ttlms = Math.min(minutes * 60 * 1000, 86400000); - if (ttlms > reloadIntervalMS) { - reloadIntervalMS = ttlms; - Log.info(`reloadInterval set to ttl=${reloadIntervalMS} for url ${url}`); - } - } catch (error) { - Log.warn(`feed ttl is no valid integer=${minutes} for url ${url}`); + const ttlms = Math.min(minutes * 60 * 1000, 86400000); + if (ttlms > this.httpFetcher.reloadInterval) { + this.httpFetcher.reloadInterval = ttlms; + Log.info(`reloadInterval set to ttl=${ttlms} for url ${this.url}`); } }); - const headers = { - "User-Agent": getUserAgent(), - "Cache-Control": "max-age=0, no-cache, no-store, must-revalidate", - Pragma: "no-cache" - }; - - fetch(url, { headers: headers }) - .then(NodeHelper.checkFetchStatus) - .then((response) => { - let nodeStream; - if (response.body instanceof stream.Readable) { - nodeStream = response.body; - } else { - nodeStream = stream.Readable.fromWeb(response.body); - } - nodeStream.pipe(iconv.decodeStream(encoding)).pipe(parser); - }) - .catch((error) => { - fetchFailedCallback(this, error); - scheduleTimer(reloadTimer, reloadIntervalMS, fetchNews); - }); - }; - - /* public methods */ + try { + const nodeStream = response.body instanceof stream.Readable + ? response.body + : stream.Readable.fromWeb(response.body); + nodeStream.pipe(iconv.decodeStream(this.encoding)).pipe(parser); + } catch (error) { + Log.error(`${this.url} - Stream processing failed: ${error.message}`); + this.fetchFailedCallback(this, this.#createParseError(`Stream processing failed: ${error.message}`, error)); + } + } /** * Update the reload interval, but only if we need to increase the speed. - * @param {number} interval Interval for the update in milliseconds. + * @param {number} interval - Interval for the update in milliseconds. */ - this.setReloadInterval = function (interval) { - if (interval > 1000 && interval < reloadIntervalMS) { - reloadIntervalMS = interval; + setReloadInterval (interval) { + if (interval > 1000 && interval < this.httpFetcher.reloadInterval) { + this.httpFetcher.reloadInterval = interval; } - }; + } - /** - * Initiate fetchNews(); - */ - this.startFetch = function () { - fetchNews(); - }; + startFetch () { + this.httpFetcher.startPeriodicFetch(); + } - /** - * Broadcast the existing items. - */ - this.broadcastItems = function () { - if (items.length <= 0) { + broadcastItems () { + if (this.items.length <= 0) { Log.info("No items to broadcast yet."); return; } - Log.info(`Broadcasting ${items.length} items.`); - itemsReceivedCallback(this); - }; - - this.onReceive = function (callback) { - itemsReceivedCallback = callback; - }; - - this.onError = function (callback) { - fetchFailedCallback = callback; - }; - - this.url = function () { - return url; - }; - - this.items = function () { - return items; - }; -}; + Log.info(`Broadcasting ${this.items.length} items.`); + this.itemsReceivedCallback(this); + } + + /** @param {function(NewsfeedFetcher): void} callback - Called when items are received */ + onReceive (callback) { + this.itemsReceivedCallback = callback; + } + + /** @param {function(NewsfeedFetcher, object): void} callback - Called on fetch error */ + onError (callback) { + this.fetchFailedCallback = callback; + } +} module.exports = NewsfeedFetcher; diff --git a/defaultmodules/newsfeed/node_helper.js b/defaultmodules/newsfeed/node_helper.js index cb5af00823..1101a72e4f 100644 --- a/defaultmodules/newsfeed/node_helper.js +++ b/defaultmodules/newsfeed/node_helper.js @@ -26,8 +26,7 @@ module.exports = NodeHelper.create({ const url = feed.url || ""; const encoding = feed.encoding || "UTF-8"; const reloadInterval = feed.reloadInterval || config.reloadInterval || 5 * 60 * 1000; - let useCorsProxy = feed.useCorsProxy; - if (useCorsProxy === undefined) useCorsProxy = true; + const useCorsProxy = feed.useCorsProxy ?? true; try { new URL(url); @@ -46,11 +45,10 @@ module.exports = NodeHelper.create({ this.broadcastFeeds(); }); - fetcher.onError((fetcher, error) => { - Log.error("Error: Could not fetch newsfeed: ", url, error); - let error_type = NodeHelper.checkFetchError(error); + fetcher.onError((fetcher, errorInfo) => { + Log.error("Error: Could not fetch newsfeed: ", fetcher.url, errorInfo.message || errorInfo); this.sendSocketNotification("NEWSFEED_ERROR", { - error_type + error_type: errorInfo.translationKey }); }); @@ -71,8 +69,8 @@ module.exports = NodeHelper.create({ */ broadcastFeeds () { const feeds = {}; - for (let f in this.fetchers) { - feeds[f] = this.fetchers[f].items(); + for (const url in this.fetchers) { + feeds[url] = this.fetchers[url].items; } this.sendSocketNotification("NEWS_ITEMS", feeds); } diff --git a/js/module_functions.js b/js/module_functions.js deleted file mode 100644 index c7ecc074a2..0000000000 --- a/js/module_functions.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Schedule the timer for the next update - * @param {object} timer The timer of the module - * @param {bigint} intervalMS interval in milliseconds - * @param {Promise} callback function to call when the timer expires - */ -const scheduleTimer = function (timer, intervalMS, callback) { - if (process.env.mmTestMode !== "true") { - // only set timer when not running in test mode - let tmr = timer; - clearTimeout(tmr); - tmr = setTimeout(function () { - callback(); - }, intervalMS); - } -}; - -module.exports = { scheduleTimer }; diff --git a/package.json b/package.json index 2510ea872d..a721f3805d 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,6 @@ ], "type": "commonjs", "imports": { - "#module_functions": { - "default": "./js/module_functions.js" - }, "#server_functions": { "default": "./js/server_functions.js" }, From 751c83bef094a464fca5732c47e163559f623c33 Mon Sep 17 00:00:00 2001 From: Veeck Date: Sat, 31 Jan 2026 23:45:46 +0100 Subject: [PATCH 358/418] Update node-ical and other deps (#4025) --- package-lock.json | 74 +++++++++++++++++++++++------------------------ package.json | 14 ++++----- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index 85df3d0c03..fbb49b0300 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,13 +27,13 @@ "ipaddr.js": "^2.3.0", "moment": "^2.30.1", "moment-timezone": "^0.6.0", - "node-ical": "^0.24.0", + "node-ical": "^0.24.1", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.30.6", - "undici": "^7.19.1", + "systeminformation": "^5.30.7", + "undici": "^7.19.2", "weathericons": "^2.1.0" }, "devDependencies": { @@ -43,7 +43,7 @@ "@vitest/ui": "^4.0.18", "cspell": "^9.6.2", "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-jsdoc": "^62.4.1", + "eslint-plugin-jsdoc": "^62.5.0", "eslint-plugin-package-json": "^0.88.2", "eslint-plugin-playwright": "^2.5.1", "express-basic-auth": "^1.2.1", @@ -52,10 +52,10 @@ "lint-staged": "^16.2.7", "markdownlint-cli2": "^0.20.0", "msw": "^2.12.7", - "playwright": "^1.58.0", + "playwright": "^1.58.1", "prettier": "^3.8.1", "prettier-plugin-jinja-template": "^2.1.0", - "stylelint": "^17.0.0", + "stylelint": "^17.1.0", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", "vitest": "^4.0.18" @@ -64,7 +64,7 @@ "node": ">=22.21.1 <23 || >=24" }, "optionalDependencies": { - "electron": "^40.0.0" + "electron": "^40.1.0" } }, "node_modules/@acemir/cssom": { @@ -5466,9 +5466,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "40.0.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-40.0.0.tgz", - "integrity": "sha512-UyBy5yJ0/wm4gNugCtNPjvddjAknMTuXR2aCHioXicH7aKRKGDBPp4xqTEi/doVcB3R+MN3wfU9o8d/9pwgK2A==", + "version": "40.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-40.1.0.tgz", + "integrity": "sha512-2j/kvw7uF0H1PnzYBzw2k2Q6q16J8ToKrtQzZfsAoXbbMY0l5gQi2DLOauIZLzwp4O01n8Wt/74JhSRwG0yj9A==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -6081,9 +6081,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "62.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.4.1.tgz", - "integrity": "sha512-HgX2iN4j104D/mCUqRbhtzSZbph+KO9jfMHiIJjJ19Q+IwLQ5Na2IqvOJYq4S+4kgvEk1w6KYF4vVus6H2wcHg==", + "version": "62.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.5.0.tgz", + "integrity": "sha512-D+1haMVDzW/ZMoPwOnsbXCK07rJtsq98Z1v+ApvDKxSzYTTcPgmFc/nyUDCGmxm2cP7g7hszyjYHO7Zodl/43w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9684,13 +9684,13 @@ } }, "node_modules/node-ical": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.24.0.tgz", - "integrity": "sha512-kBnxTUozR+vukiTaGzliasrnCXimhyvEw97ALVLoPO6xFED8V67O1/ZJbrlZ9ujMfZfiAhBkKLeJ/hU7oB5zAw==", + "version": "0.24.1", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.24.1.tgz", + "integrity": "sha512-49jmPpznMetMY+oEO+8AhZf/ccSdxuQfcOikjMzhls72OigEDtOMGFZumLHdHx6MVvJf1D7wnbbcn3kRHfIALQ==", "license": "Apache-2.0", "dependencies": { "@js-temporal/polyfill": "^0.5.1", - "rrule-temporal": "^1.3.0" + "rrule-temporal": "^1.4.5" }, "engines": { "node": ">=18" @@ -10313,13 +10313,13 @@ "license": "MIT" }, "node_modules/playwright": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.0.tgz", - "integrity": "sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==", + "version": "1.58.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.1.tgz", + "integrity": "sha512-+2uTZHxSCcxjvGc5C891LrS1/NlxglGxzrC4seZiVjcYVQfUa87wBL6rTDqzGjuoWNjnBzRqKmF6zRYGMvQUaQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.58.0" + "playwright-core": "1.58.1" }, "bin": { "playwright": "cli.js" @@ -10332,9 +10332,9 @@ } }, "node_modules/playwright-core": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.0.tgz", - "integrity": "sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==", + "version": "1.58.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.1.tgz", + "integrity": "sha512-bcWzOaTxcW+VOOGBCQgnaKToLJ65d6AqfLVKEWvexyS3AS6rbXl+xdpYRMGSRBClPvyj44njOWoxjNdL/H9UNg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -11170,9 +11170,9 @@ } }, "node_modules/rrule-temporal": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.4.4.tgz", - "integrity": "sha512-bw0Ru8aNodk6THbBfVHzwAI8Wxux8ky0IVwu2d+7iZ7j7EzgRO+MfHyAN6RA8inbmILGRNwNnh9qamcitsn73w==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.4.5.tgz", + "integrity": "sha512-g0qDEx7Wk1eaOKyZvBSTAz/DAfPnS+7GZT3vRShue6zIGCjkHWJs6evnGb7Nx2SVGKxOyMDUtKBBI53HMaFDKQ==", "license": "MIT", "dependencies": { "@js-temporal/polyfill": "^0.5.1" @@ -12103,9 +12103,9 @@ } }, "node_modules/stylelint": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.0.0.tgz", - "integrity": "sha512-saMZ2mqdQre4AfouxcbTdpVglDRcROb4MIucKHvgsDb/0IX7ODhcaz+EOIyfxAsm8Zjl/7j4hJj6MgIYYM8Xwg==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.1.0.tgz", + "integrity": "sha512-+cUX1FxkkbLX5qJRAPapUv/+v+YU3pGbWu+pHVqTXpiY0mYh3Dxfxa0bLBtVtYgOC8hIWIyX2H/3Y3LWlAevDg==", "dev": true, "funding": [ { @@ -12133,7 +12133,7 @@ "debug": "^4.4.3", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^11.1.1", + "file-entry-cache": "^11.1.2", "global-modules": "^2.0.0", "globby": "^16.1.0", "globjoin": "^0.1.4", @@ -12473,9 +12473,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.30.6", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.6.tgz", - "integrity": "sha512-LEIyK1aEv5P3BhAPW3swdlIyCihxwEq/Gki+kcONieU4PIeRCSLDuGkk0Va/56PSBgjVgEksOM88dmY6YqOyfQ==", + "version": "5.30.7", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.7.tgz", + "integrity": "sha512-33B/cftpaWdpvH+Ho9U1b08ss8GQuLxrWHelbJT1yw4M48Taj8W3ezcPuaLoIHZz5V6tVHuQPr5BprEfnBLBMw==", "license": "MIT", "os": [ "darwin", @@ -12949,9 +12949,9 @@ } }, "node_modules/undici": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.1.tgz", - "integrity": "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg==", + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.2.tgz", + "integrity": "sha512-4VQSpGEGsWzk0VYxyB/wVX/Q7qf9t5znLRgs0dzszr9w9Fej/8RVNQ+S20vdXSAyra/bJ7ZQfGv6ZMj7UEbzSg==", "license": "MIT", "engines": { "node": ">=20.18.1" diff --git a/package.json b/package.json index a721f3805d..5486309c81 100644 --- a/package.json +++ b/package.json @@ -92,13 +92,13 @@ "ipaddr.js": "^2.3.0", "moment": "^2.30.1", "moment-timezone": "^0.6.0", - "node-ical": "^0.24.0", + "node-ical": "^0.24.1", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.30.6", - "undici": "^7.19.1", + "systeminformation": "^5.30.7", + "undici": "^7.19.2", "weathericons": "^2.1.0" }, "devDependencies": { @@ -108,7 +108,7 @@ "@vitest/ui": "^4.0.18", "cspell": "^9.6.2", "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-jsdoc": "^62.4.1", + "eslint-plugin-jsdoc": "^62.5.0", "eslint-plugin-package-json": "^0.88.2", "eslint-plugin-playwright": "^2.5.1", "express-basic-auth": "^1.2.1", @@ -117,16 +117,16 @@ "lint-staged": "^16.2.7", "markdownlint-cli2": "^0.20.0", "msw": "^2.12.7", - "playwright": "^1.58.0", + "playwright": "^1.58.1", "prettier": "^3.8.1", "prettier-plugin-jinja-template": "^2.1.0", - "stylelint": "^17.0.0", + "stylelint": "^17.1.0", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", "vitest": "^4.0.18" }, "optionalDependencies": { - "electron": "^40.0.0" + "electron": "^40.1.0" }, "engines": { "node": ">=22.21.1 <23 || >=24" From 431103437c44f791b8e386294d368bd85f21bfe5 Mon Sep 17 00:00:00 2001 From: Jordan Welch Date: Sun, 1 Feb 2026 01:22:46 -0600 Subject: [PATCH 359/418] Add dark theme logo (#4026) I noticed that this icon that I normally can't read on a dark theme has a light version on the website as well! This is using [the HTML `` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/picture) that is [supported by GitHub Markdown](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#the-picture-element) CleanShot 2026-01-31 at 22 54 42@2x CleanShot 2026-01-31 at 22 54 58@2x ![CleanShot 2026-01-31 at 22 55 12](https://github.com/user-attachments/assets/97e1a56d-ae97-4dad-82d2-ebde8d92be2e) --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 38d708d372..873bf35ea0 100644 --- a/README.md +++ b/README.md @@ -51,5 +51,10 @@ If we receive enough donations we might even be able to free up some working hou To donate, please follow [this](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G5D8E9MR5DTD2&source=url) link.

- MagPi Top 50 + + + + MagPi Top 50 + +

From f6d559e3dc431c70b5371f7091f0526dbc89d22a Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 6 Feb 2026 00:09:59 +0100 Subject: [PATCH 360/418] remove kioskmode (#4027) Marked as deprecated since 2016. --- js/defaults.js | 1 - js/deprecated.js | 2 +- js/electron.js | 34 ++++----------------------- tests/unit/classes/deprecated_spec.js | 6 ++--- 4 files changed, 9 insertions(+), 34 deletions(-) diff --git a/js/defaults.js b/js/defaults.js index 58e930a38d..434b80a22a 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -9,7 +9,6 @@ const defaults = { address: address, port: port, basePath: "/", - kioskmode: false, electronOptions: {}, ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], diff --git a/js/deprecated.js b/js/deprecated.js index 10cf7ae044..8c8ef3fc54 100644 --- a/js/deprecated.js +++ b/js/deprecated.js @@ -1,4 +1,4 @@ module.exports = { - configs: ["kioskmode"], + configs: [], clock: ["secondsColor"] }; diff --git a/js/electron.js b/js/electron.js index 1d767a68c8..9b4465a1b9 100644 --- a/js/electron.js +++ b/js/electron.js @@ -60,19 +60,11 @@ function createWindow () { backgroundColor: "#000000" }; - /* - * DEPRECATED: "kioskmode" backwards compatibility, to be removed - * settings these options directly instead provides cleaner interface - */ - if (config.kioskmode) { - electronOptionsDefaults.kiosk = true; - } else { - electronOptionsDefaults.show = false; - electronOptionsDefaults.frame = false; - electronOptionsDefaults.transparent = true; - electronOptionsDefaults.hasShadow = false; - electronOptionsDefaults.fullscreen = true; - } + electronOptionsDefaults.show = false; + electronOptionsDefaults.frame = false; + electronOptionsDefaults.transparent = true; + electronOptionsDefaults.hasShadow = false; + electronOptionsDefaults.fullscreen = true; const electronOptions = Object.assign({}, electronOptionsDefaults, config.electronOptions); @@ -132,22 +124,6 @@ function createWindow () { mainWindow = null; }); - if (config.kioskmode) { - mainWindow.on("blur", function () { - mainWindow.focus(); - }); - - mainWindow.on("leave-full-screen", function () { - mainWindow.setFullScreen(true); - }); - - mainWindow.on("resize", function () { - setTimeout(function () { - mainWindow.reload(); - }, 1000); - }); - } - //remove response headers that prevent sites of being embedded into iframes if configured mainWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => { let curHeaders = details.responseHeaders; diff --git a/tests/unit/classes/deprecated_spec.js b/tests/unit/classes/deprecated_spec.js index ef78db911d..b1e6aa631d 100644 --- a/tests/unit/classes/deprecated_spec.js +++ b/tests/unit/classes/deprecated_spec.js @@ -5,11 +5,11 @@ describe("Deprecated", () => { expect(typeof deprecated).toBe("object"); }); - it("should contain configs array with deprecated options as strings", () => { - expect(Array.isArray(["deprecated.configs"])).toBe(true); + it("should contain clock array with deprecated options as strings", () => { + expect(Array.isArray(["deprecated.clock"])).toBe(true); for (let option of deprecated.configs) { expect(typeof option).toBe("string"); } - expect(deprecated.configs).toEqual(expect.arrayContaining(["kioskmode"])); + expect(deprecated.clock).toEqual(expect.arrayContaining(["secondsColor"])); }); }); From f9f3461f13ef9be395ee7358d5bed670bae7ba62 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 6 Feb 2026 00:11:53 +0100 Subject: [PATCH 361/418] calendar.js: remove useless hasCalendarURL function (#4028) Found this while debugging. The `hasCalendarURL` function does a check if the url is in the config. But the calendar sees only his own config part, so this check is always true (tested with more than one calendar module in `config.js`). --- defaultmodules/calendar/calendar.js | 79 +++++++++++------------------ 1 file changed, 30 insertions(+), 49 deletions(-) diff --git a/defaultmodules/calendar/calendar.js b/defaultmodules/calendar/calendar.js index 51270497df..0d8575c810 100644 --- a/defaultmodules/calendar/calendar.js +++ b/defaultmodules/calendar/calendar.js @@ -169,9 +169,7 @@ Module.register("calendar", { notificationReceived (notification, payload, sender) { if (notification === "FETCH_CALENDAR") { - if (this.hasCalendarURL(payload.url)) { - this.sendSocketNotification(notification, { url: payload.url, id: this.identifier }); - } + this.sendSocketNotification(notification, { url: payload.url, id: this.identifier }); } }, @@ -183,40 +181,38 @@ Module.register("calendar", { } if (notification === "CALENDAR_EVENTS") { - if (this.hasCalendarURL(payload.url)) { - // have we received events for this url - if (!this.calendarData[payload.url]) { - // no, setup the structure to hold the info - this.calendarData[payload.url] = { events: null, checksum: null }; - } - // save the event list - this.calendarData[payload.url].events = payload.events; - - this.error = null; - this.loaded = true; + // have we received events for this url + if (!this.calendarData[payload.url]) { + // no, setup the structure to hold the info + this.calendarData[payload.url] = { events: null, checksum: null }; + } + // save the event list + this.calendarData[payload.url].events = payload.events; - if (this.config.broadcastEvents) { - this.broadcastEvents(); - } - // if the checksum is the same - if (this.calendarData[payload.url].checksum === payload.checksum) { - // then don't update the UI - return; - } - // haven't seen or the checksum is different - this.calendarData[payload.url].checksum = payload.checksum; + this.error = null; + this.loaded = true; - if (!this.config.updateOnFetch) { - if (this.calendarDisplayer[payload.url] === undefined) { - // calendar will never displayed, so display it - this.updateDom(this.config.animationSpeed); - // set this calendar as displayed - this.calendarDisplayer[payload.url] = true; - } else { - Log.debug("[calendar] DOM not updated waiting self update()"); - } - return; + if (this.config.broadcastEvents) { + this.broadcastEvents(); + } + // if the checksum is the same + if (this.calendarData[payload.url].checksum === payload.checksum) { + // then don't update the UI + return; + } + // haven't seen or the checksum is different + this.calendarData[payload.url].checksum = payload.checksum; + + if (!this.config.updateOnFetch) { + if (this.calendarDisplayer[payload.url] === undefined) { + // calendar will never displayed, so display it + this.updateDom(this.config.animationSpeed); + // set this calendar as displayed + this.calendarDisplayer[payload.url] = true; + } else { + Log.debug("[calendar] DOM not updated waiting self update()"); } + return; } } else if (notification === "CALENDAR_ERROR") { let error_message = this.translate(payload.error_type); @@ -580,21 +576,6 @@ Module.register("calendar", { return wrapper; }, - /** - * Checks if this config contains the calendar url. - * @param {string} url The calendar url - * @returns {boolean} True if the calendar config contains the url, False otherwise - */ - hasCalendarURL (url) { - for (const calendar of this.config.calendars) { - if (calendar.url === url) { - return true; - } - } - - return false; - }, - /** * converts the given timestamp to a moment with a timezone * @param {number} timestamp timestamp from an event From 9dd964e004e1b7ce9c46112bdd3dad0913381914 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 6 Feb 2026 00:21:35 +0100 Subject: [PATCH 362/418] change loading config.js, allow variables in config.js and try to protect sensitive data (#4029) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Loading `config.js` ### Previously Loaded on server-side in `app.js` and in the browser by including `config.js` in `index.html`. The web server has an endpoint `/config` providing the content of server loaded `config.js`. ### Now Loaded only on server-side in `app.js`. The browser loads the content using the web server endpoint `/config`. So the server has control what to provide to the clients. Loading the `config.js` was moved to `Utils.js` so that `check_config.js` can use the same functions. ## Using environment variables in `config.js` ### Previously Environment variables were not allowed in `config.js`. The workaround was to create a `config.js.template` with curly braced bash variables allowed. While starting the app the `config.js.template` was converted via `envsub` into a `config.js`. ### Now Curly braced bash variables are allowed in `config.js`. Because only the server loads `config.js` he can substitute the variables while loading. ## Secrets in MagicMirror² To be honest, this is a mess. ### Previously All content defined in the `config` directory was reachable from the browser. Everyone with access to the site could see all stuff defined in the configuration e.g. using the url http://ip:8080/config. This included api keys and other secrets. So sharing a MagicMirror² url to others or running MagicMirror² without authentication as public website was not possible. ### Now With this PR we add (beta) functionality to protect sensitive data. This is only possible for modules running with a `node_helper`. For modules running in the browser only (e.g. default `weather` module), there is no way to hide data (per construction). This does not mean, that every module with `node_helper` is safe, e.g. the default `calendar` module is not safe because it uses the calendar url's as sort of id and sends them to the client. For adding more security you have to set `hideConfigSecrets: true` in `config.js`. With this: - `config/config.env` is not deliverd to the browser - the contents of environment variables beginning with `SECRET_` are not published to the clients This is a first step to protect sensitive data and you can at least protect some secrets. --- cspell.config.json | 5 + eslint.config.mjs | 2 +- index.html | 2 +- js/app.js | 125 +- js/check_config.js | 143 +- js/defaults.js | 1 + js/main.js | 18 +- js/node_helper.js | 16 +- js/server.js | 21 +- js/server_functions.js | 17 +- js/utils.js | 314 +++- package-lock.json | 1302 +---------------- package.json | 1 - ..._variable.js.template => port_variable.js} | 0 14 files changed, 352 insertions(+), 1615 deletions(-) rename tests/configs/{port_variable.js.template => port_variable.js} (100%) diff --git a/cspell.config.json b/cspell.config.json index 33ff5bcb04..564f7d205b 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -179,6 +179,7 @@ "Lightspeed", "loadingcircle", "locationforecast", + "logg", "lockstring", "lstrip", "Luciella", @@ -285,6 +286,8 @@ "Teeuw", "Teil", "TESTMODE", + "testpass", + "testuser", "thomasrockhu", "thumbslider", "timeformat", @@ -307,6 +310,7 @@ "VEVENT", "vgtu", "Vitest", + "VCALENDAR", "Voelt", "Vorberechnung", "vppencilsharpener", @@ -326,6 +330,7 @@ "winddirection", "windgusts", "windspeed", + "WKST", "Woolridge", "worktree", "Wsymb", diff --git a/eslint.config.mjs b/eslint.config.mjs index d6cdcdc311..b1c90ca6c3 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,7 +9,7 @@ import stylistic from "@stylistic/eslint-plugin"; import vitest from "@vitest/eslint-plugin"; export default defineConfig([ - globalIgnores(["config/**", "modules/**/*", "js/positions.js"]), + globalIgnores(["config/**", "modules/**/*", "js/positions.js", "tests/configs/port_variable.js"]), { files: ["**/*.js"], languageOptions: { diff --git a/index.html b/index.html index dcd354b776..af9df8560d 100644 --- a/index.html +++ b/index.html @@ -44,7 +44,6 @@ - @@ -52,6 +51,7 @@ + diff --git a/js/app.js b/js/app.js index 3d7e35d101..3de59c316b 100644 --- a/js/app.js +++ b/js/app.js @@ -4,7 +4,6 @@ require("./alias-resolver"); const fs = require("node:fs"); const path = require("node:path"); const Spawn = require("node:child_process").spawn; -const envsub = require("envsub"); const Log = require("logger"); // global absolute root path @@ -15,7 +14,7 @@ const Utils = require(`${__dirname}/utils`); // used to control fetch timeout for node_helpers const { setGlobalDispatcher, Agent } = require("undici"); -const { getEnvVarsAsObj, getConfigFilePath } = require("#server_functions"); +const { getEnvVarsAsObj } = require("#server_functions"); // common timeout value, provide environment override in case const fetch_timeout = process.env.mmFetchTimeout !== undefined ? process.env.mmFetchTimeout : 30000; @@ -59,122 +58,6 @@ function App () { let defaultModules; let env; - /** - * Loads the config file. Combines it with the defaults and returns the config - * @async - * @returns {Promise} the loaded config or the defaults if something goes wrong - */ - async function loadConfig () { - Log.log("Loading config ..."); - const defaults = require(`${__dirname}/defaults`); - if (global.mmTestMode) { - // if we are running in test mode - defaults.address = "0.0.0.0"; - } - - // For this check proposed to TestSuite - // https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8 - const configFilename = getConfigFilePath(); - let templateFile = `${configFilename}.template`; - - // check if templateFile exists - try { - fs.accessSync(templateFile, fs.constants.F_OK); - } catch (err) { - templateFile = null; - Log.log("config template file not exists, no envsubst"); - } - - if (templateFile) { - // save current config.js - try { - if (fs.existsSync(configFilename)) { - fs.copyFileSync(configFilename, `${configFilename}-old`); - } - } catch (err) { - Log.warn(`Could not copy ${configFilename}: ${err.message}`); - } - - // check if config.env exists - const envFiles = []; - const configEnvFile = `${configFilename.substr(0, configFilename.lastIndexOf("."))}.env`; - try { - if (fs.existsSync(configEnvFile)) { - envFiles.push(configEnvFile); - } - } catch (err) { - Log.log(`${configEnvFile} does not exist. ${err.message}`); - } - - let options = { - all: true, - diff: false, - envFiles: envFiles, - protect: false, - syntax: "default", - system: true - }; - - // envsubst variables in templateFile and create new config.js - // naming for envsub must be templateFile and outputFile - const outputFile = configFilename; - try { - await envsub({ templateFile, outputFile, options }); - } catch (err) { - Log.error(`Could not envsubst variables: ${err.message}`); - } - } - - require(`${global.root_path}/js/check_config.js`); - - try { - fs.accessSync(configFilename, fs.constants.F_OK); - const c = require(configFilename); - if (Object.keys(c).length === 0) { - Log.error("WARNING! Config file appears empty, maybe missing module.exports last line?"); - } - checkDeprecatedOptions(c); - return Object.assign(defaults, c); - } catch (e) { - if (e.code === "ENOENT") { - Log.error("WARNING! Could not find config file. Please create one. Starting with default configuration."); - } else if (e instanceof ReferenceError || e instanceof SyntaxError) { - Log.error(`WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: ${e.stack}`); - } else { - Log.error(`WARNING! Could not load config file. Starting with default configuration. Error found: ${e}`); - } - } - - return defaults; - } - - /** - * Checks the config for deprecated options and throws a warning in the logs - * if it encounters one option from the deprecated.js list - * @param {object} userConfig The user config - */ - function checkDeprecatedOptions (userConfig) { - const deprecated = require(`${global.root_path}/js/deprecated`); - - // check for deprecated core options - const deprecatedOptions = deprecated.configs; - const usedDeprecated = deprecatedOptions.filter((option) => userConfig.hasOwnProperty(option)); - if (usedDeprecated.length > 0) { - Log.warn(`WARNING! Your config is using deprecated option(s): ${usedDeprecated.join(", ")}. Check README and Documentation for more up-to-date ways of getting the same functionality.`); - } - - // check for deprecated module options - for (const element of userConfig.modules) { - if (deprecated[element.module] !== undefined && element.config !== undefined) { - const deprecatedModuleOptions = deprecated[element.module]; - const usedDeprecatedModuleOptions = deprecatedModuleOptions.filter((option) => element.config.hasOwnProperty(option)); - if (usedDeprecatedModuleOptions.length > 0) { - Log.warn(`WARNING! Your config for module ${element.module} is using deprecated option(s): ${usedDeprecatedModuleOptions.join(", ")}. Check README and Documentation for more up-to-date ways of getting the same functionality.`); - } - } - } - } - /** * Loads a specific module. * @param {string} module The name of the module (including subpath). @@ -289,7 +172,9 @@ function App () { * @returns {Promise} the config used */ this.start = async function () { - config = await loadConfig(); + const configObj = Utils.loadConfig(); + config = configObj.fullConf; + Utils.checkConfigFile(configObj); global.defaultModulesDir = config.defaultModulesDir; defaultModules = require(`${global.root_path}/${global.defaultModulesDir}/defaultmodules`); @@ -331,7 +216,7 @@ function App () { await loadModules(modules); - httpServer = new Server(config); + httpServer = new Server(configObj); const { app, io } = await httpServer.open(); Log.log("Server started ..."); diff --git a/js/check_config.js b/js/check_config.js index f2c9b2b7a2..3ed042c10b 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -2,154 +2,13 @@ require("./alias-resolver"); const path = require("node:path"); -const fs = require("node:fs"); -const { styleText } = require("node:util"); -const Ajv = require("ajv"); -const globals = require("globals"); -const { Linter } = require("eslint"); const Log = require("logger"); const rootPath = path.resolve(`${__dirname}/../`); const Utils = require(`${rootPath}/js/utils.js`); -const linter = new Linter({ configType: "flat" }); -const ajv = new Ajv(); - -/** - * Returns a string with path of configuration file. - * Check if set by environment variable MM_CONFIG_FILE - * @returns {string} path and filename of the config file - */ -function getConfigFile () { - // FIXME: This function should be in core. Do you want refactor me ;) ?, be good! - return path.resolve(process.env.MM_CONFIG_FILE || `${rootPath}/config/config.js`); -} - -/** - * Checks the config file using eslint. - */ -function checkConfigFile () { - const configFileName = getConfigFile(); - - // Check if file exists and is accessible - try { - fs.accessSync(configFileName, fs.constants.R_OK); - } catch (error) { - if (error.code === "ENOENT") { - Log.error(`File not found: ${configFileName}`); - } else if (error.code === "EACCES") { - Log.error(`No permission to read config file: ${configFileName}`); - } else { - Log.error(`Cannot access config file: ${configFileName}\n${error.message}`); - } - process.exit(1); - } - - // Validate syntax of the configuration file. - Log.info(`Checking config file ${configFileName} ...`); - - // I'm not sure if all ever is utf-8 - const configFile = fs.readFileSync(configFileName, "utf-8"); - - const errors = linter.verify( - configFile, - { - languageOptions: { - ecmaVersion: "latest", - globals: { - ...globals.browser, - ...globals.node - } - }, - rules: { - "no-sparse-arrays": "error", - "no-undef": "error" - } - }, - configFileName - ); - - if (errors.length === 0) { - Log.info(styleText("green", "Your configuration file doesn't contain syntax errors :)")); - validateModulePositions(configFileName); - } else { - let errorMessage = "Your configuration file contains syntax errors :("; - - for (const error of errors) { - errorMessage += `\nLine ${error.line} column ${error.column}: ${error.message}`; - } - Log.error(errorMessage); - process.exit(1); - } -} - -/** - * - * @param {string} configFileName - The path and filename of the configuration file to validate. - */ -function validateModulePositions (configFileName) { - Log.info("Checking modules structure configuration ..."); - - const positionList = Utils.getModulePositions(); - - // Make Ajv schema configuration of modules config - // Only scan "module" and "position" - const schema = { - type: "object", - properties: { - modules: { - type: "array", - items: { - type: "object", - properties: { - module: { - type: "string" - }, - position: { - type: "string" - } - }, - required: ["module"] - } - } - } - }; - - // Scan all modules - const validate = ajv.compile(schema); - const data = require(configFileName); - - const valid = validate(data); - if (valid) { - Log.info(styleText("green", "Your modules structure configuration doesn't contain errors :)")); - - // Check for unknown positions (warning only, not an error) - if (data.modules) { - for (const [index, module] of data.modules.entries()) { - if (module.position && !positionList.includes(module.position)) { - Log.warn(`Module ${index} ("${module.module}") uses unknown position: "${module.position}"`); - Log.warn(`Known positions are: ${positionList.join(", ")}`); - } - } - } - } else { - const module = validate.errors[0].instancePath.split("/")[2]; - const position = validate.errors[0].instancePath.split("/")[3]; - let errorMessage = "This module configuration contains errors:"; - errorMessage += `\n${JSON.stringify(data.modules[module], null, 2)}`; - if (position) { - errorMessage += `\n${position}: ${validate.errors[0].message}`; - errorMessage += `\n${JSON.stringify(validate.errors[0].params.allowedValues, null, 2).slice(1, -1)}`; - } else { - errorMessage += validate.errors[0].message; - } - Log.error(errorMessage); - process.exit(1); - } -} - try { - checkConfigFile(); + Utils.checkConfigFile(); } catch (error) { const message = error && error.message ? error.message : error; Log.error(`Unexpected error: ${message}`); diff --git a/js/defaults.js b/js/defaults.js index 434b80a22a..bd590894cb 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -20,6 +20,7 @@ const defaults = { customCss: "config/custom.css", foreignModulesDir: "modules", defaultModulesDir: "defaultmodules", + hideConfigSecrets: false, // httpHeaders used by helmet, see https://helmetjs.github.io/. You can add other/more object values by overriding this in config.js, // e.g. you need to add `frameguard: false` for embedding MagicMirror in another website, see https://github.com/MagicMirrorOrg/MagicMirror/issues/2847 httpHeaders: { contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false }, diff --git a/js/main.js b/js/main.js index 6f7f65f8b2..f5c9e75e5f 100644 --- a/js/main.js +++ b/js/main.js @@ -470,17 +470,15 @@ const MM = (function () { }; /** - * Loads the core config and combines it with the system defaults. + * Loads the core config from the server (already combined with the system defaults). */ - const loadConfig = function () { - // FIXME: Think about how to pass config around without breaking tests - if (typeof config === "undefined") { - config = defaults; - Log.error("Config file is missing! Please create a config file."); - return; + const loadConfig = async function () { + try { + const res = await fetch(new URL("config/", `${location.origin}${config.basePath}`)); + config = JSON.parse(await res.text()); + } catch (error) { + Log.error("Unable to retrieve config", error); } - - config = Object.assign({}, defaults, config); }; /** @@ -582,7 +580,7 @@ const MM = (function () { */ async init () { Log.info("Initializing MagicMirror²."); - loadConfig(); + await loadConfig(); Log.setLogLevel(config.logLevel); diff --git a/js/node_helper.js b/js/node_helper.js index cbe30edda0..952db968c6 100644 --- a/js/node_helper.js +++ b/js/node_helper.js @@ -27,7 +27,7 @@ const NodeHelper = Class.extend({ /** * This method is called when a socket notification arrives. * @param {string} notification The identifier of the notification. - * @param {object} payload The payload of the notification. + * @param {object} payload The payload of the notification. */ socketNotificationReceived (notification, payload) { Log.log(`${this.name} received a socket notification: ${notification} - Payload: ${payload}`); @@ -88,7 +88,19 @@ const NodeHelper = Class.extend({ io.of(this.name).on("connection", (socket) => { // register catch all. socket.onAny((notification, payload) => { - this.socketNotificationReceived(notification, payload); + if (config.hideConfigSecrets && payload && typeof payload === "object") { + try { + const payloadStr = JSON.stringify(payload).replaceAll(/\*\*(SECRET_.*)\*\*/g, (match, group) => { + return process.env[group]; + }); + this.socketNotificationReceived(notification, JSON.parse(payloadStr)); + } catch (e) { + Log.error("Error substituting variables in payload: ", e); + this.socketNotificationReceived(notification, payload); + } + } else { + this.socketNotificationReceived(notification, payload); + } }); }); } diff --git a/js/server.js b/js/server.js index e96a6cc862..3bf892097f 100644 --- a/js/server.js +++ b/js/server.js @@ -6,7 +6,7 @@ const express = require("express"); const helmet = require("helmet"); const socketio = require("socket.io"); const Log = require("logger"); -const { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars } = require("#server_functions"); +const { cors, getHtml, getVersion, getStartup, getEnvVars } = require("#server_functions"); const { ipAccessControl } = require(`${__dirname}/ip_access_control`); @@ -14,10 +14,11 @@ const vendor = require(`${__dirname}/vendor`); /** * Server - * @param {object} config The MM config + * @param {object} configObj The MM config full and redacted * @class */ -function Server (config) { +function Server (configObj) { + const config = configObj.fullConf; const app = express(); const port = process.env.MM_PORT || config.port; const serverSockets = new Set(); @@ -89,6 +90,12 @@ function Server (config) { app.use(helmet(config.httpHeaders)); app.use("/js", express.static(__dirname)); + if (config.hideConfigSecrets) { + app.get("/config/config.env", (req, res) => { + res.status(404).send("\n\n\n\nError\n\n\n
Cannot GET /config/config.env
\n\n"); + }); + } + 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)) { const dirArr = value.split("/"); @@ -99,6 +106,14 @@ function Server (config) { app.use(directory, express.static(path.resolve(global.root_path + directory))); } + const getConfig = (req, res) => { + if (config.hideConfigSecrets) { + res.send(configObj.redactedConf); + } else { + res.send(configObj.fullConf); + } + }; + app.get("/cors", async (req, res) => await cors(req, res)); app.get("/version", (req, res) => getVersion(req, res)); diff --git a/js/server_functions.js b/js/server_functions.js index aedf6fa43c..85e674d816 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -4,15 +4,6 @@ const Log = require("logger"); const startUp = new Date(); -/** - * Gets the config. - * @param {Request} req - the request - * @param {Response} res - the result - */ -function getConfig (req, res) { - res.send(config); -} - /** * Gets the startup time. * @param {Request} req - the request @@ -118,12 +109,6 @@ function getHtml (req, res) { html = html.replace("#VERSION#", global.version); html = html.replace("#TESTMODE#", global.mmTestMode); - let configFile = "config/config.js"; - if (typeof global.configuration_file !== "undefined") { - configFile = global.configuration_file; - } - html = html.replace("#CONFIG_FILE#", configFile); - res.send(html); } @@ -201,4 +186,4 @@ function getConfigFilePath () { return path.resolve(global.configuration_file || `${global.root_path}/config/config.js`); } -module.exports = { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath }; +module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath }; diff --git a/js/utils.js b/js/utils.js index 42a651dcc9..258167afc7 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,51 +1,289 @@ const fs = require("node:fs"); -const Log = require("logger"); +const { loadEnvFile } = require("node:process"); const modulePositions = []; // will get list from index.html const regionRegEx = /"region ([^"]*)/i; const indexFileName = "index.html"; const discoveredPositionsJSFilename = "js/positions.js"; -module.exports = { - - // return all available module positions - getAvailableModulePositions () { - return modulePositions; - }, - - // return if position is on modulePositions Array (true/false) - moduleHasValidPosition (position) { - if (this.getAvailableModulePositions().indexOf(position) === -1) return false; - return true; - }, - - getModulePositions () { - // if not already discovered - if (modulePositions.length === 0) { - // get the lines of the index.html - const lines = fs.readFileSync(indexFileName).toString().split("\n"); - // loop thru the lines - lines.forEach((line) => { - // run the regex on each line - const results = regionRegEx.exec(line); - // if the regex returned something - if (results && results.length > 0) { - // get the position parts and replace space with underscore - const positionName = results[1].replace(" ", "_"); - // add it to the list only if not already present (avoid duplicates) - if (!modulePositions.includes(positionName)) { - modulePositions.push(positionName); - } +const { styleText } = require("node:util"); +const Log = require("logger"); +const Ajv = require("ajv"); +const globals = require("globals"); +const { Linter } = require("eslint"); +const { getConfigFilePath } = require("#server_functions"); + +const linter = new Linter({ configType: "flat" }); +const ajv = new Ajv(); + +const requireFromString = (src) => { + const m = new module.constructor(); + m._compile(src, ""); + return m.exports; +}; + +// return all available module positions +const getAvailableModulePositions = () => { + return modulePositions; +}; + +// return if position is on modulePositions Array (true/false) +const moduleHasValidPosition = (position) => { + if (getAvailableModulePositions().indexOf(position) === -1) return false; + return true; +}; + +const getModulePositions = () => { + // if not already discovered + if (modulePositions.length === 0) { + // get the lines of the index.html + const lines = fs.readFileSync(indexFileName).toString().split("\n"); + // loop thru the lines + lines.forEach((line) => { + // run the regex on each line + const results = regionRegEx.exec(line); + // if the regex returned something + if (results && results.length > 0) { + // get the position parts and replace space with underscore + const positionName = results[1].replace(" ", "_"); + // add it to the list only if not already present (avoid duplicates) + if (!modulePositions.includes(positionName)) { + modulePositions.push(positionName); + } + } + }); + try { + fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`); + } + catch (error) { + Log.error("unable to write js/positions.js with the discovered module positions\nmake the MagicMirror/js folder writeable by the user starting MagicMirror"); + } + } + // return the list to the caller + return modulePositions; +}; + +/** + * Checks the config for deprecated options and throws a warning in the logs + * if it encounters one option from the deprecated.js list + * @param {object} userConfig The user config + */ +const checkDeprecatedOptions = (userConfig) => { + const deprecated = require(`${global.root_path}/js/deprecated`); + + // check for deprecated core options + const deprecatedOptions = deprecated.configs; + const usedDeprecated = deprecatedOptions.filter((option) => userConfig.hasOwnProperty(option)); + if (usedDeprecated.length > 0) { + Log.warn(`WARNING! Your config is using deprecated option(s): ${usedDeprecated.join(", ")}. Check README and Documentation for more up-to-date ways of getting the same functionality.`); + } + + // check for deprecated module options + for (const element of userConfig.modules) { + if (deprecated[element.module] !== undefined && element.config !== undefined) { + const deprecatedModuleOptions = deprecated[element.module]; + const usedDeprecatedModuleOptions = deprecatedModuleOptions.filter((option) => element.config.hasOwnProperty(option)); + if (usedDeprecatedModuleOptions.length > 0) { + Log.warn(`WARNING! Your config for module ${element.module} is using deprecated option(s): ${usedDeprecatedModuleOptions.join(", ")}. Check README and Documentation for more up-to-date ways of getting the same functionality.`); + } + } + } +}; + +/** + * Loads the config file. Combines it with the defaults and returns the config + * @returns {object} an object holding full and redacted config + */ +const loadConfig = () => { + Log.log("Loading config ..."); + const defaults = require(`${__dirname}/defaults`); + if (global.mmTestMode) { + // if we are running in test mode + defaults.address = "0.0.0.0"; + } + + // For this check proposed to TestSuite + // https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8 + const configFilename = getConfigFilePath(); + let templateFile = `${configFilename}.template`; + + // check if templateFile exists + 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) { + // no action + } + + // check if config.env exists + const configEnvFile = `${configFilename.substr(0, configFilename.lastIndexOf("."))}.env`; + try { + if (fs.existsSync(configEnvFile)) { + // load content into process.env + loadEnvFile(configEnvFile); + } + } catch (error) { + Log.log(`${configEnvFile} does not exist. ${error.message}`); + } + + // Load config.js and catch errors if not accessible + try { + let configContent = fs.readFileSync(configFilename, "utf-8"); + let configContentFull = configContent; + let configContentRedacted = configContent; + Object.keys(process.env).forEach((env) => { + configContentFull = configContentFull.replaceAll(`\${${env}}`, process.env[env]); + if (env.startsWith("SECRET_")) { + configContentRedacted = configContentRedacted.replaceAll(`"\${${env}}"`, `"**${env}**"`); + configContentRedacted = configContentRedacted.replaceAll(`\${${env}}`, `"**${env}**"`); + } else { + configContentRedacted = configContentRedacted.replaceAll(`\${${env}}`, process.env[env]); + } + }); + const configObj = { + configFilename: configFilename, + configContentFull: configContentFull, + configContentRedacted: configContentRedacted, + redactedConf: Object.assign({}, defaults, requireFromString(configContentRedacted)), + fullConf: Object.assign({}, defaults, requireFromString(configContentFull)) + }; + + if (Object.keys(configObj.fullConf).length === 0) { + Log.error("WARNING! Config file appears empty, maybe missing module.exports last line?"); + } + checkDeprecatedOptions(configObj.fullConf); + + try { + const cfg = `let config = { basePath: "${configObj.fullConf.basePath}"};`; + fs.writeFileSync(`${global.root_path}/config/basepath.js`, cfg, "utf-8"); + } catch (error) { + Log.error(`Could not write config/basepath.js file: ${error.message}`); + } + + return configObj; + + } catch (error) { + if (error.code === "ENOENT") { + Log.error(`Could not find config file: ${configFilename}`); + } else if (error.code === "EACCES") { + Log.error(`No permission to read config file: ${configFilename}`); + } else { + Log.error(`Cannot access config file: ${configFilename}\n${error.message}`); + } + process.exit(1); + } + return {}; +}; + +/** + * Checks the config file using eslint. + * @param {object} configObject the configuration object + */ +const checkConfigFile = (configObject) => { + let configObj = configObject; + if (!configObj) configObj = loadConfig(); + const configFileName = configObj.configFilename; + + // Validate syntax of the configuration file. + Log.info(`Checking config file ${configFileName} ...`); + + // I'm not sure if all ever is utf-8 + const configFile = configObj.configContentFull; + + const errors = linter.verify( + configFile, + { + languageOptions: { + ecmaVersion: "latest", + globals: { + ...globals.browser, + ...globals.node + } + }, + rules: { + "no-sparse-arrays": "error", + "no-undef": "error" + } + }, + configFileName + ); + + if (errors.length === 0) { + Log.info(styleText("green", "Your configuration file doesn't contain syntax errors :)")); + validateModulePositions(configObj.fullConf); + } else { + let errorMessage = "Your configuration file contains syntax errors :("; + + for (const error of errors) { + errorMessage += `\nLine ${error.line} column ${error.column}: ${error.message}`; + } + Log.error(errorMessage); + process.exit(1); + } +}; + +/** + * + * @param {string} data - The content of the configuration file to validate. + */ +const validateModulePositions = (data) => { + Log.info("Checking modules structure configuration ..."); + + const positionList = getModulePositions(); + + // Make Ajv schema configuration of modules config + // Only scan "module" and "position" + const schema = { + type: "object", + properties: { + modules: { + type: "array", + items: { + type: "object", + properties: { + module: { + type: "string" + }, + position: { + type: "string" + } + }, + required: ["module"] } - }); - try { - fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`); } - catch (error) { - Log.error("unable to write js/positions.js with the discovered module positions\nmake the MagicMirror/js folder writeable by the user starting MagicMirror"); + } + }; + + // Scan all modules + const validate = ajv.compile(schema); + + const valid = validate(data); + if (valid) { + Log.info(styleText("green", "Your modules structure configuration doesn't contain errors :)")); + + // Check for unknown positions (warning only, not an error) + if (data.modules) { + for (const [index, module] of data.modules.entries()) { + if (module.position && !positionList.includes(module.position)) { + Log.warn(`Module ${index} ("${module.module}") uses unknown position: "${module.position}"`); + Log.warn(`Known positions are: ${positionList.join(", ")}`); + } } } - // return the list to the caller - return modulePositions; + } else { + const module = validate.errors[0].instancePath.split("/")[2]; + const position = validate.errors[0].instancePath.split("/")[3]; + let errorMessage = "This module configuration contains errors:"; + errorMessage += `\n${JSON.stringify(data.modules[module], null, 2)}`; + if (position) { + errorMessage += `\n${position}: ${validate.errors[0].message}`; + errorMessage += `\n${JSON.stringify(validate.errors[0].params.allowedValues, null, 2).slice(1, -1)}`; + } else { + errorMessage += validate.errors[0].message; + } + Log.error(errorMessage); + process.exit(1); } }; + +module.exports = { loadConfig, getModulePositions, moduleHasValidPosition, getAvailableModulePositions, checkConfigFile }; diff --git a/package-lock.json b/package-lock.json index fbb49b0300..e815ee3b5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "animate.css": "^4.1.1", "console-stamp": "^3.1.2", "croner": "^9.1.0", - "envsub": "^4.1.0", "eslint": "^9.39.2", "express": "^5.2.1", "feedme": "^2.0.2", @@ -3895,22 +3894,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-timsort": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", @@ -3918,27 +3901,6 @@ "dev": true, "license": "MIT" }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -4001,30 +3963,6 @@ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "license": "MIT" }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -4084,12 +4022,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "license": "MIT" - }, "node_modules/bodec": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", @@ -4228,24 +4160,6 @@ "@keyv/serialize": "^1.1.1" } }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -5109,57 +5023,6 @@ "node": ">=20" } }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/dateformat": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", @@ -5272,6 +5135,7 @@ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "license": "MIT", + "optional": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -5289,6 +5153,7 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "license": "MIT", + "optional": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -5381,15 +5246,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -5653,48 +5509,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/envsub": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/envsub/-/envsub-4.1.0.tgz", - "integrity": "sha512-B44hta3xNFu6+zDhOha1TIrZkQHGDO3G5K8D2sJIkm/s3XyQjxWBGp1B+b/Y74Go1PqMP+cp8moPR4JullnD9Q==", - "license": "ISC", - "dependencies": { - "bluebird": "^3.7.2", - "chalk": "^3.0.0", - "commander": "^4.0.1", - "diff": "^4.0.1", - "handlebars": "^4.5.3", - "lodash": "^4.17.15", - "replace-last": "^1.2.6", - "string.prototype.matchall": "^4.0.8" - }, - "bin": { - "envsub": "bin/envsub.js", - "envsubh": "bin/envsubh.js" - } - }, - "node_modules/envsub/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/envsub/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -5705,74 +5519,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-abstract": { - "version": "1.24.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", - "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -5810,38 +5556,6 @@ "node": ">= 0.4" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -6725,21 +6439,6 @@ } } }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -6796,44 +6495,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/gensequence": { "version": "8.0.8", "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-8.0.8.tgz", @@ -6920,23 +6581,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-tsconfig": { "version": "4.13.0", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", @@ -7097,6 +6741,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "license": "MIT", + "optional": true, "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -7201,39 +6846,6 @@ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -7248,6 +6860,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "license": "MIT", + "optional": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -7255,21 +6868,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -7282,21 +6880,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hashery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.4.0.tgz", @@ -7611,24 +7194,10 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "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==", + "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==", "license": "MIT", "engines": { "node": ">= 12" @@ -7669,23 +7238,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -7693,40 +7245,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -7739,34 +7257,6 @@ "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -7782,39 +7272,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-decimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", @@ -7835,21 +7292,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-fullwidth-code-point": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", @@ -7866,25 +7308,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7908,30 +7331,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-node-process": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", @@ -7948,22 +7347,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-path-inside": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", @@ -8013,148 +7396,6 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -9434,15 +8675,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -9668,12 +8900,6 @@ "node": ">= 0.6" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "license": "MIT" - }, "node_modules/netmask": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", @@ -9785,30 +9011,11 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/obug": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", @@ -9881,23 +9088,6 @@ "dev": true, "license": "MIT" }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -10514,15 +9704,6 @@ "node": ">=10" } }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -10864,72 +10045,21 @@ "license": "MIT", "dependencies": { "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + }, + "engines": { + "node": ">=8.10.0" } }, - "node_modules/replace-last": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/replace-last/-/replace-last-1.2.6.tgz", - "integrity": "sha512-Cj+MK38VtNu1S5J73mEZY3ciQb9dJajNq1Q8inP4dn/MhJMjHwoAF3Z3FjspwAEV9pfABl565MQucmrjOkty4g==", - "license": "ISC", + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/require-directory": { @@ -11222,25 +10352,6 @@ ], "license": "MIT" }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -11248,39 +10359,6 @@ "dev": true, "license": "MIT" }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -11415,52 +10493,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -11944,19 +10976,6 @@ "dev": true, "license": "MIT" }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/strict-event-emitter": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", @@ -11991,89 +11010,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/strip-ansi": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", @@ -12821,80 +11757,6 @@ "node": ">= 0.6" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -12917,37 +11779,6 @@ "dev": true, "license": "MIT" }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/undici": { "version": "7.19.2", "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.2.tgz", @@ -13377,91 +12208,6 @@ "node": ">= 8" } }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.20", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", - "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -13488,12 +12234,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "license": "MIT" - }, "node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", diff --git a/package.json b/package.json index 5486309c81..6e969dc425 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,6 @@ "animate.css": "^4.1.1", "console-stamp": "^3.1.2", "croner": "^9.1.0", - "envsub": "^4.1.0", "eslint": "^9.39.2", "express": "^5.2.1", "feedme": "^2.0.2", diff --git a/tests/configs/port_variable.js.template b/tests/configs/port_variable.js similarity index 100% rename from tests/configs/port_variable.js.template rename to tests/configs/port_variable.js From b9481d27fa13f85c793cfcbf3b166ea4ed8b06ed Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 8 Feb 2026 00:26:40 +0100 Subject: [PATCH 363/418] fix: correct secret redaction and optimize loadConfig (#4031) - fix copy/paste typo in redacted replacement - create redacted content only if hideConfigSecrets is true follow up for #4029 --- js/utils.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/js/utils.js b/js/utils.js index 258167afc7..ae43840278 100644 --- a/js/utils.js +++ b/js/utils.js @@ -129,17 +129,21 @@ const loadConfig = () => { // Load config.js and catch errors if not accessible try { let configContent = fs.readFileSync(configFilename, "utf-8"); + const hideConfigSecrets = configContent.match(/^\s*hideConfigSecrets: true.*$/m); let configContentFull = configContent; - let configContentRedacted = configContent; + let configContentRedacted = hideConfigSecrets ? configContent : undefined; Object.keys(process.env).forEach((env) => { configContentFull = configContentFull.replaceAll(`\${${env}}`, process.env[env]); - if (env.startsWith("SECRET_")) { - configContentRedacted = configContentRedacted.replaceAll(`"\${${env}}"`, `"**${env}**"`); - configContentRedacted = configContentRedacted.replaceAll(`\${${env}}`, `"**${env}**"`); - } else { - configContentRedacted = configContentRedacted.replaceAll(`\${${env}}`, process.env[env]); + if (hideConfigSecrets) { + if (env.startsWith("SECRET_")) { + configContentRedacted = configContentRedacted.replaceAll(`"\${${env}}"`, `"**${env}**"`); + configContentRedacted = configContentRedacted.replaceAll(`\${${env}}`, `**${env}**`); + } else { + configContentRedacted = configContentRedacted.replaceAll(`\${${env}}`, process.env[env]); + } } }); + configContentRedacted = configContentRedacted ? configContentRedacted : configContentFull; const configObj = { configFilename: configFilename, configContentFull: configContentFull, From 172ca18178070dea030198d9aa2dc45cf9d50238 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 8 Feb 2026 12:02:50 +0100 Subject: [PATCH 364/418] fix cors proxy getting binary data (e.g. png, webp) (#4030) fixes #3266 --------- Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> --- js/server_functions.js | 4 ++-- tests/unit/functions/server_functions_spec.js | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/js/server_functions.js b/js/server_functions.js index 85e674d816..a2f0ea0557 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -46,8 +46,8 @@ async function cors (req, res) { const headerValue = response.headers.get(header); if (header) res.set(header, headerValue); } - const data = await response.text(); - res.send(data); + const arrayBuffer = await response.arrayBuffer(); + res.send(Buffer.from(arrayBuffer)); } else { throw new Error(`Response status: ${response.status}`); } diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index 5383500ae6..7596577309 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -4,19 +4,19 @@ describe("server_functions tests", () => { describe("The cors method", () => { let fetchResponse; let fetchResponseHeadersGet; - let fetchResponseHeadersText; + let fetchResponseArrayBuffer; let corsResponse; let request; let fetchMock; beforeEach(() => { fetchResponseHeadersGet = vi.fn(() => {}); - fetchResponseHeadersText = vi.fn(() => {}); + fetchResponseArrayBuffer = vi.fn(() => {}); fetchResponse = { headers: { get: fetchResponseHeadersGet }, - text: fetchResponseHeadersText, + arrayBuffer: fetchResponseArrayBuffer, ok: true }; @@ -78,7 +78,9 @@ describe("server_functions tests", () => { it("Sends correct data from response", async () => { const responseData = "some data"; - fetchResponseHeadersText.mockImplementation(() => responseData); + const encoder = new TextEncoder(); + const arrayBuffer = encoder.encode(responseData).buffer; + fetchResponseArrayBuffer.mockImplementation(() => arrayBuffer); let sentData; corsResponse.send = vi.fn((input) => { @@ -87,19 +89,19 @@ describe("server_functions tests", () => { await cors(request, corsResponse); - expect(fetchResponseHeadersText.mock.calls).toHaveLength(1); - expect(sentData).toBe(responseData); + expect(fetchResponseArrayBuffer.mock.calls).toHaveLength(1); + expect(sentData).toEqual(Buffer.from(arrayBuffer)); }); it("Sends error data from response", async () => { const error = new Error("error data"); - fetchResponseHeadersText.mockImplementation(() => { + fetchResponseArrayBuffer.mockImplementation(() => { throw error; }); await cors(request, corsResponse); - expect(fetchResponseHeadersText.mock.calls).toHaveLength(1); + expect(fetchResponseArrayBuffer.mock.calls).toHaveLength(1); expect(corsResponse.status).toHaveBeenCalledWith(500); expect(corsResponse.json).toHaveBeenCalledWith({ error: error.message }); }); From 1dc3032171364447dad2f2316de6362fc48ffd77 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 8 Feb 2026 16:18:56 +0100 Subject: [PATCH 365/418] allow environment variables in cors urls (#4033) and centralize and optimize replace regex. Another follow up to #4029 With this PR you can use secrets in urls in browser modules if you use the cors proxy. --- js/node_helper.js | 5 ++--- js/server_functions.js | 18 +++++++++++++++++- tests/unit/functions/server_functions_spec.js | 19 ++++++++++++++++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/js/node_helper.js b/js/node_helper.js index 952db968c6..8910699930 100644 --- a/js/node_helper.js +++ b/js/node_helper.js @@ -1,6 +1,7 @@ const express = require("express"); const Log = require("logger"); const Class = require("./class"); +const { replaceSecretPlaceholder } = require("#server_functions"); const NodeHelper = Class.extend({ init () { @@ -90,9 +91,7 @@ const NodeHelper = Class.extend({ socket.onAny((notification, payload) => { if (config.hideConfigSecrets && payload && typeof payload === "object") { try { - const payloadStr = JSON.stringify(payload).replaceAll(/\*\*(SECRET_.*)\*\*/g, (match, group) => { - return process.env[group]; - }); + const payloadStr = replaceSecretPlaceholder(JSON.stringify(payload)); this.socketNotificationReceived(notification, JSON.parse(payloadStr)); } catch (e) { Log.error("Error substituting variables in payload: ", e); diff --git a/js/server_functions.js b/js/server_functions.js index a2f0ea0557..063e9cfe35 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -13,6 +13,17 @@ function getStartup (req, res) { res.send(startUp); } +/** + * A method that replaces the secret placeholders `**SECRET_ABC**` with the environment variable SECRET_ABC + * @param {string} input - the input string + * @returns {string} the input with real variable content + */ +function replaceSecretPlaceholder (input) { + return input.replaceAll(/\*\*(SECRET_[^*]+)\*\*/g, (match, group) => { + return process.env[group]; + }); +} + /** * A method that forwards HTTP Get-methods to the internet to avoid CORS-errors. * @@ -35,6 +46,11 @@ async function cors (req, res) { return res.status(400).send(url); } else { url = match[1]; + if (typeof config !== "undefined") { + if (config.hideConfigSecrets) { + url = replaceSecretPlaceholder(url); + } + } const headersToSend = getHeadersToSend(req.url); const expectedReceivedHeaders = geExpectedReceivedHeaders(req.url); @@ -186,4 +202,4 @@ function getConfigFilePath () { return path.resolve(global.configuration_file || `${global.root_path}/config/config.js`); } -module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath }; +module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath, replaceSecretPlaceholder }; diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index 7596577309..c0953d4877 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -1,6 +1,23 @@ -const { cors, getUserAgent } = require("#server_functions"); +const { cors, getUserAgent, replaceSecretPlaceholder } = require("#server_functions"); describe("server_functions tests", () => { + describe("The replaceSecretPlaceholder method", () => { + 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**"; + process.env.SECRET_ONE = "secret1"; + process.env.SECRET_TWO = "secret2"; + const resultstring = `test string with secret1=${process.env.SECRET_ONE} and secret2=${process.env.SECRET_TWO}`; + const result = replaceSecretPlaceholder(teststring); + expect(result).toBe(resultstring); + }); + }); + describe("The cors method", () => { let fetchResponse; let fetchResponseHeadersGet; From 6cb3e24c2a759795a9fac59f80bef0ac2bbfaa72 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 9 Feb 2026 20:35:54 +0100 Subject: [PATCH 366/418] replace template_spec test with config_variables test (#4034) After introducing new config loading this PR replaces the obsolete template test with a config test. --- cspell.config.json | 2 ++ eslint.config.mjs | 2 +- tests/configs/config_variables.env | 7 ++++++ tests/configs/config_variables.js | 12 +++++++++++ tests/configs/port_variable.env | 1 - tests/configs/port_variable.js | 8 ------- tests/e2e/config_variables_spec.js | 34 ++++++++++++++++++++++++++++++ tests/e2e/template_spec.js | 23 -------------------- 8 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 tests/configs/config_variables.env create mode 100644 tests/configs/config_variables.js delete mode 100644 tests/configs/port_variable.env delete mode 100644 tests/configs/port_variable.js create mode 100644 tests/e2e/config_variables_spec.js delete mode 100644 tests/e2e/template_spec.js diff --git a/cspell.config.json b/cspell.config.json index 564f7d205b..1fa1ba6873 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -248,6 +248,7 @@ "Reis", "rejas", "relativehumidity", + "resultstring", "Resig", "roboto", "rohitdharavath", @@ -288,6 +289,7 @@ "TESTMODE", "testpass", "testuser", + "teststring", "thomasrockhu", "thumbslider", "timeformat", diff --git a/eslint.config.mjs b/eslint.config.mjs index b1c90ca6c3..238efa961d 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,7 +9,7 @@ import stylistic from "@stylistic/eslint-plugin"; import vitest from "@vitest/eslint-plugin"; export default defineConfig([ - globalIgnores(["config/**", "modules/**/*", "js/positions.js", "tests/configs/port_variable.js"]), + globalIgnores(["config/**", "modules/**/*", "js/positions.js", "tests/configs/config_variables.js"]), { files: ["**/*.js"], languageOptions: { diff --git a/tests/configs/config_variables.env b/tests/configs/config_variables.env new file mode 100644 index 0000000000..6f38944695 --- /dev/null +++ b/tests/configs/config_variables.env @@ -0,0 +1,7 @@ +MM_LANGUAGE=de +MM_TIME_FORMAT=12 +MM_LOG_INFO=INFO +MM_LOG_ERROR=ERROR +SECRET_IP1="127.0.0.1" +SECRET_IP2="::ffff:127.0.0.1" +SECRET_IP3=1 diff --git a/tests/configs/config_variables.js b/tests/configs/config_variables.js new file mode 100644 index 0000000000..2068a22a6f --- /dev/null +++ b/tests/configs/config_variables.js @@ -0,0 +1,12 @@ +let config = require(`${process.cwd()}/tests/configs/default.js`).configFactory({ + language: "${MM_LANGUAGE}", + logLevel: ["${MM_LOG_ERROR}", "LOG", "WARN", "${MM_LOG_INFO}"], + timeFormat: ${MM_TIME_FORMAT}, + hideConfigSecrets: true, + ipWhitelist: ["${SECRET_IP2}", "::${SECRET_IP3}", "${SECRET_IP1}"] +}); + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/port_variable.env b/tests/configs/port_variable.env deleted file mode 100644 index 2b19af0113..0000000000 --- a/tests/configs/port_variable.env +++ /dev/null @@ -1 +0,0 @@ -MM_PORT=8090 diff --git a/tests/configs/port_variable.js b/tests/configs/port_variable.js deleted file mode 100644 index e44aa5ac90..0000000000 --- a/tests/configs/port_variable.js +++ /dev/null @@ -1,8 +0,0 @@ -let config = require(`${process.cwd()}/tests/configs/default.js`).configFactory({ - port: ${MM_PORT} -}); - -/*************** DO NOT EDIT THE LINE BELOW ***************/ -if (typeof module !== "undefined") { - module.exports = config; -} diff --git a/tests/e2e/config_variables_spec.js b/tests/e2e/config_variables_spec.js new file mode 100644 index 0000000000..f3bf650527 --- /dev/null +++ b/tests/e2e/config_variables_spec.js @@ -0,0 +1,34 @@ +const helpers = require("./helpers/global-setup"); + +describe("config with variables and secrets", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/config_variables.js"); + }); + + afterAll(async () => { + await helpers.stopApplication(); + }); + + it("config.language should be \"de\"", async () => { + expect(config.language).toBe("de"); + }); + + it("config.loglevel should be [\"ERROR\", \"LOG\", \"WARN\", \"INFO\"]", async () => { + expect(config.logLevel).toStrictEqual(["ERROR", "LOG", "WARN", "INFO"]); + }); + + it("config.ipWhitelist should be [\"::ffff:127.0.0.1\", \"::1\", \"127.0.0.1\"]", async () => { + expect(config.ipWhitelist).toStrictEqual(["::ffff:127.0.0.1", "::1", "127.0.0.1"]); + }); + + it("config.timeFormat should be 12", async () => { + expect(config.timeFormat).toBe(12); // default is 24 + }); + + it("/config endpoint should show redacted secrets", async () => { + const res = await fetch(`http://localhost:${config.port}/config`); + expect(res.status).toBe(200); + const cfg = await res.json(); + expect(cfg.ipWhitelist).toStrictEqual(["**SECRET_IP2**", "::**SECRET_IP3**", "**SECRET_IP1**"]); + }); +}); diff --git a/tests/e2e/template_spec.js b/tests/e2e/template_spec.js deleted file mode 100644 index 17178c27b7..0000000000 --- a/tests/e2e/template_spec.js +++ /dev/null @@ -1,23 +0,0 @@ -const fs = require("node:fs"); -const helpers = require("./helpers/global-setup"); - -describe("templated config with port variable", () => { - beforeAll(async () => { - await helpers.startApplication("tests/configs/port_variable.js"); - }); - - afterAll(async () => { - await helpers.stopApplication(); - try { - fs.unlinkSync("tests/configs/port_variable.js"); - } catch (err) { - // do nothing - } - }); - - it("should return 200", async () => { - const port = global.testPort || 8080; - const res = await fetch(`http://localhost:${port}`); - expect(res.status).toBe(200); - }); -}); From 80c48791b227b15fd99154e9e055fb38c0e14f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Vanegas=20Jim=C3=A9nez?= <142350+angeldeejay@users.noreply.github.com> Date: Sat, 21 Feb 2026 17:19:22 -0500 Subject: [PATCH 367/418] [weather] feat: add Weather API Provider (#4036) Weather API: https://www.weatherapi.com/docs/ --- .../weather/providers/weatherapi.js | 412 ++++++++++++++++++ 1 file changed, 412 insertions(+) create mode 100644 defaultmodules/weather/providers/weatherapi.js diff --git a/defaultmodules/weather/providers/weatherapi.js b/defaultmodules/weather/providers/weatherapi.js new file mode 100644 index 0000000000..e0bf3c9fb4 --- /dev/null +++ b/defaultmodules/weather/providers/weatherapi.js @@ -0,0 +1,412 @@ +/* global WeatherProvider, WeatherObject */ + +/* + * This class is a provider for Weather API, + * see https://www.weatherapi.com/docs/ + */ + +const WEATHER_API_BASE = "https://api.weatherapi.com/v1"; +const EMPTY_RESPONSE_DATA = { + location: { + name: "", + region: "", + country: "", + lat: 0, + lon: 0, + tz_id: "", + localtime_epoch: 0, + localtime: "" + }, + forecast: { + forecastday: [] + } +}; + +WeatherProvider.register("weatherapi", { + /* + * Set the name of the provider. + * Not strictly required but helps for debugging. + */ + providerName: "Weather API", + + // Set the default config properties that is specific to this provider + defaults: { + apiBase: WEATHER_API_BASE, + lat: 0, + lon: 0, + type: "current", + apiKey: "" + }, + + requestForecast () { + return new Promise((resolve, reject) => { + this.fetchData(this.getForecastUrl()) + .then((data) => resolve(data)) + .catch((request) => reject(request)); + }); + }, + + preProcessResponses (responseData) { + // Ensure nested structures + responseData.location ??= {}; + responseData.current ??= {}; + responseData.current.condition ??= {}; + responseData.forecast ??= {}; + responseData.forecast.forecastday ??= []; + responseData.forecast.forecastday = responseData.forecast.forecastday.map((fd) => ({ + ...fd, + astro: fd.astro ?? {}, + day: fd.day ?? {}, + hour: fd.hour ?? [] + })); + + const locationParts = [responseData.location.name, responseData.location.region, responseData.location.country].map((v) => `${v}`.trim()).filter((v) => v !== ""); + + if (locationParts.length > 0) { + this.setFetchedLocation(locationParts.join(", ").trim()); + } + + return responseData; + }, + + fetchCurrentWeather () { + this.requestForecast() + .then((data) => this.preProcessResponses(data)) + .then((data) => this.parseWeatherApiResponse(data)) + .then((parsedData) => { + if (!parsedData) { + // No usable data? + return; + } + + const currentWeather = this.generateWeatherDayFromCurrentWeather(parsedData); + this.setCurrentWeather(currentWeather); + }) + .catch(function (err) { + Log.error("[weatherprovider.weatherapi] Could not load data ... ", err); + }) + .finally(() => this.updateAvailable()); + }, + + fetchWeatherForecast () { + this.requestForecast() + .then((data) => this.preProcessResponses(data)) + .then((data) => this.parseWeatherApiResponse(data)) + .then((parsedData) => { + if (!parsedData) { + // No usable data? + return; + } + + const dailyForecast = this.generateWeatherObjectsFromForecast(parsedData); + + this.setWeatherForecast(dailyForecast); + }) + .catch(function (err) { + Log.error("[weatherprovider.weatherapi] Could not load data ... ", err); + }) + .finally(() => this.updateAvailable()); + }, + + fetchWeatherHourly () { + this.requestForecast() + .then((data) => this.preProcessResponses(data)) + .then((data) => this.parseWeatherApiResponse(data)) + .then((parsedData) => { + if (!parsedData) { + // No usable data? + return; + } + + const hourlyForecast = this.generateWeatherObjectsFromHourly(parsedData); + this.setWeatherHourly(hourlyForecast); + }) + .catch(function (request) { + Log.error("[weatherprovider.weatherapi] Could not load data ... ", request); + }) + .finally(() => this.updateAvailable()); + }, + + // Sanitize config + validateConfig () { + this.config.type = `${this.config.type ?? ""}`.trim().toLowerCase(); + Object.keys(this.defaults).forEach((key) => { + if (typeof this.config[key] === "undefined" || this.config[key] === null || `${this.config[key]}`.trim() === "") { + const message = `[weatherprovider.weatherapi] ${key} not configured`; + Log.error(message); + throw new Error(message); + } + }); + + if (this.config.type === "forecast") this.config.type = "daily"; + if (!["hourly", "daily", "current"].includes(this.config.type)) { + const message = `[weatherprovider.weatherapi] Unknown type: ${this.config.type}`; + Log.error(message); + throw new Error(message); + } + + // fix values + if (this.config.type === "current") { + this.config.maxEntries = 1; + this.config.maxNumberOfDays = 1; + this.config.ignoreToday = false; + } else { + this.config.ignoreToday = !!this.config.ignoreToday; + } + }, + + /** + * Overrides method for setting config to check if endpoint is correct for hourly + * @param {object} config The configuration object + */ + setConfig (config) { + this.fetchedLocationName = null; + this.config = { + lang: config.lang ?? "en", + ...this.defaults, + ...config + }; + + this.validateConfig(); + }, + + // Generate valid query params to perform the request + getForecastQueryParameters () { + let params = { + q: `${this.config.lat},${this.config.lon}`, + unixdt: moment().valueOf(), + days: this.config.maxNumberOfDays, + lang: this.config.lang, + tp: 60, + key: this.config.apiKey + }; + + return Object.keys(params) + .filter((key) => !!params[key]) + .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`.trim()) + .join("&"); + }, + + // Create a URL from the config and base URL. + getForecastUrl () { + return `${this.config.apiBase}/forecast.json?${this.getForecastQueryParameters()}`; + }, + + // fix daylight-saving-time differences + checkDST (dt) { + const uxdt = moment.unix(dt); + const nowDST = moment().isDST(); + if (nowDST === moment(uxdt).isDST()) { + return uxdt; + } else { + return uxdt.add(nowDST ? +1 : -1, "hour"); + } + }, + + // Transpose hourly and daily data matrices + transposeDataMatrix (data) { + return data.time.map((_, index) => Object.keys(data).reduce((row, key) => { + return { + ...row, + // Parse time values as moment.js instances + [key]: ["time", "sunrise", "sunset"].includes(key) ? this.checkDST(data[key][index]) : data[key][index] + }; + }, {})); + }, + + // Sanitize and validate API response + parseWeatherApiResponse (data) { + const _isObject = (obj) => obj && typeof obj === "object" && obj !== null && !Array.isArray(obj); + const _isArray = (obj) => obj && Array.isArray(obj); + + if (_isObject(data.location) && _isObject(data.current) && _isObject(data.forecast) && _isArray(data.forecast.forecastday)) { + return data; + } + + throw new Error("Invalid API response"); + }, + + // Parse sunrise and sunset moments + parseSunDatetime (forecastDay, key) { + const { date, astro } = forecastDay; + return moment(`${date} ${astro[key]}`, "YYYY-MM-DD hh:mm A"); + }, + + // Implement WeatherDay generator. + generateWeatherDayFromCurrentWeather (data) { + const fd = data.forecast.forecastday[0]; + const weather = new WeatherObject(); + + weather.date = moment(); + weather.humidity = parseFloat(data.current.humidity); + weather.temperature = parseFloat(data.current.temp_c); + weather.feelsLikeTemp = parseFloat(data.current.feelslike_c); + weather.windSpeed = parseFloat(data.current.wind_kph) * 0.2778; + weather.windFromDirection = parseFloat(data.current.wind_degree); + weather.weatherType = this.convertWeatherType(data.current.condition.code, data.current.is_day === 1); + weather.sunrise = this.parseSunDatetime(fd, "sunrise"); + weather.sunset = this.parseSunDatetime(fd, "sunset"); + // Optional + weather.minTemperature = parseFloat(fd.day.mintemp_c); + weather.maxTemperature = parseFloat(fd.day.maxtemp_c); + weather.snow = parseFloat(data.current.snow_cm * 10); + weather.rain = parseFloat(data.current.precip_mm); + weather.precipitationAmount = weather.rain + weather.snow; + weather.uv_index = parseFloat(data.current.uv); + + return weather; + }, + + // Implement WeatherForecast generator. + generateWeatherObjectsFromForecast (data) { + const days = []; + + for (const fd of data.forecast.forecastday) { + const weather = new WeatherObject(); + + const precipitationProbability + = (fd.hour.reduce((acc, h) => { + const idxValue = ((h.will_it_rain ?? 0) + (h.will_it_snow ?? 0)) / 2; + return acc + idxValue; + }, 0) + / fd.hour.length) + * 100; + + const avgwind_degree + = fd.hour.reduce((acc, h) => { + return acc + (h.wind_degree ?? 0); + }, 0) / fd.hour.length; + + weather.date = moment(fd.date).startOf("day"); + weather.minTemperature = parseFloat(fd.day.mintemp_c); + weather.maxTemperature = parseFloat(fd.day.maxtemp_c); + weather.weatherType = this.convertWeatherType(fd.day.condition.code, true); + weather.windSpeed = parseFloat(fd.day.maxwind_kph) * 0.2778; + weather.windFromDirection = parseFloat(avgwind_degree); + weather.sunrise = this.parseSunDatetime(fd, "sunrise"); + weather.sunset = this.parseSunDatetime(fd, "sunset"); + weather.temperature = parseFloat(fd.day.avgtemp_c); + weather.humidity = parseFloat(fd.day.avghumidity); + weather.snow = parseFloat(fd.day.totalsnow_cm * 10); + weather.rain = parseFloat(fd.day.totalprecip_mm); + weather.precipitationAmount = weather.rain + weather.snow; + weather.precipitationProbability = precipitationProbability; + weather.uv_index = parseFloat(fd.day.uv); + + days.push(weather); + + if (days.length >= this.config.maxEntries) { + break; + } + } + + return days; + }, + + // Implement WeatherHourly generator. + generateWeatherObjectsFromHourly (data) { + const hours = []; + const now = moment(); + const nowStart = moment(now).add(1, "hour").startOf("hour"); + + for (const fd of data.forecast.forecastday) { + for (const h of fd.hour) { + const currentMoment = moment(h.time, "YYYY-MM-DD HH:00"); + if (currentMoment.isBefore(nowStart)) { + continue; + } + + const weather = new WeatherObject(); + + weather.date = currentMoment; + weather.sunrise = this.parseSunDatetime(fd, "sunrise"); + weather.sunset = this.parseSunDatetime(fd, "sunset"); + weather.minTemperature = parseFloat(fd.day.mintemp_c); + weather.maxTemperature = parseFloat(fd.day.maxtemp_c); + weather.humidity = parseFloat(h.humidity); + weather.windSpeed = parseFloat(h.wind_kph) * 0.2778; + weather.windFromDirection = parseFloat(h.wind_degree); + weather.weatherType = this.convertWeatherType(h.condition.code, h.is_day === 1); + weather.snow = parseFloat(h.snow_cm * 10); + weather.temperature = parseFloat(h.temp_c); + weather.precipitationAmount = parseFloat(h.precip_mm); + weather.precipitationProbability = ((h.will_it_rain ?? 0) + (h.will_it_snow ?? 0)) * 50; + weather.uv_index = parseFloat(h.uv); + + hours.push(weather); + + if (hours.length >= this.config.maxEntries) { + break; + } + } + + if (hours.length >= this.config.maxEntries) { + break; + } + } + + return hours; + }, + + // Map icons from Dark Sky to our icons. + convertWeatherType (weathercode, isDayTime) { + const weatherConditions = { + 1000: { day: "day-sunny", night: "night-clear" }, + 1003: { day: "day-cloudy", night: "night-alt-cloudy" }, + 1006: { day: "day-cloudy", night: "night-alt-cloudy" }, + 1009: { day: "day-sunny-overcast", night: "night-alt-partly-cloudy" }, + 1030: { day: "day-fog", night: "night-fog" }, + 1063: { day: "day-sprinkle", night: "night-sprinkle" }, + 1066: { day: "day-snow-wind", night: "night-snow-wind" }, + 1069: { day: "day-sleet", night: "night-sleet" }, + 1072: { day: "day-sprinkle", night: "night-sprinkle" }, + 1087: { day: "day-thunderstorm", night: "night-thunderstorm" }, + 1114: { day: "day-snow-wind", night: "night-snow-wind" }, + 1117: { day: "windy", night: "windy" }, + 1135: { day: "day-fog", night: "night-fog" }, + 1147: { day: "day-fog", night: "night-fog" }, + 1150: { day: "day-sprinkle", night: "night-sprinkle" }, + 1153: { day: "day-sprinkle", night: "night-sprinkle" }, + 1168: { day: "day-sprinkle", night: "night-sprinkle" }, + 1171: { day: "day-sprinkle", night: "night-sprinkle" }, + 1180: { day: "day-sprinkle", night: "night-sprinkle" }, + 1183: { day: "day-sprinkle", night: "night-sprinkle" }, + 1186: { day: "day-showers", night: "night-showers" }, + 1189: { day: "day-showers", night: "night-showers" }, + 1192: { day: "day-showers", night: "night-showers" }, + 1195: { day: "day-showers", night: "night-showers" }, + 1198: { day: "day-thunderstorm", night: "night-thunderstorm" }, + 1201: { day: "day-thunderstorm", night: "night-thunderstorm" }, + 1204: { day: "day-sprinkle", night: "night-sprinkle" }, + 1207: { day: "day-showers", night: "night-showers" }, + 1210: { day: "snowflake-cold", night: "snowflake-cold" }, + 1213: { day: "snowflake-cold", night: "snowflake-cold" }, + 1216: { day: "snowflake-cold", night: "snowflake-cold" }, + 1219: { day: "snowflake-cold", night: "snowflake-cold" }, + 1222: { day: "snowflake-cold", night: "snowflake-cold" }, + 1225: { day: "snowflake-cold", night: "snowflake-cold" }, + 1237: { day: "day-sleet", night: "night-sleet" }, + 1240: { day: "day-sprinkle", night: "night-sprinkle" }, + 1243: { day: "day-showers", night: "night-showers" }, + 1246: { day: "day-showers", night: "night-showers" }, + 1249: { day: "day-showers", night: "night-showers" }, + 1252: { day: "day-showers", night: "night-showers" }, + 1255: { day: "day-snow-wind", night: "night-snow-wind" }, + 1258: { day: "day-snow-wind", night: "night-snow-wind" }, + 1261: { day: "day-sleet", night: "night-sleet" }, + 1264: { day: "day-sleet", night: "night-sleet" }, + 1273: { day: "day-thunderstorm", night: "night-thunderstorm" }, + 1276: { day: "day-thunderstorm", night: "night-thunderstorm" }, + 1279: { day: "day-snow-thunderstorm", night: "night-snow-thunderstorm" }, + 1282: { day: "day-snow-thunderstorm", night: "night-snow-thunderstorm" } + }; + + if (!Object.keys(weatherConditions).includes(`${weathercode}`)) return "na"; + return weatherConditions[`${weathercode}`][isDayTime ? "day" : "night"]; + }, + + // Define required scripts. + getScripts () { + return ["moment.js"]; + } +}); From 8ce0cda7bfd64da76bf532739aa457c455c09e7b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 23 Feb 2026 10:27:29 +0100 Subject: [PATCH 368/418] [weather] refactor: migrate to server-side providers with centralized HTTPFetcher (#4032) This migrates the Weather module from client-side fetching to use the server-side centralized HTTPFetcher (introduced in #4016), following the same pattern as the Calendar and Newsfeed modules. ## Motivation This brings consistent error handling and better maintainability and completes the refactoring effort to centralize HTTP error handling across all default modules. Migrating to server-side providers with HTTPFetcher brings: - **Centralized error handling**: Inherits smart retry strategies (401/403, 429, 5xx backoff) and timeout handling (30s) - **Consistency**: Same architecture as Calendar and Newsfeed modules - **Security**: Possibility to hide API keys/secrets from client-side - **Performance**: Reduced API calls in multi-client setups - one server fetch instead of one per client - **Enabling possible future features**: e.g. server-side caching, rate limit monitoring, and data sharing with third-party modules ## Changes - All 10 weather providers now use HTTPFetcher for server-side fetching - Consistent error handling like Calendar and Newsfeed modules ## Breaking Changes None. Existing configurations continue to work. ## Testing To ensure proper functionality, I obtained API keys and credentials for all providers that require them. I configured all 10 providers in a carousel setup and tested each one individually. Screenshots for each provider are attached below demonstrating their working state. I even requested developer access from the Tempest/WeatherFlow team to properly test this provider. **Comprehensive test coverage**: A major advantage of the server-side architecture is the ability to thoroughly test providers with unit tests using real API response snapshots. Don't be alarmed by the many lines added in this PR - they are primarily test files and real-data mocks that ensure provider reliability. ## Review Notes I know this is an enormous change - I've been working on this for quite some time. Unfortunately, breaking it into smaller incremental PRs wasn't feasible due to the interdependencies between providers and the shared architecture. Given the scope, it's nearly impossible to manually review every change. To ensure quality, I've used both CodeRabbit and GitHub Copilot to review the code multiple times in my fork, and both provided extensive and valuable feedback. Most importantly, my test setup with all 10 providers working successfully is very encouraging. ## Related Part of the HTTPFetcher migration #4016. ## Screenshots Ekrankopio de 2026-02-08 13-06-54 Ekrankopio de 2026-02-08 13-07-02 Ekrankopio de 2026-02-08 13-07-07 Ekrankopio de 2026-02-08 13-07-12 Ekrankopio de 2026-02-08 13-07-17 Ekrankopio de 2026-02-08 13-07-22 Ekrankopio de 2026-02-08 13-07-27 Ekrankopio de 2026-02-08 13-07-32 Ekrankopio de 2026-02-08 13-07-37 Ekrankopio de 2026-02-08 13-07-42 Provider "Weather API" added later: Ekrankopio de 2026-02-15 19-39-06 --- defaultmodules/utils.js | 152 - defaultmodules/weather/current.njk | 2 +- defaultmodules/weather/node_helper.js | 103 + defaultmodules/weather/provider-utils.js | 181 + defaultmodules/weather/providers/README.md | 2 +- defaultmodules/weather/providers/envcanada.js | 850 ++- defaultmodules/weather/providers/openmeteo.js | 768 +-- .../weather/providers/openweathermap.js | 477 +- .../weather/providers/overrideWrapper.js | 112 - .../weather/providers/pirateweather.js | 324 +- defaultmodules/weather/providers/smhi.js | 586 +- .../weather/providers/ukmetofficedatahub.js | 501 +- .../weather/providers/weatherapi.js | 672 ++- .../weather/providers/weatherbit.js | 329 +- .../weather/providers/weatherflow.js | 389 +- .../weather/providers/weathergov.js | 663 +-- defaultmodules/weather/providers/yr.js | 1000 ++-- defaultmodules/weather/weather.js | 198 +- defaultmodules/weather/weatherobject.js | 10 +- defaultmodules/weather/weatherprovider.js | 165 - defaultmodules/weather/weatherutils.js | 3 + eslint.config.mjs | 11 +- js/http_fetcher.js | 63 +- js/server.js | 8 +- .../weather/currentweather_compliments.js | 6 +- .../modules/weather/currentweather_default.js | 6 +- .../modules/weather/currentweather_options.js | 6 +- .../modules/weather/currentweather_units.js | 6 +- .../weather/forecastweather_absolute.js | 6 +- .../weather/forecastweather_default.js | 6 +- .../weather/forecastweather_options.js | 6 +- .../modules/weather/forecastweather_units.js | 6 +- .../modules/weather/hourlyweather_default.js | 6 +- .../modules/weather/hourlyweather_options.js | 6 +- .../hourlyweather_showPrecipitation.js | 6 +- tests/e2e/helpers/weather-functions.js | 104 +- tests/e2e/modules/weather_current_spec.js | 8 +- tests/e2e/modules/weather_forecast_spec.js | 8 +- tests/e2e/modules/weather_hourly_spec.js | 6 +- tests/electron/helpers/weather-setup.js | 89 +- tests/electron/modules/weather_spec.js | 2 - tests/mocks/weather_envcanada.xml | 871 +++ tests/mocks/weather_envcanada_index.html | 427 ++ tests/mocks/weather_onecall_current.json | 28 + tests/mocks/weather_onecall_forecast.json | 149 + ...ourly.json => weather_onecall_hourly.json} | 100 +- tests/mocks/weather_openmeteo_current.json | 218 + .../weather_openmeteo_current_weather.json | 84 + tests/mocks/weather_owm_onecall.json | 970 ++++ tests/mocks/weather_pirateweather.json | 1665 ++++++ tests/mocks/weather_smhi.json | 1907 +++++++ tests/mocks/weather_ukmetoffice.json | 1062 ++++ tests/mocks/weather_ukmetoffice_daily.json | 419 ++ tests/mocks/weather_weatherbit.json | 45 + tests/mocks/weather_weatherbit_forecast.json | 290 + tests/mocks/weather_weatherbit_hourly.json | 1 + tests/mocks/weather_weatherflow.json | 4875 +++++++++++++++++ tests/mocks/weather_weathergov_current.json | 151 + tests/mocks/weather_weathergov_forecast.json | 304 + tests/mocks/weather_weathergov_hourly.json | 4250 ++++++++++++++ tests/mocks/weather_weathergov_points.json | 89 + tests/mocks/weather_weathergov_stations.json | 1793 ++++++ tests/mocks/weather_yr.json | 707 +++ tests/unit/functions/server_functions_spec.js | 3 + tests/unit/modules/default/utils_spec.js | 104 +- .../default/weather/provider_utils_spec.js | 167 + .../weather/providers/envcanada_spec.js | 309 ++ .../weather/providers/openmeteo_spec.js | 305 ++ .../weather/providers/openweathermap_spec.js | 235 + .../weather/providers/pirateweather_spec.js | 366 ++ .../default/weather/providers/smhi_spec.js | 208 + .../providers/ukmetofficedatahub_spec.js | 348 ++ .../weather/providers/weatherapi_spec.js | 311 ++ .../weather/providers/weatherbit_spec.js | 247 + .../weather/providers/weatherflow_spec.js | 264 + .../weather/providers/weathergov_spec.js | 412 ++ .../default/weather/providers/yr_spec.js | 287 + .../default/weather/weather_providers_spec.js | 189 + tests/utils/weather_mocker.js | 52 - 79 files changed, 28083 insertions(+), 3981 deletions(-) create mode 100644 defaultmodules/weather/node_helper.js create mode 100644 defaultmodules/weather/provider-utils.js delete mode 100644 defaultmodules/weather/providers/overrideWrapper.js delete mode 100644 defaultmodules/weather/weatherprovider.js create mode 100644 tests/mocks/weather_envcanada.xml create mode 100644 tests/mocks/weather_envcanada_index.html create mode 100644 tests/mocks/weather_onecall_current.json create mode 100644 tests/mocks/weather_onecall_forecast.json rename tests/mocks/{weather_hourly.json => weather_onecall_hourly.json} (99%) create mode 100644 tests/mocks/weather_openmeteo_current.json create mode 100644 tests/mocks/weather_openmeteo_current_weather.json create mode 100644 tests/mocks/weather_owm_onecall.json create mode 100644 tests/mocks/weather_pirateweather.json create mode 100644 tests/mocks/weather_smhi.json create mode 100644 tests/mocks/weather_ukmetoffice.json create mode 100644 tests/mocks/weather_ukmetoffice_daily.json create mode 100644 tests/mocks/weather_weatherbit.json create mode 100644 tests/mocks/weather_weatherbit_forecast.json create mode 100644 tests/mocks/weather_weatherbit_hourly.json create mode 100644 tests/mocks/weather_weatherflow.json create mode 100644 tests/mocks/weather_weathergov_current.json create mode 100644 tests/mocks/weather_weathergov_forecast.json create mode 100644 tests/mocks/weather_weathergov_hourly.json create mode 100644 tests/mocks/weather_weathergov_points.json create mode 100644 tests/mocks/weather_weathergov_stations.json create mode 100644 tests/mocks/weather_yr.json create mode 100644 tests/unit/modules/default/weather/provider_utils_spec.js create mode 100644 tests/unit/modules/default/weather/providers/envcanada_spec.js create mode 100644 tests/unit/modules/default/weather/providers/openmeteo_spec.js create mode 100644 tests/unit/modules/default/weather/providers/openweathermap_spec.js create mode 100644 tests/unit/modules/default/weather/providers/pirateweather_spec.js create mode 100644 tests/unit/modules/default/weather/providers/smhi_spec.js create mode 100644 tests/unit/modules/default/weather/providers/ukmetofficedatahub_spec.js create mode 100644 tests/unit/modules/default/weather/providers/weatherapi_spec.js create mode 100644 tests/unit/modules/default/weather/providers/weatherbit_spec.js create mode 100644 tests/unit/modules/default/weather/providers/weatherflow_spec.js create mode 100644 tests/unit/modules/default/weather/providers/weathergov_spec.js create mode 100644 tests/unit/modules/default/weather/providers/yr_spec.js create mode 100644 tests/unit/modules/default/weather/weather_providers_spec.js delete mode 100644 tests/utils/weather_mocker.js diff --git a/defaultmodules/utils.js b/defaultmodules/utils.js index d9eab5c57e..ecdb890239 100644 --- a/defaultmodules/utils.js +++ b/defaultmodules/utils.js @@ -1,154 +1,3 @@ -/** - * A function to make HTTP requests via the server to avoid CORS-errors. - * @param {string} url the url to fetch from - * @param {string} type what content-type to expect in the response, can be "json" or "xml" - * @param {boolean} useCorsProxy A flag to indicate - * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send - * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive - * @param {string} basePath The base path, default is "/" - * @returns {Promise} resolved when the fetch is done. The response headers is placed in a headers-property (provided the response does not already contain a headers-property). - */ -async function performWebRequest (url, type = "json", useCorsProxy = false, requestHeaders = undefined, expectedResponseHeaders = undefined, basePath = "/") { - const request = {}; - let requestUrl; - if (useCorsProxy) { - requestUrl = getCorsUrl(url, requestHeaders, expectedResponseHeaders, basePath); - } else { - requestUrl = url; - request.headers = getHeadersToSend(requestHeaders); - } - - try { - const response = await fetch(requestUrl, request); - if (response.ok) { - const data = await response.text(); - - if (type === "xml") { - return new DOMParser().parseFromString(data, "text/html"); - } else { - if (!data || !data.length > 0) return undefined; - - const dataResponse = JSON.parse(data); - if (!dataResponse.headers) { - dataResponse.headers = getHeadersFromResponse(expectedResponseHeaders, response); - } - return dataResponse; - } - } else { - throw new Error(`Response status: ${response.status}`); - } - } catch (error) { - Log.error(`Error fetching data from ${url}: ${error}`); - return undefined; - } -} - -/** - * Gets a URL that will be used when calling the CORS-method on the server. - * @param {string} url the url to fetch from - * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send - * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive - * @param {string} basePath The base path, default is "/" - * @returns {string} to be used as URL when calling CORS-method on server. - */ -const getCorsUrl = function (url, requestHeaders, expectedResponseHeaders, basePath = "/") { - if (!url || url.length < 1) { - throw new Error(`Invalid URL: ${url}`); - } else { - let corsUrl = `${location.protocol}//${location.host}${basePath}cors?`; - - const requestHeaderString = getRequestHeaderString(requestHeaders); - if (requestHeaderString) corsUrl = `${corsUrl}sendheaders=${requestHeaderString}`; - - const expectedResponseHeadersString = getExpectedResponseHeadersString(expectedResponseHeaders); - if (requestHeaderString && expectedResponseHeadersString) { - corsUrl = `${corsUrl}&expectedheaders=${expectedResponseHeadersString}`; - } else if (expectedResponseHeadersString) { - corsUrl = `${corsUrl}expectedheaders=${expectedResponseHeadersString}`; - } - - if (requestHeaderString || expectedResponseHeadersString) { - return `${corsUrl}&url=${url}`; - } - return `${corsUrl}url=${url}`; - } -}; - -/** - * Gets the part of the CORS URL that represents the HTTP headers to send. - * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send - * @returns {string} to be used as request-headers component in CORS URL. - */ -const getRequestHeaderString = function (requestHeaders) { - let requestHeaderString = ""; - if (requestHeaders) { - for (const header of requestHeaders) { - if (requestHeaderString.length === 0) { - requestHeaderString = `${header.name}:${encodeURIComponent(header.value)}`; - } else { - requestHeaderString = `${requestHeaderString},${header.name}:${encodeURIComponent(header.value)}`; - } - } - return requestHeaderString; - } - return undefined; -}; - -/** - * Gets headers and values to attach to the web request. - * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send - * @returns {object} An object specifying name and value of the headers. - */ -const getHeadersToSend = (requestHeaders) => { - const headersToSend = {}; - if (requestHeaders) { - for (const header of requestHeaders) { - headersToSend[header.name] = header.value; - } - } - - return headersToSend; -}; - -/** - * Gets the part of the CORS URL that represents the expected HTTP headers to receive. - * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive - * @returns {string} to be used as the expected HTTP-headers component in CORS URL. - */ -const getExpectedResponseHeadersString = function (expectedResponseHeaders) { - let expectedResponseHeadersString = ""; - if (expectedResponseHeaders) { - for (const header of expectedResponseHeaders) { - if (expectedResponseHeadersString.length === 0) { - expectedResponseHeadersString = `${header}`; - } else { - expectedResponseHeadersString = `${expectedResponseHeadersString},${header}`; - } - } - return expectedResponseHeaders; - } - return undefined; -}; - -/** - * Gets the values for the expected headers from the response. - * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive - * @param {Response} response the HTTP response - * @returns {string} to be used as the expected HTTP-headers component in CORS URL. - */ -const getHeadersFromResponse = (expectedResponseHeaders, response) => { - const responseHeaders = []; - - if (expectedResponseHeaders) { - for (const header of expectedResponseHeaders) { - const headerValue = response.headers.get(header); - responseHeaders.push({ name: header, value: headerValue }); - } - } - - return responseHeaders; -}; - /** * Format the time according to the config * @param {object} config The config of the module @@ -178,6 +27,5 @@ const formatTime = (config, time) => { }; if (typeof module !== "undefined") module.exports = { - performWebRequest, formatTime }; diff --git a/defaultmodules/weather/current.njk b/defaultmodules/weather/current.njk index 51687231eb..b75966d3b1 100644 --- a/defaultmodules/weather/current.njk +++ b/defaultmodules/weather/current.njk @@ -25,7 +25,7 @@ {% if config.showHumidity === "wind" %} {{ humidity() }} {% endif %} - {% if config.showSun %} + {% if config.showSun and current.nextSunAction() %} {% if current.nextSunAction() === "sunset" %} diff --git a/defaultmodules/weather/node_helper.js b/defaultmodules/weather/node_helper.js new file mode 100644 index 0000000000..f9ea08c42a --- /dev/null +++ b/defaultmodules/weather/node_helper.js @@ -0,0 +1,103 @@ +const path = require("node:path"); +const NodeHelper = require("node_helper"); +const Log = require("logger"); + +module.exports = NodeHelper.create({ + providers: {}, + + start () { + Log.log(`Starting node helper for: ${this.name}`); + }, + + socketNotificationReceived (notification, payload) { + if (notification === "INIT_WEATHER") { + Log.log(`Received INIT_WEATHER for instance ${payload.instanceId}`); + this.initWeatherProvider(payload); + } else if (notification === "STOP_WEATHER") { + Log.log(`Received STOP_WEATHER for instance ${payload.instanceId}`); + this.stopWeatherProvider(payload.instanceId); + } + // FETCH_WEATHER is no longer needed - HTTPFetcher handles periodic fetching + }, + + /** + * Initialize a weather provider + * @param {object} config The configuration object + */ + async initWeatherProvider (config) { + const identifier = config.weatherProvider.toLowerCase(); + const instanceId = config.instanceId; + + Log.log(`Attempting to initialize provider ${identifier} for instance ${instanceId}`); + + if (this.providers[instanceId]) { + Log.log(`Weather provider ${identifier} already initialized for instance ${instanceId}`); + return; + } + + try { + // Dynamically load the provider module + const providerPath = path.join(__dirname, "providers", `${identifier}.js`); + Log.log(`Loading provider from: ${providerPath}`); + const ProviderClass = require(providerPath); + + // Create provider instance + const provider = new ProviderClass(config); + + // Set up callbacks before initializing + provider.setCallbacks( + (data) => { + // On data received + this.sendSocketNotification("WEATHER_DATA", { + instanceId, + type: config.type, + data + }); + }, + (errorInfo) => { + // On error + this.sendSocketNotification("WEATHER_ERROR", { + instanceId, + error: errorInfo.message || "Unknown error", + translationKey: errorInfo.translationKey + }); + } + ); + + await provider.initialize(); + this.providers[instanceId] = provider; + + this.sendSocketNotification("WEATHER_INITIALIZED", { + instanceId, + locationName: provider.locationName + }); + + // Start periodic fetching + provider.start(); + + Log.log(`Weather provider ${identifier} initialized for instance ${instanceId}`); + } catch (error) { + Log.error(`Failed to initialize weather provider ${identifier}:`, error); + this.sendSocketNotification("WEATHER_ERROR", { + instanceId, + error: error.message + }); + } + }, + + /** + * Stop and cleanup a weather provider + * @param {string} instanceId The instance identifier + */ + stopWeatherProvider (instanceId) { + const provider = this.providers[instanceId]; + + if (provider) { + Log.log(`Stopping weather provider for instance ${instanceId}`); + provider.stop(); + delete this.providers[instanceId]; + } else { + Log.warn(`No provider found for instance ${instanceId}`); + } + } +}); diff --git a/defaultmodules/weather/provider-utils.js b/defaultmodules/weather/provider-utils.js new file mode 100644 index 0000000000..f29e4396c5 --- /dev/null +++ b/defaultmodules/weather/provider-utils.js @@ -0,0 +1,181 @@ +/** + * Shared utility functions for weather providers + */ + +const SunCalc = require("suncalc"); + +/** + * Convert OpenWeatherMap icon codes to internal weather types + * @param {string} weatherType - OpenWeatherMap icon code (e.g., "01d", "02n") + * @returns {string|null} Internal weather type + */ +function convertWeatherType (weatherType) { + const weatherTypes = { + "01d": "day-sunny", + "02d": "day-cloudy", + "03d": "cloudy", + "04d": "cloudy-windy", + "09d": "showers", + "10d": "rain", + "11d": "thunderstorm", + "13d": "snow", + "50d": "fog", + "01n": "night-clear", + "02n": "night-cloudy", + "03n": "night-cloudy", + "04n": "night-cloudy", + "09n": "night-showers", + "10n": "night-rain", + "11n": "night-thunderstorm", + "13n": "night-snow", + "50n": "night-alt-cloudy-windy" + }; + + return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; +} + +/** + * Apply timezone offset to a date + * @param {Date} date - The date to apply offset to + * @param {number} offsetMinutes - Timezone offset in minutes + * @returns {Date} Date with applied offset + */ +function applyTimezoneOffset (date, offsetMinutes) { + const utcTime = date.getTime() + (date.getTimezoneOffset() * 60000); + return new Date(utcTime + (offsetMinutes * 60000)); +} + +/** + * Limit decimal places for coordinates (truncate, not round) + * @param {number} value - The coordinate value + * @param {number} decimals - Maximum number of decimal places + * @returns {number} Value with limited decimal places + */ +function limitDecimals (value, decimals) { + const str = value.toString(); + if (str.includes(".")) { + const parts = str.split("."); + if (parts[1].length > decimals) { + return parseFloat(`${parts[0]}.${parts[1].substring(0, decimals)}`); + } + } + return value; +} + +/** + * Get sunrise and sunset times for a given date and location + * @param {Date} date - The date to calculate for + * @param {number} lat - Latitude + * @param {number} lon - Longitude + * @returns {object} Object with sunrise and sunset Date objects + */ +function getSunTimes (date, lat, lon) { + const sunTimes = SunCalc.getTimes(date, lat, lon); + return { + sunrise: sunTimes.sunrise, + sunset: sunTimes.sunset + }; +} + +/** + * Check if a given time is during daylight hours + * @param {Date} date - The date/time to check + * @param {Date} sunrise - Sunrise time + * @param {Date} sunset - Sunset time + * @returns {boolean} True if during daylight hours + */ +function isDayTime (date, sunrise, sunset) { + if (!sunrise || !sunset) { + return true; // Default to day if times unavailable + } + return date >= sunrise && date < sunset; +} + +/** + * Format timezone offset as string (e.g., "+01:00", "-05:30") + * @param {number} offsetMinutes - Timezone offset in minutes (use -new Date().getTimezoneOffset() for local) + * @returns {string} Formatted offset string + */ +function formatTimezoneOffset (offsetMinutes) { + const hours = Math.floor(Math.abs(offsetMinutes) / 60); + const minutes = Math.abs(offsetMinutes) % 60; + const sign = offsetMinutes >= 0 ? "+" : "-"; + return `${sign}${String(hours).padStart(2, "0")}:${String(minutes).padStart(2, "0")}`; +} + +/** + * Get date string in YYYY-MM-DD format (local time) + * @param {Date} date - The date to format + * @returns {string} Date string in YYYY-MM-DD format + */ +function getDateString (date) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const day = String(date.getDate()).padStart(2, "0"); + return `${year}-${month}-${day}`; +} + +/** + * Convert wind speed from km/h to m/s + * @param {number} kmh - Wind speed in km/h + * @returns {number} Wind speed in m/s + */ +function convertKmhToMs (kmh) { + return kmh / 3.6; +} + +/** + * Convert cardinal wind direction string to degrees + * @param {string} direction - Cardinal direction (e.g., "N", "NNE", "SW") + * @returns {number|null} Direction in degrees (0-360) or null if unknown + */ +function cardinalToDegrees (direction) { + const directions = { + N: 0, + NNE: 22.5, + NE: 45, + ENE: 67.5, + E: 90, + ESE: 112.5, + SE: 135, + SSE: 157.5, + S: 180, + SSW: 202.5, + SW: 225, + WSW: 247.5, + W: 270, + WNW: 292.5, + NW: 315, + NNW: 337.5 + }; + return directions[direction] ?? null; +} + +/** + * Validate and limit coordinate precision + * @param {object} config - Configuration object with lat/lon properties + * @param {number} maxDecimals - Maximum decimal places to preserve + * @throws {Error} If coordinates are missing or invalid + */ +function validateCoordinates (config, maxDecimals = 4) { + if (config.lat == null || config.lon == null + || !Number.isFinite(config.lat) || !Number.isFinite(config.lon)) { + throw new Error("Latitude and longitude are required"); + } + + config.lat = limitDecimals(config.lat, maxDecimals); + config.lon = limitDecimals(config.lon, maxDecimals); +} + +module.exports = { + convertWeatherType, + applyTimezoneOffset, + limitDecimals, + getSunTimes, + isDayTime, + formatTimezoneOffset, + getDateString, + convertKmhToMs, + cardinalToDegrees, + validateCoordinates +}; diff --git a/defaultmodules/weather/providers/README.md b/defaultmodules/weather/providers/README.md index faa60a058a..62959756d4 100644 --- a/defaultmodules/weather/providers/README.md +++ b/defaultmodules/weather/providers/README.md @@ -1,3 +1,3 @@ # Weather Module Weather Provider Development Documentation -For how to develop your own weather provider, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/development/weather-provider.html). +For how to develop your own weather provider, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/module-development/weather-provider.html). diff --git a/defaultmodules/weather/providers/envcanada.js b/defaultmodules/weather/providers/envcanada.js index d3d7cd5d67..a50a812143 100644 --- a/defaultmodules/weather/providers/envcanada.js +++ b/defaultmodules/weather/providers/envcanada.js @@ -1,579 +1,408 @@ -/* global WeatherProvider, WeatherObject, WeatherUtils */ +const Log = require("logger"); +const { convertKmhToMs } = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); -/* - * This class is a provider for Environment Canada MSC Datamart - * Note that this is only for Canadian locations and does not require an API key (access is anonymous) +/** + * Server-side weather provider for Environment Canada MSC Datamart + * Canada only, no API key required (anonymous access) * - * EC Documentation at following links: - * https://dd.weather.gc.ca/citypage_weather/schema/ - * https://eccc-msc.github.io/open-data/msc-datamart/readme_en/ + * Documentation: + * https://dd.weather.gc.ca/citypage_weather/schema/ + * https://eccc-msc.github.io/open-data/msc-datamart/readme_en/ * - * This module supports Canadian locations only and requires 2 additional config parameters: - * - * siteCode - the city/town unique identifier for which weather is to be displayed. Format is 's0000000'. - * - * provCode - the 2-character province code for the selected city/town. - * - * Example: for Toronto, Ontario, the following parameters would be used - * - * siteCode: 's0000458', - * provCode: 'ON' - * - * To determine the siteCode and provCode values for a Canadian city/town, look at the Environment Canada document - * at https://dd.weather.gc.ca/citypage_weather/docs/site_list_en.csv (or site_list_fr.csv). There you will find a table - * with locations you can search under column B (English Names), with the corresponding siteCode under - * column A (Codes) and provCode under column C (Province). - * - * Acknowledgement: Some logic and code for parsing Environment Canada web pages is based on material from MMM-EnvCanada - * - * License to use Environment Canada (EC) data is detailed here: - * https://eccc-msc.github.io/open-data/licence/readme_en/ + * Requires siteCode and provCode config parameters + * See https://dd.weather.gc.ca/citypage_weather/docs/site_list_en.csv */ -WeatherProvider.register("envcanada", { - // Set the name of the provider for debugging and alerting purposes (eg. provide eye-catcher) - providerName: "Environment Canada", - - // Set the default config properties that is specific to this provider - defaults: { - useCorsProxy: true, - siteCode: "s1234567", - provCode: "ON" - }, - - /* - * Set config values (equates to weather module config values). Also set values pertaining to caching of - * Today's temperature forecast (for use in the Forecast functions below) - */ - setConfig (config) { - this.config = config; - - this.todayTempCacheMin = 0; - this.todayTempCacheMax = 0; - this.todayCached = false; - this.cacheCurrentTemp = 999; - this.lastCityPageCurrent = " "; - this.lastCityPageForecast = " "; - this.lastCityPageHourly = " "; - }, - - /* - * Called when the weather provider is started - */ - start () { - Log.info(`[weatherprovider.envcanada] ${this.providerName} started.`); - this.setFetchedLocation(this.config.location); - }, - - /* - * Override the fetchCurrentWeather method to query EC and construct a Current weather object - */ - fetchCurrentWeather () { - this.fetchCommon("Current"); - }, - - /* - * Override the fetchWeatherForecast method to query EC and construct Forecast/Daily weather objects - */ - fetchWeatherForecast () { - - this.fetchCommon("Forecast"); - - }, - - /* - * Override the fetchWeatherHourly method to query EC and construct Hourly weather objects - */ - fetchWeatherHourly () { - this.fetchCommon("Hourly"); - }, - - /* - * Because the process to fetch weather data is virtually the same for Current, Forecast/Daily, and Hourly weather, - * a common module is used to access the EC weather data. The only customization (based on the caller of this routine) - * is how the data will be parsed to satisfy the Weather module config in Config.js - * - * Accessing EC weather data is accomplished in 2 steps: - * - * 1. Query the MSC Datamart Index page, which returns a list of all the filenames for all the cities that have - * weather data currently available. - * - * 2. With the city filename identified, build the appropriate URL and get the weather data (XML document) for the - * city specified in the Weather module Config information - */ - fetchCommon (target) { - const forecastURL = this.getUrl(); // Get the appropriate URL for the MSC Datamart Index page - - Log.debug(`[weatherprovider.envcanada] ${target} Index url: ${forecastURL}`); - - this.fetchData(forecastURL, "xml") // Query the Index page URL - .then((indexData) => { - if (!indexData) { - // Did not receive usable new data. - Log.info(`[weatherprovider.envcanada] ${target} - did not receive usable index data`); - this.updateAvailable(); // If there were issues, update anyways to reset timer - return; - } +class EnvCanadaProvider { + constructor (config) { + this.config = { + siteCode: "s0000000", + provCode: "ON", + type: "current", + updateInterval: 10 * 60 * 1000, + ...config + }; - /** - * With the Index page read, we must locate the filename/link for the specified city (aka Sitecode). - * This is done by building the city filename and searching for it on the Index page. Once found, - * extract the full filename (a unique name that includes dat/time, filename, etc.) and then add it - * to the Index page URL to create the proper URL pointing to the city's weather data. Finally, read the - * URL to pull in the city's XML document so that weather data can be parsed and displayed. - */ - - let forecastFile = ""; - let forecastFileURL = ""; - const fileSuffix = `${this.config.siteCode}_en.xml`; // Build city filename - const nextFile = indexData.body.innerHTML.split(fileSuffix); // Find filename on Index page - - if (nextFile.length > 1) { // Parse out the full unique file city filename - // Find the last occurrence - forecastFile = nextFile[nextFile.length - 2].slice(-41) + fileSuffix; - forecastFileURL = forecastURL + forecastFile; // Create full URL to the city's weather data - } + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + this.lastCityPageURL = null; + this.cacheCurrentTemp = null; + this.currentHour = null; // Track current hour for URL updates + } + + async initialize () { + this.#validateConfig(); + this.#initializeFetcher(); + } - Log.debug(`[weatherprovider.envcanada] ${target} Citypage url: ${forecastFileURL}`); + setCallbacks (onData, onError) { + this.onDataCallback = onData; + this.onErrorCallback = onError; + } + + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); + } + } + + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } + } - /* - * If the Citypage filename has not changed since the last Weather refresh, the forecast has not changed and - * and therefore we can skip reading the Citypage URL. - */ + #validateConfig () { + if (!this.config.siteCode || !this.config.provCode) { + throw new Error("siteCode and provCode are required"); + } + } - if (target === "Current" && this.lastCityPageCurrent === forecastFileURL) { - Log.debug(`[weatherprovider.envcanada] ${target} - Newest Citypage has already been seen - skipping!`); - this.updateAvailable(); // Update anyways to reset refresh timer + #initializeFetcher () { + this.currentHour = new Date().toISOString().substring(11, 13); + const indexURL = this.#getIndexUrl(); + + this.fetcher = new HTTPFetcher(indexURL, { + reloadInterval: this.config.updateInterval, + logContext: "weatherprovider.envcanada" + }); + + this.fetcher.on("response", async (response) => { + try { + // Check if hour changed - restart fetcher with new URL + const newHour = new Date().toISOString().substring(11, 13); + if (newHour !== this.currentHour) { + Log.info("[envcanada] Hour changed, reinitializing fetcher"); + this.stop(); + this.#initializeFetcher(); + this.start(); return; } - if (target === "Forecast" && this.lastCityPageForecast === forecastFileURL) { - Log.debug(`[weatherprovider.envcanada] ${target} - Newest Citypage has already been seen - skipping!`); - this.updateAvailable(); // Update anyways to reset refresh timer + const html = await response.text(); + const cityPageURL = this.#extractCityPageURL(html); + + if (!cityPageURL) { + // This can happen during hour transitions when old responses arrive + Log.debug("[envcanada] Could not find city page URL (may be stale response from previous hour)"); return; } - if (target === "Hourly" && this.lastCityPageHourly === forecastFileURL) { - Log.debug(`[weatherprovider.envcanada] ${target} - Newest Citypage has already been seen - skipping!`); - this.updateAvailable(); // Update anyways to reset refresh timer + if (cityPageURL === this.lastCityPageURL) { + Log.debug("[envcanada] City page unchanged"); return; } - this.fetchData(forecastFileURL, "xml") // Read city's URL to get weather data - .then((cityData) => { - if (!cityData) { - // Did not receive usable new data. - Log.info(`[weatherprovider.envcanada] ${target} - did not receive usable citypage data`); - return; - } - - /* - * With the city's weather data read, parse the resulting XML document for the appropriate weather data - * elements to create a weather object. Next, set Weather modules details from that object. - */ - Log.debug(`[weatherprovider.envcanada] ${target} - Citypage has been read and will be processed for updates`); - - if (target === "Current") { - const currentWeather = this.generateWeatherObjectFromCurrentWeather(cityData); - this.setCurrentWeather(currentWeather); - this.lastCityPageCurrent = forecastFileURL; - } - - if (target === "Forecast") { - const forecastWeather = this.generateWeatherObjectsFromForecast(cityData); - this.setWeatherForecast(forecastWeather); - this.lastCityPageForecast = forecastFileURL; - } - - if (target === "Hourly") { - const hourlyWeather = this.generateWeatherObjectsFromHourly(cityData); - this.setWeatherHourly(hourlyWeather); - this.lastCityPageHourly = forecastFileURL; - } - }) - .catch(function (cityRequest) { - Log.info(`[weatherprovider.envcanada] ${target} - could not load citypage data from: ${forecastFileURL}`); - }) - .finally(() => this.updateAvailable()); // Update no matter what to reset weather refresh timer - }) - .catch(function (indexRequest) { - Log.error(`[weatherprovider.envcanada] ${target} - could not load index data ... `, indexRequest); - this.updateAvailable(); // If there were issues, update anyways to reset timer - }); - }, - - /* - * Build the EC Index page URL based on current GMT hour. The Index page will provide a list of links for each city - * that will, in turn, provide actual weather data. The URL is comprised of 3 parts: - * - * Fixed value + Prov code specified in Weather module Config.js + current hour as GMT - */ - getUrl () { - let forecastURL = `https://dd.weather.gc.ca/today/citypage_weather/${this.config.provCode}`; - const hour = this.getCurrentHourGMT(); - forecastURL += `/${hour}/`; - return forecastURL; - }, - - /* - * Get current hour-of-day in GMT context - */ - getCurrentHourGMT () { - const now = new Date(); - return now.toISOString().substring(11, 13); // "HH" in GMT - }, - - /* - * Generate a WeatherObject based on current EC weather conditions - */ - generateWeatherObjectFromCurrentWeather (ECdoc) { - const currentWeather = new WeatherObject(); - - /* - * There are instances where EC will update weather data and current temperature will not be - * provided. While this is a defect in the EC systems, we need to accommodate to avoid a current temp - * of NaN being displayed. Therefore... whenever we get a valid current temp from EC, we will cache - * the value. Whenever EC data is missing current temp, we will provide the cached value - * instead. This is reasonable since the cached value will typically be accurate within the previous - * hour. The only time this does not work as expected is when MM is restarted and the first query to - * EC finds no current temp. In this scenario, MM will end up displaying a current temp of null; - */ - if (ECdoc.querySelector("siteData currentConditions temperature").textContent) { - currentWeather.temperature = ECdoc.querySelector("siteData currentConditions temperature").textContent; - this.cacheCurrentTemp = currentWeather.temperature; - } else { - currentWeather.temperature = this.cacheCurrentTemp; - } - - if (ECdoc.querySelector("siteData currentConditions wind speed").textContent === "calm") { - currentWeather.windSpeed = "0"; - } else { - currentWeather.windSpeed = WeatherUtils.convertWindToMs(ECdoc.querySelector("siteData currentConditions wind speed").textContent); - } + this.lastCityPageURL = cityPageURL; + await this.#fetchCityPage(cityPageURL); - currentWeather.windFromDirection = ECdoc.querySelector("siteData currentConditions wind bearing").textContent; + } catch (error) { + Log.error("[envcanada] Error:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: error.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + } + }); - currentWeather.humidity = ECdoc.querySelector("siteData currentConditions relativeHumidity").textContent; + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } - /* - * Ensure showPrecipitationAmount is forced to false. EC does not really provide POP for current day - * and this feature for the weather module (current only) is sort of broken in that it wants - * to say POP but will display precip as an accumulated amount vs. a percentage. - */ - this.config.showPrecipitationAmount = false; + async #fetchCityPage (url) { + try { + const response = await fetch(url); + if (!response.ok) throw new Error(`HTTP ${response.status}`); - /* - * If the module config wants to showFeelsLike... default to the current temperature. - * Check for EC wind chill and humidex values and overwrite the feelsLikeTemp value. - * This assumes that the EC current conditions will never contain both a wind chill - * and humidex temperature. - */ - if (this.config.showFeelsLike) { - currentWeather.feelsLikeTemp = currentWeather.temperature; + const xml = await response.text(); + const weatherData = this.#parseWeatherData(xml); - if (ECdoc.querySelector("siteData currentConditions windChill")) { - currentWeather.feelsLikeTemp = ECdoc.querySelector("siteData currentConditions windChill").textContent; + if (this.onDataCallback) { + this.onDataCallback(weatherData); } - - if (ECdoc.querySelector("siteData currentConditions humidex")) { - currentWeather.feelsLikeTemp = ECdoc.querySelector("siteData currentConditions humidex").textContent; + } catch (error) { + Log.error("[envcanada] Fetch city page error:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to fetch city data", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } } + } - // Need to map EC weather icon to MM weatherType values - currentWeather.weatherType = this.convertWeatherType(ECdoc.querySelector("siteData currentConditions iconCode").textContent); + #parseWeatherData (xml) { + switch (this.config.type) { + case "current": + return this.#generateCurrentWeather(xml); + case "forecast": + case "daily": + return this.#generateForecast(xml); + case "hourly": + return this.#generateHourly(xml); + default: + Log.error(`[envcanada] Unknown weather type: ${this.config.type}`); + return null; + } + } - // Capture the sunrise and sunset values from EC data - const sunList = ECdoc.querySelectorAll("siteData riseSet dateTime"); + #generateCurrentWeather (xml) { + const current = { date: new Date() }; - currentWeather.sunrise = moment(sunList[1].querySelector("timeStamp").textContent, "YYYYMMDDhhmmss"); - currentWeather.sunset = moment(sunList[3].querySelector("timeStamp").textContent, "YYYYMMDDhhmmss"); + // Try to get temperature from currentConditions first + const currentTempStr = this.#extract(xml, /.*?]*>(.*?)<\/temperature>/s); - return currentWeather; - }, + if (currentTempStr && currentTempStr !== "") { + current.temperature = parseFloat(currentTempStr); + this.cacheCurrentTemp = current.temperature; + } else { + // Fallback: extract from first forecast period if currentConditions is empty + const firstForecast = xml.match(/(.*?)<\/forecast>/s); + if (firstForecast) { + const forecastXml = firstForecast[1]; + const temp = this.#extract(forecastXml, /]*>(.*?)<\/temperature>/); + if (temp && temp !== "") { + current.temperature = parseFloat(temp); + this.cacheCurrentTemp = current.temperature; + } else if (this.cacheCurrentTemp !== null) { + current.temperature = this.cacheCurrentTemp; + } else { + current.temperature = null; + } + } + } - /* - * Generate an array of WeatherObjects based on EC weather forecast - */ - generateWeatherObjectsFromForecast (ECdoc) { - // Declare an array to hold each day's forecast object - const days = []; + // Wind chill / humidex for feels like temperature + const windChill = this.#extract(xml, /]*>(.*?)<\/windChill>/); + const humidex = this.#extract(xml, /]*>(.*?)<\/humidex>/); + if (windChill) { + current.feelsLikeTemp = parseFloat(windChill); + } else if (humidex) { + current.feelsLikeTemp = parseFloat(humidex); + } - const weather = new WeatherObject(); - - const foreBaseDates = ECdoc.querySelectorAll("siteData forecastGroup dateTime"); - const baseDate = foreBaseDates[1].querySelector("timeStamp").textContent; - - weather.date = moment(baseDate, "YYYYMMDDhhmmss"); - - const foreGroup = ECdoc.querySelectorAll("siteData forecastGroup forecast"); - - weather.precipitationAmount = null; - - /* - * The EC forecast is held in a 12-element array - Elements 0 to 11 - with each day encompassing - * 2 elements. the first element for a day details the Today (daytime) forecast while the second - * element details the Tonight (nighttime) forecast. Element 0 is always for the current day. - * - * However... the forecast is somewhat 'rolling'. - * - * If the EC forecast is queried in the morning, then Element 0 will contain Current - * Today and Element 1 will contain Current Tonight. From there, the next 5 days of forecast will be - * contained in Elements 2/3, 4/5, 6/7, 8/9, and 10/11. This module will create a 6-day forecast using - * all of these Elements. - * - * But, if the EC forecast is queried in late afternoon, the Current Today forecast will be rolled - * off and Element 0 will contain Current Tonight. From there, the next 5 days will be contained in - * Elements 1/2, 3/4, 5/6, 7/8, and 9/10. As well, Element 11 will contain a forecast for a 6th day, - * but only for the Today portion (not Tonight). This module will create a 6-day forecast using - * Elements 0 to 11, and will ignore the additional Today forecast in Element 11. - * - * We need to determine if Element 0 is showing the forecast for Current Today or Current Tonight. - * This is required to understand how Min and Max temperature will be determined, and to understand - * where the next day's (aka Tomorrow's) forecast is located in the forecast array. - */ - let nextDay = 0; - let lastDay = 0; - const currentTemp = ECdoc.querySelector("siteData currentConditions temperature").textContent; - - // If the first Element is Current Today, look at Current Today and Current Tonight for the current day. - if (foreGroup[0].querySelector("period[textForecastName='Today']")) { - this.todaytempCacheMin = 0; - this.todaytempCacheMax = 0; - this.todayCached = true; - - this.setMinMaxTemps(weather, foreGroup, 0, true, currentTemp); - - this.setPrecipitation(weather, foreGroup, 0); - - /* - * Set the Element number that will reflect where the next day's forecast is located. Also set - * the Element number where the end of the forecast will be. This is important because of the - * rolling nature of the EC forecast. In the current scenario (Today and Tonight are present - * in elements 0 and 11, we know that we will have 6 full days of forecasts and we will use - * them. We will set lastDay such that we iterate through all 12 elements of the forecast. - */ - nextDay = 2; - lastDay = 12; + // Get wind and icon from currentConditions or first forecast + const firstForecast = xml.match(/(.*?)<\/forecast>/s); + if (!firstForecast) { + Log.warn("[envcanada] No forecast data available"); + return current; } - // If the first Element is Current Tonight, look at Tonight only for the current day. - if (foreGroup[0].querySelector("period[textForecastName='Tonight']")) { - this.setMinMaxTemps(weather, foreGroup, 0, false, currentTemp); - - this.setPrecipitation(weather, foreGroup, 0); - - /* - * Set the Element number that will reflect where the next day's forecast is located. Also set - * the Element number where the end of the forecast will be. This is important because of the - * rolling nature of the EC forecast. In the current scenario (only Current Tonight is present - * in Element 0, we know that we will have 6 full days of forecasts PLUS a half-day and - * forecast in the final element. Because we will only use full day forecasts, we set the - * lastDay number to ensure we ignore that final half-day (in forecast Element 11). - */ - nextDay = 1; - lastDay = 11; + const forecastXml = firstForecast[1]; + + // Wind speed - try currentConditions first, fallback to forecast + let windSpeed = this.#extract(xml, /.*?.*?]*>(.*?)<\/speed>/s); + if (!windSpeed) { + windSpeed = this.#extract(forecastXml, /]*>(.*?)<\/speed>/); } + if (windSpeed) { + current.windSpeed = (windSpeed === "calm") ? 0 : convertKmhToMs(parseFloat(windSpeed)); + } + + // Wind bearing - try currentConditions first, fallback to forecast + let windBearing = this.#extract(xml, /.*?.*?]*>(.*?)<\/bearing>/s); + if (!windBearing) { + windBearing = this.#extract(forecastXml, /]*>(.*?)<\/bearing>/); + } + if (windBearing) current.windFromDirection = parseFloat(windBearing); - /* - * Need to map EC weather icon to MM weatherType values. Always pick the first Element's icon to - * reflect either Today or Tonight depending on what the forecast is showing in Element 0. - */ - weather.weatherType = this.convertWeatherType(foreGroup[0].querySelector("abbreviatedForecast iconCode").textContent); + // Try icon from currentConditions first, fallback to forecast + let iconCode = this.#extract(xml, /.*?]*>(.*?)<\/iconCode>/s); + if (!iconCode) { + iconCode = this.#extract(forecastXml, /]*>(.*?)<\/iconCode>/); + } + if (iconCode) current.weatherType = this.#convertWeatherType(iconCode); + + // Humidity from currentConditions + const humidity = this.#extract(xml, /.*?]*>(.*?)<\/relativeHumidity>/s); + if (humidity) current.humidity = parseFloat(humidity); - // Push the weather object into the forecast array. - days.push(weather); + // Precipitation probability from forecast + const pop = this.#extract(forecastXml, /]*>(.*?)<\/pop>/); + if (pop && pop !== "") { + current.precipitationProbability = parseFloat(pop); + } - /* - * Now do the rest of the forecast starting at nextDay. We will process each day using 2 EC - * forecast Elements. This will address the fact that the EC forecast always includes Today and - * Tonight for each day. This is why we iterate through the forecast by a a count of 2, with each - * iteration looking at the current Element and the next Element. - */ - let lastDate = moment(baseDate, "YYYYMMDDhhmmss"); + // Sunrise/sunset (from riseSet, independent of currentConditions) + const sunriseTime = this.#extract(xml, /]*name="sunrise"[^>]*>.*?(.*?)<\/timeStamp>/s); + const sunsetTime = this.#extract(xml, /]*name="sunset"[^>]*>.*?(.*?)<\/timeStamp>/s); + if (sunriseTime) current.sunrise = this.#parseECTime(sunriseTime); + if (sunsetTime) current.sunset = this.#parseECTime(sunsetTime); - for (let stepDay = nextDay; stepDay < lastDay; stepDay += 2) { - let weather = new WeatherObject(); + return current; + } - // Add 1 to the date to reflect the current forecast day we are building - lastDate = lastDate.add(1, "day"); - weather.date = moment(lastDate); + #generateForecast (xml) { + const days = []; + const forecasts = xml.match(/(.*?)<\/forecast>/gs) || []; - /* - * Capture the temperatures for the current Element and the next Element in order to set - * the Min and Max temperatures for the forecast - */ - this.setMinMaxTemps(weather, foreGroup, stepDay, true, currentTemp); + if (forecasts.length === 0) return days; - weather.precipitationAmount = null; + // Get current temp + const currentTempStr = this.#extract(xml, /.*?]*>(.*?)<\/temperature>/s); + const currentTemp = currentTempStr ? parseFloat(currentTempStr) : null; - this.setPrecipitation(weather, foreGroup, stepDay); + // Check if first forecast is Today or Tonight + const isToday = forecasts[0].includes("textForecastName=\"Today\""); - // Need to map EC weather icon to MM weatherType values. Always pick the first Element icon. - weather.weatherType = this.convertWeatherType(foreGroup[stepDay].querySelector("abbreviatedForecast iconCode").textContent); + let nextDay = isToday ? 2 : 1; + const lastDay = isToday ? 12 : 11; - // Push the weather object into the forecast array. - days.push(weather); + // Process first day + const firstDay = { + date: new Date(), + precipitationProbability: null + }; + this.#extractForecastTemps(firstDay, forecasts, 0, isToday, currentTemp); + this.#extractForecastPrecip(firstDay, forecasts, 0); + const firstIcon = this.#extract(forecasts[0], /]*>(.*?)<\/iconCode>/); + if (firstIcon) firstDay.weatherType = this.#convertWeatherType(firstIcon); + days.push(firstDay); + + // Process remaining days + let date = new Date(); + for (let i = nextDay; i < lastDay && i < forecasts.length; i += 2) { + date = new Date(date); + date.setDate(date.getDate() + 1); + + const day = { + date: new Date(date), + precipitationProbability: null + }; + this.#extractForecastTemps(day, forecasts, i, true, currentTemp); + this.#extractForecastPrecip(day, forecasts, i); + const icon = this.#extract(forecasts[i], /]*>(.*?)<\/iconCode>/); + if (icon) day.weatherType = this.#convertWeatherType(icon); + days.push(day); } return days; - }, + } - /* - * Generate an array of WeatherObjects based on EC hourly weather forecast - */ - generateWeatherObjectsFromHourly (ECdoc) { - // Declare an array to hold each hour's forecast object - const hours = []; + #extractForecastTemps (weather, forecasts, index, hasToday, currentTemp) { + let tempToday = null; + let tempTonight = null; - // Get local timezone UTC offset so that each hourly time can be calculated properly - const baseHours = ECdoc.querySelectorAll("siteData hourlyForecastGroup dateTime"); - const hourOffset = baseHours[1].getAttribute("UTCOffset"); + if (hasToday && forecasts[index]) { + const temp = this.#extract(forecasts[index], /]*>(.*?)<\/temperature>/); + if (temp) tempToday = parseFloat(temp); + } - /* - * The EC hourly forecast is held in a 24-element array - Elements 0 to 23 - with Element 0 holding - * the forecast for the next 'on the hour' time slot. This means the array is a rolling 24 hours. - */ - const hourGroup = ECdoc.querySelectorAll("siteData hourlyForecastGroup hourlyForecast"); + if (forecasts[index + 1]) { + const temp = this.#extract(forecasts[index + 1], /]*>(.*?)<\/temperature>/); + if (temp) tempTonight = parseFloat(temp); + } - for (let stepHour = 0; stepHour < 24; stepHour += 1) { - const weather = new WeatherObject(); + if (tempToday !== null && tempTonight !== null) { + weather.maxTemperature = Math.max(tempToday, tempTonight); + weather.minTemperature = Math.min(tempToday, tempTonight); + } else if (tempToday !== null) { + weather.maxTemperature = tempToday; + weather.minTemperature = currentTemp || tempToday; + } else if (tempTonight !== null) { + weather.maxTemperature = currentTemp || tempTonight; + weather.minTemperature = tempTonight; + } + } - // Determine local time by applying UTC offset to the forecast timestamp - const foreTime = moment(hourGroup[stepHour].getAttribute("dateTimeUTC"), "YYYYMMDDhhmmss"); - const currTime = foreTime.add(hourOffset, "hours"); - weather.date = moment(currTime); + #extractForecastPrecip (weather, forecasts, index) { + const precips = []; - // Capture the temperature - weather.temperature = hourGroup[stepHour].querySelector("temperature").textContent; + if (forecasts[index]) { + const pop = this.#extract(forecasts[index], /]*>(.*?)<\/pop>/); + if (pop) precips.push(parseFloat(pop)); + } - // Capture Likelihood of Precipitation (LOP) and unit-of-measure values - const precipLOP = hourGroup[stepHour].querySelector("lop").textContent * 1.0; + if (forecasts[index + 1]) { + const pop = this.#extract(forecasts[index + 1], /]*>(.*?)<\/pop>/); + if (pop) precips.push(parseFloat(pop)); + } - if (precipLOP > 0) { - weather.precipitationProbability = precipLOP; - } + if (precips.length > 0) { + weather.precipitationProbability = Math.max(...precips); + } + } + + #generateHourly (xml) { + const hours = []; + const hourlyMatches = xml.matchAll(/]*dateTimeUTC="([^"]*)"[^>]*>(.*?)<\/hourlyForecast>/gs); + + for (const [, dateTimeUTC, hourXML] of hourlyMatches) { + const weather = {}; - // Need to map EC weather icon to MM weatherType values. Always pick the first Element icon. - weather.weatherType = this.convertWeatherType(hourGroup[stepHour].querySelector("iconCode").textContent); + weather.date = this.#parseECTime(dateTimeUTC); + + const temp = this.#extract(hourXML, /]*>(.*?)<\/temperature>/); + if (temp) weather.temperature = parseFloat(temp); + + const lop = this.#extract(hourXML, /]*>(.*?)<\/lop>/); + if (lop) weather.precipitationProbability = parseFloat(lop); + + const icon = this.#extract(hourXML, /]*>(.*?)<\/iconCode>/); + if (icon) weather.weatherType = this.#convertWeatherType(icon); - // Push the weather object into the forecast array. hours.push(weather); + if (hours.length >= 24) break; } return hours; - }, - - /* - * Determine Min and Max temp based on a supplied Forecast Element index and a boolean that denotes if - * the next Forecast element should be considered - i.e. look at Today *and* Tonight vs.Tonight-only - */ - setMinMaxTemps (weather, foreGroup, today, fullDay, currentTemp) { - const todayTemp = foreGroup[today].querySelector("temperatures temperature").textContent; - - const todayClass = foreGroup[today].querySelector("temperatures temperature").getAttribute("class"); - - /* - * The following logic is largely aimed at accommodating the Current day's forecast whereby we - * can have either Current Today+Current Tonight or only Current Tonight. - * - * If fullDay is false, then we only have Tonight for the current day's forecast - meaning we have - * lost a min or max temp value for the day. Therefore, we will see if we were able to cache the the - * Today forecast for the current day. If we have, we will use them. If we do not have the cached values, - * it means that MM or the Computer has been restarted since the time EC rolled off Today from the - * forecast. In this scenario, we will simply default to the Current Conditions temperature and then - * check the Tonight temperature.x - */ - if (fullDay === false) { - if (this.todayCached === true) { - weather.minTemperature = this.todayTempCacheMin; - weather.maxTemperature = this.todayTempCacheMax; - } else { - weather.minTemperature = currentTemp; - weather.maxTemperature = weather.minTemperature; - } - } + } - /* - * We will check to see if the current Element's temperature is Low or High and set weather values - * accordingly. We will also check the condition where fullDay is true *and* we are looking at forecast - * element 0. This is a special case where we will cache temperature values so that we have them later - * in the current day when the Current Today element rolls off and we have Current Tonight only. - */ - if (todayClass === "low") { - weather.minTemperature = todayTemp; - if (today === 0 && fullDay === true) { - this.todayTempCacheMin = weather.minTemperature; - } - } + #extract (text, pattern) { + const match = text.match(pattern); + return match ? match[1].trim() : null; + } - if (todayClass === "high") { - weather.maxTemperature = todayTemp; - if (today === 0 && fullDay === true) { - this.todayTempCacheMax = weather.maxTemperature; - } + #getIndexUrl () { + const hour = new Date().toISOString().substring(11, 13); + return `https://dd.weather.gc.ca/today/citypage_weather/${this.config.provCode}/${hour}/`; + } + + #extractCityPageURL (html) { + // New format: {timestamp}_MSC_CitypageWeather_{siteCode}_en.xml + const pattern = `[^"]*_MSC_CitypageWeather_${this.config.siteCode}_en\\.xml`; + const match = html.match(new RegExp(`href="(${pattern})"`)); + + if (match && match[1]) { + return this.#getIndexUrl() + match[1]; } - const nextTemp = foreGroup[today + 1].querySelector("temperatures temperature").textContent; + return null; + } - const nextClass = foreGroup[today + 1].querySelector("temperatures temperature").getAttribute("class"); + #parseECTime (timeStr) { + if (!timeStr || timeStr.length < 12) return new Date(); - if (fullDay === true) { - if (nextClass === "low") { - weather.minTemperature = nextTemp; - } + const y = parseInt(timeStr.substring(0, 4), 10); + const m = parseInt(timeStr.substring(4, 6), 10) - 1; + const d = parseInt(timeStr.substring(6, 8), 10); + const h = parseInt(timeStr.substring(8, 10), 10); + const min = parseInt(timeStr.substring(10, 12), 10); + const s = timeStr.length >= 14 ? parseInt(timeStr.substring(12, 14), 10) : 0; - if (nextClass === "high") { - weather.maxTemperature = nextTemp; - } - } - }, - - /* - * Check for a Precipitation forecast. EC can provide a forecast in 2 ways: either an accumulation figure - * or a POP percentage. If there is a POP, then that is what the module will show. If there is an accumulation, - * then it will be displayed ONLY if no POP is present. - * - * POP Logic: By default, we want to show the POP for 'daytime' since we are presuming that is what - * people are more interested in seeing. While EC provides a separate POP for daytime and nighttime portions - * of each day, the weather module does not really allow for that view of a daily forecast. There we will - * ignore any nighttime portion. There is an exception however! For the Current day, the EC data will only show - * the nighttime forecast after a certain point in the afternoon. As such, we will be showing the nighttime POP - * (if one exists) in that specific scenario. - * - * Accumulation Logic: Similar to POP, we want to show accumulation for 'daytime' since we presume that is what - * people are interested in seeing. While EC provides a separate accumulation for daytime and nighttime portions - * of each day, the weather module does not really allow for that view of a daily forecast. There we will - * ignore any nighttime portion. There is an exception however! For the Current day, the EC data will only show - * the nighttime forecast after a certain point in that specific scenario. - */ - setPrecipitation (weather, foreGroup, today) { - if (foreGroup[today].querySelector("precipitation accumulation")) { - weather.precipitationAmount = foreGroup[today].querySelector("precipitation accumulation amount").textContent * 1.0; - weather.precipitationUnits = foreGroup[today].querySelector("precipitation accumulation amount").getAttribute("units"); - } + // Create UTC date since input timestamps are in UTC + return new Date(Date.UTC(y, m, d, h, min, s)); + } - // Check Today element for POP - const precipPOP = foreGroup[today].querySelector("abbreviatedForecast pop").textContent * 1.0; - if (precipPOP > 0) { - weather.precipitationProbability = precipPOP; - } - }, - - /* - * Convert the icons to a more usable name. - */ - convertWeatherType (weatherType) { - const weatherTypes = { - "00": "day-sunny", - "01": "day-sunny", - "02": "day-sunny-overcast", - "03": "day-cloudy", - "04": "day-cloudy", - "05": "day-cloudy", - "06": "day-sprinkle", - "07": "day-showers", - "08": "day-snow", - "09": "day-thunderstorm", + #convertWeatherType (iconCode) { + const code = parseInt(iconCode, 10); + const map = { + 0: "day-sunny", + 1: "day-sunny", + 2: "day-sunny-overcast", + 3: "day-cloudy", + 4: "day-cloudy", + 5: "day-cloudy", + 6: "day-sprinkle", + 7: "day-showers", + 8: "snow", + 9: "day-thunderstorm", 10: "cloud", 11: "showers", 12: "rain", @@ -614,7 +443,8 @@ WeatherProvider.register("envcanada", { 47: "thunderstorm", 48: "tornado" }; - - return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; + return map[code] || null; } -}); +} + +module.exports = EnvCanadaProvider; diff --git a/defaultmodules/weather/providers/openmeteo.js b/defaultmodules/weather/providers/openmeteo.js index c9aaaf567d..c6cff32a24 100644 --- a/defaultmodules/weather/providers/openmeteo.js +++ b/defaultmodules/weather/providers/openmeteo.js @@ -1,231 +1,258 @@ -/* global WeatherProvider, WeatherObject */ - -/* - * This class is a provider for Open-Meteo, - * see https://open-meteo.com/ - */ +const Log = require("logger"); +const { getDateString } = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); // https://www.bigdatacloud.com/docs/api/free-reverse-geocode-to-city-api const GEOCODE_BASE = "https://api.bigdatacloud.net/data/reverse-geocode-client"; const OPEN_METEO_BASE = "https://api.open-meteo.com/v1"; -WeatherProvider.register("openmeteo", { - - /* - * Set the name of the provider. - * Not strictly required but helps for debugging. - */ - providerName: "Open-Meteo", - - // Set the default config properties that is specific to this provider - defaults: { - apiBase: OPEN_METEO_BASE, - lat: 0, - lon: 0, - pastDays: 0, - type: "current" - }, - +/** + * Server-side weather provider for Open-Meteo + * see https://open-meteo.com/ + */ +class OpenMeteoProvider { // https://open-meteo.com/en/docs - hourlyParams: [ - // Air temperature at 2 meters above ground + hourlyParams = [ "temperature_2m", - // Relative humidity at 2 meters above ground "relativehumidity_2m", - // Dew point temperature at 2 meters above ground "dewpoint_2m", - // Apparent temperature is the perceived feels-like temperature combining wind chill factor, relative humidity and solar radiation "apparent_temperature", - // Atmospheric air pressure reduced to mean sea level (msl) or pressure at surface. Typically pressure on mean sea level is used in meteorology. Surface pressure gets lower with increasing elevation. "pressure_msl", "surface_pressure", - // Total cloud cover as an area fraction "cloudcover", - // Low level clouds and fog up to 3 km altitude "cloudcover_low", - // Mid level clouds from 3 to 8 km altitude "cloudcover_mid", - // High level clouds from 8 km altitude "cloudcover_high", - // Wind speed at 10, 80, 120 or 180 meters above ground. Wind speed on 10 meters is the standard level. "windspeed_10m", "windspeed_80m", "windspeed_120m", "windspeed_180m", - // Wind direction at 10, 80, 120 or 180 meters above ground "winddirection_10m", "winddirection_80m", "winddirection_120m", "winddirection_180m", - // Gusts at 10 meters above ground as a maximum of the preceding hour "windgusts_10m", - // Shortwave solar radiation as average of the preceding hour. This is equal to the total global horizontal irradiation "shortwave_radiation", - // Direct solar radiation as average of the preceding hour on the horizontal plane and the normal plane (perpendicular to the sun) "direct_radiation", "direct_normal_irradiance", - // Diffuse solar radiation as average of the preceding hour "diffuse_radiation", - // Vapor Pressure Deificit (VPD) in kilopascal (kPa). For high VPD (>1.6), water transpiration of plants increases. For low VPD (<0.4), transpiration decreases "vapor_pressure_deficit", - // Evapotranspration from land surface and plants that weather models assumes for this location. Available soil water is considered. 1 mm evapotranspiration per hour equals 1 liter of water per spare meter. + "cape", "evapotranspiration", - // ET₀ Reference Evapotranspiration of a well watered grass field. Based on FAO-56 Penman-Monteith equations ET₀ is calculated from temperature, wind speed, humidity and solar radiation. Unlimited soil water is assumed. ET₀ is commonly used to estimate the required irrigation for plants. "et0_fao_evapotranspiration", - // Total precipitation (rain, showers, snow) sum of the preceding hour "precipitation", - // Precipitation Probability - "precipitation_probability", - // UV index - "uv_index", - // Snowfall amount of the preceding hour in centimeters. For the water equivalent in millimeter, divide by 7. E.g. 7 cm snow = 10 mm precipitation water equivalent "snowfall", - // Rain from large scale weather systems of the preceding hour in millimeter + "precipitation_probability", "rain", - // Showers from convective precipitation in millimeters from the preceding hour "showers", - // Weather condition as a numeric code. Follow WMO weather interpretation codes. "weathercode", - // Snow depth on the ground "snow_depth", - // Altitude above sea level of the 0°C level "freezinglevel_height", - // Temperature in the soil at 0, 6, 18 and 54 cm depths. 0 cm is the surface temperature on land or water surface temperature on water. + "visibility", "soil_temperature_0cm", "soil_temperature_6cm", "soil_temperature_18cm", "soil_temperature_54cm", - // Average soil water content as volumetric mixing ratio at 0-1, 1-3, 3-9, 9-27 and 27-81 cm depths. "soil_moisture_0_1cm", "soil_moisture_1_3cm", "soil_moisture_3_9cm", "soil_moisture_9_27cm", - "soil_moisture_27_81cm" - ], - - dailyParams: [ - // Maximum and minimum daily air temperature at 2 meters above ground + "soil_moisture_27_81cm", + "uv_index", + "uv_index_clear_sky", + "is_day", + "terrestrial_radiation", + "terrestrial_radiation_instant", + "shortwave_radiation_instant", + "diffuse_radiation_instant", + "direct_radiation_instant", + "direct_normal_irradiance_instant" + ]; + + dailyParams = [ "temperature_2m_max", "temperature_2m_min", - // Maximum and minimum daily apparent temperature "apparent_temperature_min", "apparent_temperature_max", - // Sum of daily precipitation (including rain, showers and snowfall) "precipitation_sum", - // Sum of daily rain "rain_sum", - // Sum of daily showers "showers_sum", - // Sum of daily snowfall "snowfall_sum", - // The number of hours with rain "precipitation_hours", - // The most severe weather condition on a given day "weathercode", - // Sun rise and set times "sunrise", "sunset", - // Maximum wind speed and gusts on a day "windspeed_10m_max", "windgusts_10m_max", - // Dominant wind direction "winddirection_10m_dominant", - // The sum of solar radiation on a given day in Megajoules "shortwave_radiation_sum", - //UV Index "uv_index_max", - // Daily sum of ET₀ Reference Evapotranspiration of a well watered grass field "et0_fao_evapotranspiration" - ], - - fetchedLocation () { - return this.fetchedLocationName || ""; - }, - - fetchCurrentWeather () { - this.fetchData(this.getUrl()) - .then((data) => this.parseWeatherApiResponse(data)) - .then((parsedData) => { - if (!parsedData) { - // No usable data? - return; - } + ]; - const currentWeather = this.generateWeatherDayFromCurrentWeather(parsedData); - this.setCurrentWeather(currentWeather); - }) - .catch(function (request) { - Log.error("[weatherprovider.openmeteo] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - fetchWeatherForecast () { - this.fetchData(this.getUrl()) - .then((data) => this.parseWeatherApiResponse(data)) - .then((parsedData) => { - if (!parsedData) { - // No usable data? - return; - } + constructor (config) { + this.config = { + apiBase: OPEN_METEO_BASE, + lat: 0, + lon: 0, + pastDays: 0, + type: "current", + maxNumberOfDays: 5, + maxEntries: 5, + updateInterval: 10 * 60 * 1000, + ...config + }; - const dailyForecast = this.generateWeatherObjectsFromForecast(parsedData); - this.setWeatherForecast(dailyForecast); - }) - .catch(function (request) { - Log.error("[weatherprovider.openmeteo] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - fetchWeatherHourly () { - this.fetchData(this.getUrl()) - .then((data) => this.parseWeatherApiResponse(data)) - .then((parsedData) => { - if (!parsedData) { - // No usable data? - return; - } + this.locationName = null; + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + } - const hourlyForecast = this.generateWeatherObjectsFromHourly(parsedData); - this.setWeatherHourly(hourlyForecast); - }) - .catch(function (request) { - Log.error("[weatherprovider.openmeteo] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, + async initialize () { + await this.#fetchLocation(); + this.#initializeFetcher(); + } /** - * Overrides method for setting config to check if endpoint is correct for hourly - * @param {object} config The configuration object + * Set callbacks for data/error events + * @param {(data: object) => void} onData - Called with weather data + * @param {(error: object) => void} onError - Called with error info */ - setConfig (config) { - this.config = { - lang: config.lang ?? "en", - ...this.defaults, - ...config - }; + setCallbacks (onData, onError) { + this.onDataCallback = onData; + this.onErrorCallback = onError; + } - // Set properly maxNumberOfDays and max Entries properties according to config and value ranges allowed in the documentation - const maxEntriesLimit = ["daily", "forecast"].includes(this.config.type) ? 7 : this.config.type === "hourly" ? 48 : 0; - if (this.config.hasOwnProperty("maxNumberOfDays") && !isNaN(parseFloat(this.config.maxNumberOfDays))) { - const daysFactor = ["daily", "forecast"].includes(this.config.type) ? 1 : this.config.type === "hourly" ? 24 : 0; - this.config.maxEntries = Math.max(1, Math.min(Math.round(parseFloat(this.config.maxNumberOfDays)) * daysFactor, maxEntriesLimit)); - this.config.maxNumberOfDays = Math.ceil(this.config.maxEntries / Math.max(1, daysFactor)); + /** + * Start periodic fetching + */ + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); } - this.config.maxEntries = Math.max(1, Math.min(this.config.maxEntries, maxEntriesLimit)); + } - if (!this.config.type) { - Log.error("[weatherprovider.openmeteo] type not configured and could not resolve it"); + /** + * Stop periodic fetching + */ + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } + } + + async #fetchLocation () { + const url = `${GEOCODE_BASE}?latitude=${this.config.lat}&longitude=${this.config.lon}&localityLanguage=${this.config.lang || "en"}`; + + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); + + const response = await fetch(url, { signal: controller.signal }); + clearTimeout(timeoutId); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}`); + } + const data = await response.json(); + if (data && data.city) { + this.locationName = `${data.city}, ${data.principalSubdivisionCode}`; + } + } catch (error) { + Log.debug("[openmeteo] Could not load location data:", error.message); + } + } + + #initializeFetcher () { + const url = this.#getUrl(); + + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + headers: { "Cache-Control": "no-cache" }, + logContext: "weatherprovider.openmeteo" + }); + + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + this.#handleResponse(data); + } catch (error) { + Log.error("[openmeteo] Failed to parse JSON:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + } + }); + + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } + + #handleResponse (data) { + const parsedData = this.#parseWeatherApiResponse(data); + + if (!parsedData) { + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Invalid API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; + } + + try { + let weatherData; + switch (this.config.type) { + case "current": + weatherData = this.#generateWeatherDayFromCurrentWeather(parsedData); + break; + case "forecast": + case "daily": + weatherData = this.#generateWeatherObjectsFromForecast(parsedData); + break; + case "hourly": + weatherData = this.#generateWeatherObjectsFromHourly(parsedData); + break; + default: + Log.error(`[openmeteo] Unknown type: ${this.config.type}`); + throw new Error(`Unknown weather type: ${this.config.type}`); + } + + if (weatherData && this.onDataCallback) { + this.onDataCallback(weatherData); + } + } catch (error) { + Log.error("[openmeteo] Error processing weather data:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: error.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } } + } - this.fetchLocation(); - }, + #getQueryParameters () { + const maxEntriesLimit = ["daily", "forecast"].includes(this.config.type) ? 7 : this.config.type === "hourly" ? 48 : 0; + let maxEntries = this.config.maxEntries; + let maxNumberOfDays = this.config.maxNumberOfDays; - // Generate valid query params to perform the request - getQueryParameters () { - let params = { + if (this.config.maxNumberOfDays !== undefined && !isNaN(parseFloat(this.config.maxNumberOfDays))) { + const daysFactor = ["daily", "forecast"].includes(this.config.type) ? 1 : this.config.type === "hourly" ? 24 : 0; + maxEntries = Math.max(1, Math.min(Math.round(parseFloat(this.config.maxNumberOfDays)) * daysFactor, maxEntriesLimit)); + maxNumberOfDays = Math.ceil(maxEntries / Math.max(1, daysFactor)); + } + maxEntries = Math.max(1, Math.min(maxEntries, maxEntriesLimit)); + + const params = { latitude: this.config.lat, longitude: this.config.lon, timeformat: "unixtime", @@ -233,36 +260,34 @@ WeatherProvider.register("openmeteo", { past_days: this.config.pastDays ?? 0, daily: this.dailyParams, hourly: this.hourlyParams, - // Fixed units as metric temperature_unit: "celsius", windspeed_unit: "ms", precipitation_unit: "mm" }; - const startDate = moment().startOf("day"); - const endDate = moment(startDate) - .add(Math.max(0, Math.min(7, this.config.maxNumberOfDays)), "days") - .endOf("day"); + const now = new Date(); + const startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + const endDate = new Date(startDate); + endDate.setDate(endDate.getDate() + Math.max(0, Math.min(7, maxNumberOfDays))); - params.start_date = startDate.format("YYYY-MM-DD"); + params.start_date = startDate.toISOString().split("T")[0]; switch (this.config.type) { case "hourly": case "daily": case "forecast": - params.end_date = endDate.format("YYYY-MM-DD"); + params.end_date = endDate.toISOString().split("T")[0]; break; case "current": params.current_weather = true; params.end_date = params.start_date; break; default: - // Failsafe return ""; } return Object.keys(params) - .filter((key) => (!!params[key])) + .filter((key) => params[key] !== undefined && params[key] !== null && params[key] !== "") .map((key) => { switch (key) { case "hourly": @@ -273,200 +298,53 @@ WeatherProvider.register("openmeteo", { } }) .join("&"); - }, - - // Create a URL from the config and base URL. - getUrl () { - return `${this.config.apiBase}/forecast?${this.getQueryParameters()}`; - }, - - // fix daylight-saving-time differences - checkDST (dt) { - const uxdt = moment.unix(dt); - const nowDST = moment().isDST(); - if (nowDST === moment(uxdt).isDST()) { - return uxdt; - } else { - return uxdt.add(nowDST ? +1 : -1, "hour"); - } - }, + } + + #getUrl () { + return `${this.config.apiBase}/forecast?${this.#getQueryParameters()}`; + } - // Transpose hourly and daily data matrices - transposeDataMatrix (data) { + #transposeDataMatrix (data) { return data.time.map((_, index) => Object.keys(data).reduce((row, key) => { + const value = data[key][index]; return { ...row, - // Parse time values as moment.js instances - [key]: ["time", "sunrise", "sunset"].includes(key) ? this.checkDST(data[key][index]) : data[key][index] + // Convert Unix timestamps to Date objects + // timezone: "auto" returns times already in location timezone + [key]: ["time", "sunrise", "sunset"].includes(key) ? new Date(value * 1000) : value }; }, {})); - }, + } - // Sanitize and validate API response - parseWeatherApiResponse (data) { + #parseWeatherApiResponse (data) { const validByType = { current: data.current_weather && data.current_weather.time, hourly: data.hourly && data.hourly.time && Array.isArray(data.hourly.time) && data.hourly.time.length > 0, daily: data.daily && data.daily.time && Array.isArray(data.daily.time) && data.daily.time.length > 0 }; - // backwards compatibility + const type = ["daily", "forecast"].includes(this.config.type) ? "daily" : this.config.type; - if (!validByType[type]) return; + if (!validByType[type]) return null; - switch (type) { - case "current": - if (!validByType.daily && !validByType.hourly) { - return; - } - break; - case "hourly": - case "daily": - break; - default: - return; + if (type === "current" && !validByType.daily && !validByType.hourly) { + return null; } for (const key of ["hourly", "daily"]) { if (typeof data[key] === "object") { - data[key] = this.transposeDataMatrix(data[key]); + data[key] = this.#transposeDataMatrix(data[key]); } } if (data.current_weather) { - data.current_weather.time = moment.unix(data.current_weather.time); + data.current_weather.time = new Date(data.current_weather.time * 1000); } return data; - }, - - // Reverse geocoding from latitude and longitude provided - fetchLocation () { - this.fetchData(`${GEOCODE_BASE}?latitude=${this.config.lat}&longitude=${this.config.lon}&localityLanguage=${this.config.lang}`) - .then((data) => { - if (!data || !data.city) { - // No usable data? - return; - } - this.fetchedLocationName = `${data.city}, ${data.principalSubdivisionCode}`; - }) - .catch((request) => { - Log.error("[weatherprovider.openmeteo] Could not load data ... ", request); - }); - }, - - // Implement WeatherDay generator. - generateWeatherDayFromCurrentWeather (weather) { - - /** - * Since some units come from API response "splitted" into daily, hourly and current_weather - * every time you request it, you have to ensure to get the data from the right place every time. - * For the current weather case, the response have the following structure (after transposing): - * ``` - * { - * current_weather: { ... }, - * hourly: [ - * 0: {... }, - * 1: {... }, - * ... - * ], - * daily: [ - * {... }, - * ] - * } - * ``` - * Some data should be returned from `hourly` array data when the index matches the current hour, - * some data from the first and only one object received in `daily` array and some from the - * `current_weather` object. - */ - const h = moment().hour(); - const currentWeather = new WeatherObject(); - - currentWeather.date = weather.current_weather.time; - currentWeather.windSpeed = weather.current_weather.windspeed; - currentWeather.windFromDirection = weather.current_weather.winddirection; - currentWeather.sunrise = weather.daily[0].sunrise; - currentWeather.sunset = weather.daily[0].sunset; - currentWeather.temperature = parseFloat(weather.current_weather.temperature); - currentWeather.minTemperature = parseFloat(weather.daily[0].temperature_2m_min); - currentWeather.maxTemperature = parseFloat(weather.daily[0].temperature_2m_max); - currentWeather.weatherType = this.convertWeatherType(weather.current_weather.weathercode, currentWeather.isDayTime()); - currentWeather.humidity = parseFloat(weather.hourly[h].relativehumidity_2m); - currentWeather.feelsLikeTemp = parseFloat(weather.hourly[h].apparent_temperature); - currentWeather.rain = parseFloat(weather.hourly[h].rain); - currentWeather.snow = parseFloat(weather.hourly[h].snowfall * 10); - currentWeather.precipitationAmount = parseFloat(weather.hourly[h].precipitation); - currentWeather.precipitationProbability = parseFloat(weather.hourly[h].precipitation_probability); - currentWeather.uv_index = parseFloat(weather.hourly[h].uv_index); - - return currentWeather; - }, - - // Implement WeatherForecast generator. - generateWeatherObjectsFromForecast (weathers) { - const days = []; - - weathers.daily.forEach((weather) => { - const currentWeather = new WeatherObject(); - - currentWeather.date = weather.time; - currentWeather.windSpeed = weather.windspeed_10m_max; - currentWeather.windFromDirection = weather.winddirection_10m_dominant; - currentWeather.sunrise = weather.sunrise; - currentWeather.sunset = weather.sunset; - currentWeather.temperature = parseFloat((weather.temperature_2m_max + weather.temperature_2m_min) / 2); - currentWeather.minTemperature = parseFloat(weather.temperature_2m_min); - currentWeather.maxTemperature = parseFloat(weather.temperature_2m_max); - currentWeather.weatherType = this.convertWeatherType(weather.weathercode, true); - currentWeather.rain = parseFloat(weather.rain_sum); - currentWeather.snow = parseFloat(weather.snowfall_sum * 10); - currentWeather.precipitationAmount = parseFloat(weather.precipitation_sum); - currentWeather.precipitationProbability = parseFloat(weather.precipitation_hours * 100 / 24); - currentWeather.uv_index = parseFloat(weather.uv_index_max); - - days.push(currentWeather); - }); - - return days; - }, - - // Implement WeatherHourly generator. - generateWeatherObjectsFromHourly (weathers) { - const hours = []; - const now = moment(); - - weathers.hourly.forEach((weather, i) => { - if ((hours.length === 0 && weather.time <= now) || hours.length >= this.config.maxEntries) { - return; - } - - const currentWeather = new WeatherObject(); - const h = Math.ceil((i + 1) / 24) - 1; - - currentWeather.date = weather.time; - currentWeather.windSpeed = weather.windspeed_10m; - currentWeather.windFromDirection = weather.winddirection_10m; - currentWeather.sunrise = weathers.daily[h].sunrise; - currentWeather.sunset = weathers.daily[h].sunset; - currentWeather.temperature = parseFloat(weather.temperature_2m); - currentWeather.minTemperature = parseFloat(weathers.daily[h].temperature_2m_min); - currentWeather.maxTemperature = parseFloat(weathers.daily[h].temperature_2m_max); - currentWeather.weatherType = this.convertWeatherType(weather.weathercode, currentWeather.isDayTime()); - currentWeather.humidity = parseFloat(weather.relativehumidity_2m); - currentWeather.rain = parseFloat(weather.rain); - currentWeather.snow = parseFloat(weather.snowfall * 10); - currentWeather.precipitationAmount = parseFloat(weather.precipitation); - currentWeather.precipitationProbability = parseFloat(weather.precipitation_probability); - currentWeather.uv_index = parseFloat(weather.uv_index); - - hours.push(currentWeather); - }); - - return hours; - }, + } - // Map icons from Dark Sky to our icons. - convertWeatherType (weathercode, isDayTime) { + #convertWeatherType (weathercode, isDayTime) { const weatherConditions = { 0: "clear", 1: "mainly-clear", @@ -498,60 +376,188 @@ WeatherProvider.register("openmeteo", { 99: "thunderstorm-heavy-hail" }; - if (!Object.keys(weatherConditions).includes(`${weathercode}`)) return null; - - switch (weatherConditions[`${weathercode}`]) { - case "clear": - return isDayTime ? "day-sunny" : "night-clear"; - case "mainly-clear": - case "partly-cloudy": - return isDayTime ? "day-cloudy" : "night-alt-cloudy"; - case "overcast": - return isDayTime ? "day-sunny-overcast" : "night-alt-partly-cloudy"; - case "fog": - case "depositing-rime-fog": - return isDayTime ? "day-fog" : "night-fog"; - case "drizzle-light-intensity": - case "rain-slight-intensity": - case "rain-showers-slight": - return isDayTime ? "day-sprinkle" : "night-sprinkle"; - case "drizzle-moderate-intensity": - case "rain-moderate-intensity": - case "rain-showers-moderate": - return isDayTime ? "day-showers" : "night-showers"; - case "drizzle-dense-intensity": - case "rain-heavy-intensity": - case "rain-showers-violent": - return isDayTime ? "day-thunderstorm" : "night-thunderstorm"; - case "freezing-rain-light-intensity": - return isDayTime ? "day-rain-mix" : "night-rain-mix"; - case "freezing-drizzle-light-intensity": - case "freezing-drizzle-dense-intensity": - return "snowflake-cold"; - case "snow-grains": - return isDayTime ? "day-sleet" : "night-sleet"; - case "snow-fall-slight-intensity": - case "snow-fall-moderate-intensity": - return isDayTime ? "day-snow-wind" : "night-snow-wind"; - case "snow-fall-heavy-intensity": - case "freezing-rain-heavy-intensity": - return isDayTime ? "day-snow-thunderstorm" : "night-snow-thunderstorm"; - case "snow-showers-slight": - case "snow-showers-heavy": - return isDayTime ? "day-rain-mix" : "night-rain-mix"; - case "thunderstorm": - return isDayTime ? "day-thunderstorm" : "night-thunderstorm"; - case "thunderstorm-slight-hail": - return isDayTime ? "day-sleet" : "night-sleet"; - case "thunderstorm-heavy-hail": - return isDayTime ? "day-sleet-storm" : "night-sleet-storm"; - default: - return "na"; + if (!(weathercode in weatherConditions)) return null; + + const mappings = { + clear: isDayTime ? "day-sunny" : "night-clear", + "mainly-clear": isDayTime ? "day-cloudy" : "night-alt-cloudy", + "partly-cloudy": isDayTime ? "day-cloudy" : "night-alt-cloudy", + overcast: isDayTime ? "day-sunny-overcast" : "night-alt-partly-cloudy", + fog: isDayTime ? "day-fog" : "night-fog", + "depositing-rime-fog": isDayTime ? "day-fog" : "night-fog", + "drizzle-light-intensity": isDayTime ? "day-sprinkle" : "night-sprinkle", + "rain-slight-intensity": isDayTime ? "day-sprinkle" : "night-sprinkle", + "rain-showers-slight": isDayTime ? "day-sprinkle" : "night-sprinkle", + "drizzle-moderate-intensity": isDayTime ? "day-showers" : "night-showers", + "rain-moderate-intensity": isDayTime ? "day-showers" : "night-showers", + "rain-showers-moderate": isDayTime ? "day-showers" : "night-showers", + "drizzle-dense-intensity": isDayTime ? "day-thunderstorm" : "night-thunderstorm", + "rain-heavy-intensity": isDayTime ? "day-thunderstorm" : "night-thunderstorm", + "rain-showers-violent": isDayTime ? "day-thunderstorm" : "night-thunderstorm", + "freezing-rain-light-intensity": isDayTime ? "day-rain-mix" : "night-rain-mix", + "freezing-drizzle-light-intensity": "snowflake-cold", + "freezing-drizzle-dense-intensity": "snowflake-cold", + "snow-grains": isDayTime ? "day-sleet" : "night-sleet", + "snow-fall-slight-intensity": isDayTime ? "day-snow-wind" : "night-snow-wind", + "snow-fall-moderate-intensity": isDayTime ? "day-snow-wind" : "night-snow-wind", + "snow-fall-heavy-intensity": isDayTime ? "day-snow-thunderstorm" : "night-snow-thunderstorm", + "freezing-rain-heavy-intensity": isDayTime ? "day-snow-thunderstorm" : "night-snow-thunderstorm", + "snow-showers-slight": isDayTime ? "day-rain-mix" : "night-rain-mix", + "snow-showers-heavy": isDayTime ? "day-rain-mix" : "night-rain-mix", + thunderstorm: isDayTime ? "day-thunderstorm" : "night-thunderstorm", + "thunderstorm-slight-hail": isDayTime ? "day-sleet" : "night-sleet", + "thunderstorm-heavy-hail": isDayTime ? "day-sleet-storm" : "night-sleet-storm" + }; + + return mappings[weatherConditions[`${weathercode}`]] || "na"; + } + + #isDayTime (date, sunrise, sunset) { + const time = date.getTime(); + return time >= sunrise.getTime() && time < sunset.getTime(); + } + + #generateWeatherDayFromCurrentWeather (parsedData) { + // Basic current weather data + const current = { + date: parsedData.current_weather.time, + windSpeed: parsedData.current_weather.windspeed, + windFromDirection: parsedData.current_weather.winddirection, + temperature: parsedData.current_weather.temperature, + weatherType: this.#convertWeatherType(parsedData.current_weather.weathercode, true) + }; + + // Add hourly data if available + if (parsedData.hourly) { + let h = 0; + 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]; + } + } + + // Add daily data if available (after transpose, daily is array of objects) + if (parsedData.daily && Array.isArray(parsedData.daily) && parsedData.daily[0]) { + const today = parsedData.daily[0]; + if (today.sunrise) { + current.sunrise = today.sunrise; + } + if (today.sunset) { + current.sunset = today.sunset; + // Update weatherType with correct day/night status + if (current.sunrise && current.sunset) { + current.weatherType = this.#convertWeatherType( + parsedData.current_weather.weathercode, + this.#isDayTime(parsedData.current_weather.time, current.sunrise, current.sunset) + ); + } + } + if (today.temperature_2m_min !== undefined) { + current.minTemperature = today.temperature_2m_min; + } + if (today.temperature_2m_max !== undefined) { + current.maxTemperature = today.temperature_2m_max; + } } - }, - // Define required scripts. - getScripts () { - return ["moment.js"]; + return current; + } + + #generateWeatherObjectsFromForecast (parsedData) { + return parsedData.daily.map((weather) => ({ + date: weather.time, + windSpeed: weather.windspeed_10m_max, + windFromDirection: weather.winddirection_10m_dominant, + sunrise: weather.sunrise, + sunset: weather.sunset, + temperature: parseFloat((weather.temperature_2m_max + weather.temperature_2m_min) / 2), + minTemperature: parseFloat(weather.temperature_2m_min), + maxTemperature: parseFloat(weather.temperature_2m_max), + weatherType: this.#convertWeatherType(weather.weathercode, true), + rain: weather.rain_sum != null ? parseFloat(weather.rain_sum) : null, + snow: weather.snowfall_sum != null ? parseFloat(weather.snowfall_sum * 10) : null, + precipitationAmount: weather.precipitation_sum != null ? parseFloat(weather.precipitation_sum) : null, + precipitationProbability: weather.precipitation_hours != null ? parseFloat(weather.precipitation_hours * 100 / 24) : null, + uvIndex: weather.uv_index_max != null ? parseFloat(weather.uv_index_max) : null + })); + } + + #generateWeatherObjectsFromHourly (parsedData) { + const hours = []; + const now = new Date(); + + parsedData.hourly.forEach((weather, i) => { + // Skip past entries, collect only future hours up to maxEntries + if (weather.time <= now || hours.length >= this.config.maxEntries) { + return; + } + + // Calculate daily index with bounds check + const h = Math.ceil((i + 1) / 24) - 1; + const safeH = Math.max(0, Math.min(h, parsedData.daily.length - 1)); + const dailyData = parsedData.daily[safeH]; + + const hourlyWeather = { + date: weather.time, + windSpeed: weather.windspeed_10m, + windFromDirection: weather.winddirection_10m, + sunrise: dailyData.sunrise, + sunset: dailyData.sunset, + temperature: parseFloat(weather.temperature_2m), + minTemperature: parseFloat(dailyData.temperature_2m_min), + maxTemperature: parseFloat(dailyData.temperature_2m_max), + weatherType: this.#convertWeatherType( + weather.weathercode, + this.#isDayTime(weather.time, dailyData.sunrise, dailyData.sunset) + ), + humidity: weather.relativehumidity_2m != null ? parseFloat(weather.relativehumidity_2m) : null, + rain: weather.rain != null ? parseFloat(weather.rain) : null, + snow: weather.snowfall != null ? parseFloat(weather.snowfall * 10) : null, + precipitationAmount: weather.precipitation != null ? parseFloat(weather.precipitation) : null, + precipitationProbability: weather.precipitation_probability != null ? parseFloat(weather.precipitation_probability) : null, + uvIndex: weather.uv_index != null ? parseFloat(weather.uv_index) : null + }; + + hours.push(hourlyWeather); + }); + + return hours; } -}); +} + +module.exports = OpenMeteoProvider; diff --git a/defaultmodules/weather/providers/openweathermap.js b/defaultmodules/weather/providers/openweathermap.js index 5ad0fa1460..c75e1f927c 100644 --- a/defaultmodules/weather/providers/openweathermap.js +++ b/defaultmodules/weather/providers/openweathermap.js @@ -1,290 +1,157 @@ -/* global WeatherProvider, WeatherObject */ +const Log = require("logger"); +const weatherUtils = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); -/* - * This class is a provider for Openweathermap, +/** + * Server-side weather provider for OpenWeatherMap * see https://openweathermap.org/ */ -WeatherProvider.register("openweathermap", { - - /* - * Set the name of the provider. - * This isn't strictly necessary, since it will fallback to the provider identifier - * But for debugging (and future alerts) it would be nice to have the real name. - */ - providerName: "OpenWeatherMap", - - // Set the default config properties that is specific to this provider - defaults: { - apiVersion: "3.0", - apiBase: "https://api.openweathermap.org/data/", - // weatherEndpoint is "/onecall" since API 3.0 - // "/onecall", "/forecast" or "/weather" only for pro customers - weatherEndpoint: "/onecall", - locationID: false, - location: false, - // the /onecall endpoint needs lat / lon values, it doesn't support the locationId - lat: 0, - lon: 0, - apiKey: "" - }, - - // Overwrite the fetchCurrentWeather method. - fetchCurrentWeather () { - this.fetchData(this.getUrl()) - .then((data) => { - let currentWeather; - if (this.config.weatherEndpoint === "/onecall") { - currentWeather = this.generateWeatherObjectsFromOnecall(data).current; - this.setFetchedLocation(`${data.timezone}`); - } else { - currentWeather = this.generateWeatherObjectFromCurrentWeather(data); - } - this.setCurrentWeather(currentWeather); - }) - .catch(function (request) { - Log.error("[weatherprovider.openweathermap] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - // Overwrite the fetchWeatherForecast method. - fetchWeatherForecast () { - this.fetchData(this.getUrl()) - .then((data) => { - let forecast; - let location; - if (this.config.weatherEndpoint === "/onecall") { - forecast = this.generateWeatherObjectsFromOnecall(data).days; - location = `${data.timezone}`; - } else { - forecast = this.generateWeatherObjectsFromForecast(data.list); - location = `${data.city.name}, ${data.city.country}`; - } - this.setWeatherForecast(forecast); - this.setFetchedLocation(location); - }) - .catch(function (request) { - Log.error("[weatherprovider.openweathermap] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - // Overwrite the fetchWeatherHourly method. - fetchWeatherHourly () { - this.fetchData(this.getUrl()) - .then((data) => { - if (!data) { - - /* - * Did not receive usable new data. - * Maybe this needs a better check? - */ - return; - } +class OpenWeatherMapProvider { + constructor (config) { + this.config = { + apiVersion: "3.0", + apiBase: "https://api.openweathermap.org/data/", + weatherEndpoint: "/onecall", + locationID: false, + location: false, + lat: 0, + lon: 0, + apiKey: "", + type: "current", + updateInterval: 10 * 60 * 1000, + ...config + }; + + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + this.locationName = null; + } - this.setFetchedLocation(`(${data.lat},${data.lon})`); - - const weatherData = this.generateWeatherObjectsFromOnecall(data); - this.setWeatherHourly(weatherData.hours); - }) - .catch(function (request) { - Log.error("[weatherprovider.openweathermap] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - /** OpenWeatherMap Specific Methods - These are not part of the default provider methods */ - /* - * Gets the complete url for the request - */ - getUrl () { - return this.config.apiBase + this.config.apiVersion + this.config.weatherEndpoint + this.getParams(); - }, - - /* - * Generate a WeatherObject based on currentWeatherInformation - */ - generateWeatherObjectFromCurrentWeather (currentWeatherData) { - const currentWeather = new WeatherObject(); - - currentWeather.date = moment.unix(currentWeatherData.dt); - currentWeather.humidity = currentWeatherData.main.humidity; - currentWeather.temperature = currentWeatherData.main.temp; - currentWeather.feelsLikeTemp = currentWeatherData.main.feels_like; - currentWeather.windSpeed = currentWeatherData.wind.speed; - currentWeather.windFromDirection = currentWeatherData.wind.deg; - currentWeather.weatherType = this.convertWeatherType(currentWeatherData.weather[0].icon); - currentWeather.sunrise = moment.unix(currentWeatherData.sys.sunrise); - currentWeather.sunset = moment.unix(currentWeatherData.sys.sunset); - - return currentWeather; - }, - - /* - * Generate WeatherObjects based on forecast information - */ - generateWeatherObjectsFromForecast (forecasts) { - if (this.config.weatherEndpoint === "/forecast") { - return this.generateForecastHourly(forecasts); - } else if (this.config.weatherEndpoint === "/forecast/daily") { - return this.generateForecastDaily(forecasts); + async initialize () { + // Validate callbacks exist + if (typeof this.onErrorCallback !== "function") { + throw new Error("setCallbacks() must be called before initialize()"); } - // if weatherEndpoint does not match forecast or forecast/daily, what should be returned? - return [new WeatherObject()]; - }, - - /* - * Generate WeatherObjects based on One Call forecast information - */ - generateWeatherObjectsFromOnecall (data) { - if (this.config.weatherEndpoint === "/onecall") { - return this.fetchOnecall(data); + + if (!this.config.apiKey) { + Log.error("[openweathermap] API key is required"); + this.onErrorCallback({ + message: "API key is required", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + return; } - // if weatherEndpoint does not match onecall, what should be returned? - return { current: new WeatherObject(), hours: [], days: [] }; - }, - - /* - * Generate forecast information for 3-hourly forecast (available for free - * subscription). - */ - generateForecastHourly (forecasts) { - // initial variable declaration - const days = []; - // variables for temperature range and rain - let minTemp = []; - let maxTemp = []; - let rain = 0; - let snow = 0; - // variable for date - let date = ""; - let weather = new WeatherObject(); - - for (const forecast of forecasts) { - if (date !== moment.unix(forecast.dt).format("YYYY-MM-DD")) { - // calculate minimum/maximum temperature, specify rain amount - weather.minTemperature = Math.min.apply(null, minTemp); - weather.maxTemperature = Math.max.apply(null, maxTemp); - weather.rain = rain; - weather.snow = snow; - weather.precipitationAmount = (weather.rain ?? 0) + (weather.snow ?? 0); - // push weather information to days array - days.push(weather); - // create new weather-object - weather = new WeatherObject(); - minTemp = []; - maxTemp = []; - rain = 0; - snow = 0; + this.#initializeFetcher(); + } - // set new date - date = moment.unix(forecast.dt).format("YYYY-MM-DD"); + setCallbacks (onData, onError) { + this.onDataCallback = onData; + this.onErrorCallback = onError; + } - // specify date - weather.date = moment.unix(forecast.dt); + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); + } + } - // If the first value of today is later than 17:00, we have an icon at least! - weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); - } + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } + } - if (moment.unix(forecast.dt).format("H") >= 8 && moment.unix(forecast.dt).format("H") <= 17) { - weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); + #initializeFetcher () { + const url = this.#getUrl(); + + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + headers: { "Cache-Control": "no-cache" }, + logContext: "weatherprovider.openweathermap" + }); + + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + this.#handleResponse(data); + } catch (error) { + Log.error("[openweathermap] Failed to parse JSON:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } } + }); - /* - * the same day as before - * add values from forecast to corresponding variables - */ - minTemp.push(forecast.main.temp_min); - maxTemp.push(forecast.main.temp_max); - - if (forecast.hasOwnProperty("rain") && !isNaN(forecast.rain["3h"])) { - rain += forecast.rain["3h"]; + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); } + }); + } - if (forecast.hasOwnProperty("snow") && !isNaN(forecast.snow["3h"])) { - snow += forecast.snow["3h"]; + #handleResponse (data) { + try { + // Set location name from timezone + if (data.timezone) { + this.locationName = data.timezone; } - } - /* - * last day - * calculate minimum/maximum temperature, specify rain amount - */ - weather.minTemperature = Math.min.apply(null, minTemp); - weather.maxTemperature = Math.max.apply(null, maxTemp); - weather.rain = rain; - weather.snow = snow; - weather.precipitationAmount = (weather.rain ?? 0) + (weather.snow ?? 0); - // push weather information to days array - days.push(weather); - return days.slice(1); - }, - - /* - * Generate forecast information for daily forecast (available for paid - * subscription or old apiKey). - */ - generateForecastDaily (forecasts) { - // initial variable declaration - const days = []; - - for (const forecast of forecasts) { - const weather = new WeatherObject(); - - weather.date = moment.unix(forecast.dt); - weather.minTemperature = forecast.temp.min; - weather.maxTemperature = forecast.temp.max; - weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); - weather.rain = 0; - weather.snow = 0; - - /* - * forecast.rain not available if amount is zero - * The API always returns in millimeters - */ - if (forecast.hasOwnProperty("rain") && !isNaN(forecast.rain)) { - weather.rain = forecast.rain; + 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}`); } - /* - * forecast.snow not available if amount is zero - * The API always returns in millimeters - */ - if (forecast.hasOwnProperty("snow") && !isNaN(forecast.snow)) { - weather.snow = forecast.snow; + if (weatherData && this.onDataCallback) { + this.onDataCallback(weatherData); + } + } catch (error) { + Log.error("[openweathermap] Error processing weather data:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: error.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } - - weather.precipitationAmount = weather.rain + weather.snow; - weather.precipitationProbability = forecast.pop ? forecast.pop * 100 : undefined; - - days.push(weather); } + } - return days; - }, - - /* - * Fetch One Call forecast information (available for free subscription). - * Factors in timezone offsets. - * Minutely forecasts are excluded for the moment, see getParams(). - */ - fetchOnecall (data) { + #generateWeatherObjectsFromOnecall (data) { let precip = false; - // get current weather, if requested - const current = new WeatherObject(); + // Get current weather + const current = {}; if (data.hasOwnProperty("current")) { - current.date = moment.unix(data.current.dt).utcOffset(data.timezone_offset / 60); + const timezoneOffset = data.timezone_offset / 60; + current.date = weatherUtils.applyTimezoneOffset(new Date(data.current.dt * 1000), timezoneOffset); current.windSpeed = data.current.wind_speed; current.windFromDirection = data.current.wind_deg; - current.sunrise = moment.unix(data.current.sunrise).utcOffset(data.timezone_offset / 60); - current.sunset = moment.unix(data.current.sunset).utcOffset(data.timezone_offset / 60); + current.sunrise = weatherUtils.applyTimezoneOffset(new Date(data.current.sunrise * 1000), timezoneOffset); + current.sunset = weatherUtils.applyTimezoneOffset(new Date(data.current.sunset * 1000), timezoneOffset); current.temperature = data.current.temp; - current.weatherType = this.convertWeatherType(data.current.weather[0].icon); + current.weatherType = weatherUtils.convertWeatherType(data.current.weather[0].icon); current.humidity = data.current.humidity; - current.uv_index = data.current.uvi; + current.uvIndex = data.current.uvi; + + precip = false; if (data.current.hasOwnProperty("rain") && !isNaN(data.current.rain["1h"])) { current.rain = data.current.rain["1h"]; precip = true; @@ -299,21 +166,22 @@ WeatherProvider.register("openweathermap", { current.feelsLikeTemp = data.current.feels_like; } - let weather = new WeatherObject(); - - // get hourly weather, if requested + // Get hourly weather const hours = []; if (data.hasOwnProperty("hourly")) { + const timezoneOffset = data.timezone_offset / 60; for (const hour of data.hourly) { - weather.date = moment.unix(hour.dt).utcOffset(data.timezone_offset / 60); + const weather = {}; + weather.date = weatherUtils.applyTimezoneOffset(new Date(hour.dt * 1000), timezoneOffset); weather.temperature = hour.temp; weather.feelsLikeTemp = hour.feels_like; weather.humidity = hour.humidity; weather.windSpeed = hour.wind_speed; weather.windFromDirection = hour.wind_deg; - weather.weatherType = this.convertWeatherType(hour.weather[0].icon); - weather.precipitationProbability = hour.pop ? hour.pop * 100 : undefined; - weather.uv_index = hour.uvi; + weather.weatherType = weatherUtils.convertWeatherType(hour.weather[0].icon); + weather.precipitationProbability = hour.pop !== undefined ? hour.pop * 100 : undefined; + weather.uvIndex = hour.uvi; + precip = false; if (hour.hasOwnProperty("rain") && !isNaN(hour.rain["1h"])) { weather.rain = hour.rain["1h"]; @@ -328,25 +196,27 @@ WeatherProvider.register("openweathermap", { } hours.push(weather); - weather = new WeatherObject(); } } - // get daily weather, if requested + // Get daily weather const days = []; if (data.hasOwnProperty("daily")) { + const timezoneOffset = data.timezone_offset / 60; for (const day of data.daily) { - weather.date = moment.unix(day.dt).utcOffset(data.timezone_offset / 60); - weather.sunrise = moment.unix(day.sunrise).utcOffset(data.timezone_offset / 60); - weather.sunset = moment.unix(day.sunset).utcOffset(data.timezone_offset / 60); + const weather = {}; + weather.date = weatherUtils.applyTimezoneOffset(new Date(day.dt * 1000), timezoneOffset); + weather.sunrise = weatherUtils.applyTimezoneOffset(new Date(day.sunrise * 1000), timezoneOffset); + weather.sunset = weatherUtils.applyTimezoneOffset(new Date(day.sunset * 1000), timezoneOffset); weather.minTemperature = day.temp.min; weather.maxTemperature = day.temp.max; weather.humidity = day.humidity; weather.windSpeed = day.wind_speed; weather.windFromDirection = day.wind_deg; - weather.weatherType = this.convertWeatherType(day.weather[0].icon); - weather.precipitationProbability = day.pop ? day.pop * 100 : undefined; - weather.uv_index = day.uvi; + weather.weatherType = weatherUtils.convertWeatherType(day.weather[0].icon); + weather.precipitationProbability = day.pop !== undefined ? day.pop * 100 : undefined; + weather.uvIndex = day.uvi; + precip = false; if (!isNaN(day.rain)) { weather.rain = day.rain; @@ -361,52 +231,23 @@ WeatherProvider.register("openweathermap", { } days.push(weather); - weather = new WeatherObject(); } } - return { current: current, hours: hours, days: days }; - }, - - /* - * Convert the OpenWeatherMap icons to a more usable name. - */ - convertWeatherType (weatherType) { - const weatherTypes = { - "01d": "day-sunny", - "02d": "day-cloudy", - "03d": "cloudy", - "04d": "cloudy-windy", - "09d": "showers", - "10d": "rain", - "11d": "thunderstorm", - "13d": "snow", - "50d": "fog", - "01n": "night-clear", - "02n": "night-cloudy", - "03n": "night-cloudy", - "04n": "night-cloudy", - "09n": "night-showers", - "10n": "night-rain", - "11n": "night-thunderstorm", - "13n": "night-snow", - "50n": "night-alt-cloudy-windy" - }; + return { current, hours, days }; + } - return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; - }, + #getUrl () { + return this.config.apiBase + this.config.apiVersion + this.config.weatherEndpoint + this.#getParams(); + } - /* - * getParams(compliments) - * Generates an url with api parameters based on the config. - * - * return String - URL params. - */ - getParams () { + #getParams () { let params = "?"; + if (this.config.weatherEndpoint === "/onecall") { params += `lat=${this.config.lat}`; params += `&lon=${this.config.lon}`; + if (this.config.type === "current") { params += "&exclude=minutely,hourly,daily"; } else if (this.config.type === "hourly") { @@ -422,20 +263,14 @@ WeatherProvider.register("openweathermap", { params += `id=${this.config.locationID}`; } else if (this.config.location) { params += `q=${this.config.location}`; - } else if (this.firstEvent && this.firstEvent.geo) { - params += `lat=${this.firstEvent.geo.lat}&lon=${this.firstEvent.geo.lon}`; - } else if (this.firstEvent && this.firstEvent.location) { - params += `q=${this.firstEvent.location}`; - } else { - // TODO hide doesn't exist! - this.hide(this.config.animationSpeed, { lockString: this.identifier }); - return; } - params += "&units=metric"; // WeatherProviders should use metric internally and use the units only for when displaying data - params += `&lang=${this.config.lang}`; + params += "&units=metric"; + params += `&lang=${this.config.lang || "en"}`; params += `&APPID=${this.config.apiKey}`; return params; } -}); +} + +module.exports = OpenWeatherMapProvider; diff --git a/defaultmodules/weather/providers/overrideWrapper.js b/defaultmodules/weather/providers/overrideWrapper.js deleted file mode 100644 index 61afa10176..0000000000 --- a/defaultmodules/weather/providers/overrideWrapper.js +++ /dev/null @@ -1,112 +0,0 @@ -/* global Class, WeatherObject */ - -/* - * Wrapper class to enable overrides of currentOverrideWeatherObject. - * - * Sits between the weather.js module and the provider implementations to allow us to - * combine the incoming data from the CURRENT_WEATHER_OVERRIDE notification with the - * existing data received from the current api provider. If no notifications have - * been received then the api provider's data is used. - * - * The intent is to allow partial WeatherObjects from local sensors to augment or - * replace the WeatherObjects from the api providers. - * - * This class shares the signature of WeatherProvider, and passes any methods not - * concerning the current weather directly to the api provider implementation that - * is currently in use. - */ -const OverrideWrapper = Class.extend({ - baseProvider: null, - providerName: "localWrapper", - notificationWeatherObject: null, - currentOverrideWeatherObject: null, - - init (baseProvider) { - this.baseProvider = baseProvider; - - // Binding the scope of current weather functions so any fetchData calls with - // setCurrentWeather nested in them call this classes implementation instead - // of the provider's default - this.baseProvider.setCurrentWeather = this.setCurrentWeather.bind(this); - this.baseProvider.currentWeather = this.currentWeather.bind(this); - }, - - /* Unchanged Api Provider Methods */ - - setConfig (config) { - this.baseProvider.setConfig(config); - }, - start () { - this.baseProvider.start(); - }, - fetchCurrentWeather () { - this.baseProvider.fetchCurrentWeather(); - }, - fetchWeatherForecast () { - this.baseProvider.fetchWeatherForecast(); - }, - fetchWeatherHourly () { - this.baseProvider.fetchWeatherHourly(); - }, - weatherForecast () { - this.baseProvider.weatherForecast(); - }, - weatherHourly () { - this.baseProvider.weatherHourly(); - }, - fetchedLocation () { - this.baseProvider.fetchedLocation(); - }, - setWeatherForecast (weatherForecastArray) { - this.baseProvider.setWeatherForecast(weatherForecastArray); - }, - setWeatherHourly (weatherHourlyArray) { - this.baseProvider.setWeatherHourly(weatherHourlyArray); - }, - setFetchedLocation (name) { - this.baseProvider.setFetchedLocation(name); - }, - updateAvailable () { - this.baseProvider.updateAvailable(); - }, - async fetchData (url, type = "json", requestHeaders = undefined, expectedResponseHeaders = undefined) { - this.baseProvider.fetchData(url, type, requestHeaders, expectedResponseHeaders); - }, - - /* Override Methods */ - - /** - * Override to return this scope's - * @returns {WeatherObject} The current weather object. May or may not contain overridden data. - */ - currentWeather () { - return this.currentOverrideWeatherObject; - }, - - /** - * Override to combine the overrideWeatherObject provided in the - * notificationReceived method with the currentOverrideWeatherObject provided by the - * api provider fetchData implementation. - * @param {WeatherObject} currentWeatherObject - the api provider weather object - */ - setCurrentWeather (currentWeatherObject) { - this.currentOverrideWeatherObject = Object.assign(currentWeatherObject, this.notificationWeatherObject); - }, - - /** - * Updates the overrideWeatherObject, calls setCurrentWeather to combine it with - * the existing current weather object provided by the base provider, and signals - * that an update is ready. - * @param {WeatherObject} payload - the weather object received from the CURRENT_WEATHER_OVERRIDE - * notification. Represents information to augment the - * existing currentOverrideWeatherObject with. - */ - notificationReceived (payload) { - this.notificationWeatherObject = payload; - - // setCurrentWeather combines the newly received notification weather with - // the existing weather object we return for current weather - this.setCurrentWeather(this.currentOverrideWeatherObject); - this.updateAvailable(); - } -}); diff --git a/defaultmodules/weather/providers/pirateweather.js b/defaultmodules/weather/providers/pirateweather.js index 73760578f2..fbf14403b5 100644 --- a/defaultmodules/weather/providers/pirateweather.js +++ b/defaultmodules/weather/providers/pirateweather.js @@ -1,115 +1,243 @@ -/* global WeatherProvider, WeatherObject */ - -/* - * This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api), - * see http://pirateweather.net/en/latest/ - */ -WeatherProvider.register("pirateweather", { - - /* - * Set the name of the provider. - * Not strictly required, but helps for debugging. - */ - providerName: "pirateweather", - - // Set the default config properties that is specific to this provider - defaults: { - useCorsProxy: true, - apiBase: "https://api.pirateweather.net", - weatherEndpoint: "/forecast", - apiKey: "", - lat: 0, - lon: 0 - }, - - async fetchCurrentWeather () { - try { - const data = await this.fetchData(this.getUrl()); - if (!data || !data.currently || typeof data.currently.temperature === "undefined") { - throw new Error("No usable data received from Pirate Weather API."); +const Log = require("logger"); +const HTTPFetcher = require("#http_fetcher"); + +class PirateweatherProvider { + constructor (config) { + this.config = { + apiBase: "https://api.pirateweather.net", + weatherEndpoint: "/forecast", + apiKey: "", + lat: 0, + lon: 0, + type: "current", + updateInterval: 10 * 60 * 1000, + lang: "en", + ...config + }; + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + } + + setCallbacks (onDataCallback, onErrorCallback) { + this.onDataCallback = onDataCallback; + this.onErrorCallback = onErrorCallback; + } + + async initialize () { + if (!this.config.apiKey) { + Log.error("[pirateweather] No API key configured"); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "API key required", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } + return; + } + + this.#initializeFetcher(); + } + + #initializeFetcher () { + const url = this.#getUrl(); + + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + headers: { + "Cache-Control": "no-cache", + Accept: "application/json" + }, + logContext: "weatherprovider.pirateweather" + }); + + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + this.#handleResponse(data); + } catch (error) { + Log.error("[pirateweather] Parse error:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + } + }); + + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } - const currentWeather = this.generateWeatherDayFromCurrentWeather(data); - this.setCurrentWeather(currentWeather); - } catch (error) { - Log.error("Could not load data ... ", error); - } finally { - this.updateAvailable(); + #handleResponse (data) { + if (!data || (!data.currently && !data.daily && !data.hourly)) { + Log.error("[pirateweather] No usable data received"); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "No usable data in API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; + } + + let weatherData = null; + + switch (this.config.type) { + case "current": + weatherData = this.#generateCurrent(data); + break; + case "forecast": + case "daily": + weatherData = this.#generateDaily(data); + break; + case "hourly": + weatherData = this.#generateHourly(data); + break; + default: + Log.error(`[pirateweather] Unknown weather type: ${this.config.type}`); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: `Unknown weather type: ${this.config.type}`, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; + + } + + if (weatherData && this.onDataCallback) { + this.onDataCallback(weatherData); } - }, + } + + #generateCurrent (data) { + if (!data.currently || typeof data.currently.temperature === "undefined") { + return null; + } + + const current = { + date: new Date(), + humidity: data.currently.humidity != null ? parseFloat(data.currently.humidity) * 100 : null, + temperature: parseFloat(data.currently.temperature), + feelsLikeTemp: data.currently.apparentTemperature != null ? parseFloat(data.currently.apparentTemperature) : null, + windSpeed: data.currently.windSpeed != null ? parseFloat(data.currently.windSpeed) : null, + windFromDirection: data.currently.windBearing || null, + weatherType: this.#convertWeatherType(data.currently.icon), + sunrise: null, + sunset: null + }; - async fetchWeatherForecast () { - try { - const data = await this.fetchData(this.getUrl()); - if (!data || !data.daily || !data.daily.data.length) { - throw new Error("No usable data received from Pirate Weather API."); + // Add sunrise/sunset from daily data if available + if (data.daily && data.daily.data && data.daily.data.length > 0) { + const today = data.daily.data[0]; + if (today.sunriseTime) { + current.sunrise = new Date(today.sunriseTime * 1000); + } + if (today.sunsetTime) { + current.sunset = new Date(today.sunsetTime * 1000); } + } - const forecast = this.generateWeatherObjectsFromForecast(data.daily.data); - this.setWeatherForecast(forecast); - } catch (error) { - Log.error("Could not load data ... ", error); - } finally { - this.updateAvailable(); + return current; + } + + #generateDaily (data) { + if (!data.daily || !data.daily.data || !data.daily.data.length) { + return []; } - }, - - // Create a URL from the config and base URL. - getUrl () { - return `${this.config.apiBase}${this.config.weatherEndpoint}/${this.config.apiKey}/${this.config.lat},${this.config.lon}?units=si&lang=${this.config.lang}`; - }, - - // Implement WeatherDay generator. - generateWeatherDayFromCurrentWeather (currentWeatherData) { - const currentWeather = new WeatherObject(); - - currentWeather.date = moment(); - currentWeather.humidity = parseFloat(currentWeatherData.currently.humidity); - currentWeather.temperature = parseFloat(currentWeatherData.currently.temperature); - currentWeather.windSpeed = parseFloat(currentWeatherData.currently.windSpeed); - currentWeather.windFromDirection = currentWeatherData.currently.windBearing; - currentWeather.weatherType = this.convertWeatherType(currentWeatherData.currently.icon); - currentWeather.sunrise = moment.unix(currentWeatherData.daily.data[0].sunriseTime); - currentWeather.sunset = moment.unix(currentWeatherData.daily.data[0].sunsetTime); - - return currentWeather; - }, - - generateWeatherObjectsFromForecast (forecasts) { - const days = []; - for (const forecast of forecasts) { - const weather = new WeatherObject(); + const days = []; - weather.date = moment.unix(forecast.time); - weather.minTemperature = forecast.temperatureMin; - weather.maxTemperature = forecast.temperatureMax; - weather.weatherType = this.convertWeatherType(forecast.icon); - weather.snow = 0; - weather.rain = 0; + for (const forecast of data.daily.data) { + const day = { + date: new Date(forecast.time * 1000), + minTemperature: forecast.temperatureMin != null ? parseFloat(forecast.temperatureMin) : null, + maxTemperature: forecast.temperatureMax != null ? parseFloat(forecast.temperatureMax) : null, + weatherType: this.#convertWeatherType(forecast.icon), + snow: 0, + rain: 0, + precipitationAmount: 0, + precipitationProbability: forecast.precipProbability != null ? parseFloat(forecast.precipProbability) * 100 : null + }; + // Handle precipitation let precip = 0; if (forecast.hasOwnProperty("precipAccumulation")) { - precip = forecast.precipAccumulation * 10; + precip = forecast.precipAccumulation * 10; // cm to mm } - weather.precipitationAmount = precip; - if (forecast.hasOwnProperty("precipType")) { + day.precipitationAmount = precip; + + if (forecast.precipType) { if (forecast.precipType === "snow") { - weather.snow = precip; + day.snow = precip; } else { - weather.rain = precip; + day.rain = precip; } } - days.push(weather); + days.push(day); } return days; - }, + } + + #generateHourly (data) { + if (!data.hourly || !data.hourly.data || !data.hourly.data.length) { + return []; + } + + const hours = []; + + for (const forecast of data.hourly.data) { + const hour = { + date: new Date(forecast.time * 1000), + temperature: forecast.temperature !== undefined ? parseFloat(forecast.temperature) : null, + feelsLikeTemp: forecast.apparentTemperature !== undefined ? parseFloat(forecast.apparentTemperature) : null, + weatherType: this.#convertWeatherType(forecast.icon), + windSpeed: forecast.windSpeed !== undefined ? parseFloat(forecast.windSpeed) : null, + windFromDirection: forecast.windBearing || null, + precipitationProbability: forecast.precipProbability ? parseFloat(forecast.precipProbability) * 100 : null, + snow: 0, + rain: 0, + precipitationAmount: 0 + }; + + // Handle precipitation + let precip = 0; + if (forecast.hasOwnProperty("precipAccumulation")) { + precip = forecast.precipAccumulation * 10; // cm to mm + } + + hour.precipitationAmount = precip; + + if (forecast.precipType) { + if (forecast.precipType === "snow") { + hour.snow = precip; + } else { + hour.rain = precip; + } + } + + hours.push(hour); + } + + return hours; + } + + #getUrl () { + const apiBase = this.config.apiBase || "https://api.pirateweather.net"; + const weatherEndpoint = this.config.weatherEndpoint || "/forecast"; + const lang = this.config.lang || "en"; + return `${apiBase}${weatherEndpoint}/${this.config.apiKey}/${this.config.lat},${this.config.lon}?units=si&lang=${lang}`; + } - // Map icons from Pirate Weather to our icons. - convertWeatherType (weatherType) { + #convertWeatherType (weatherType) { const weatherTypes = { "clear-day": "day-sunny", "clear-night": "night-clear", @@ -123,6 +251,20 @@ WeatherProvider.register("pirateweather", { "partly-cloudy-night": "night-cloudy" }; - return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; + return weatherTypes[weatherType] || null; + } + + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); + } + } + + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } } -}); +} + +module.exports = PirateweatherProvider; diff --git a/defaultmodules/weather/providers/smhi.js b/defaultmodules/weather/providers/smhi.js index bcb873a9af..26deb54ede 100644 --- a/defaultmodules/weather/providers/smhi.js +++ b/defaultmodules/weather/providers/smhi.js @@ -1,213 +1,267 @@ -/* global WeatherProvider, WeatherObject */ +const Log = require("logger"); +const { getSunTimes, isDayTime, validateCoordinates } = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); -/* - * This class is a provider for SMHI (Sweden only). - * Metric system is the only supported unit, - * see https://www.smhi.se/ +/** + * Server-side weather provider for SMHI (Swedish Meteorological and Hydrological Institute) + * Sweden only, metric system + * API: https://opendata.smhi.se/apidocs/metfcst/ */ -WeatherProvider.register("smhi", { - providerName: "SMHI", - - // Set the default config properties that is specific to this provider - defaults: { - lat: 0, // Cant have more than 6 digits - lon: 0, // Cant have more than 6 digits - precipitationValue: "pmedian", - location: false - }, - - /** - * Implements method in interface for fetching current weather. - */ - fetchCurrentWeather () { - this.fetchData(this.getURL()) - .then((data) => { - const closest = this.getClosestToCurrentTime(data.timeSeries); - const coordinates = this.resolveCoordinates(data); - const weatherObject = this.convertWeatherDataToObject(closest, coordinates); - this.setFetchedLocation(this.config.location || `(${coordinates.lat},${coordinates.lon})`); - this.setCurrentWeather(weatherObject); - }) - .catch((error) => Log.error(`[weatherprovider.smhi] Could not load data: ${error.message}`)) - .finally(() => this.updateAvailable()); - }, - - /** - * Implements method in interface for fetching a multi-day forecast. - */ - fetchWeatherForecast () { - this.fetchData(this.getURL()) - .then((data) => { - const coordinates = this.resolveCoordinates(data); - const weatherObjects = this.convertWeatherDataGroupedBy(data.timeSeries, coordinates); - this.setFetchedLocation(this.config.location || `(${coordinates.lat},${coordinates.lon})`); - this.setWeatherForecast(weatherObjects); - }) - .catch((error) => Log.error(`[weatherprovider.smhi] Could not load data: ${error.message}`)) - .finally(() => this.updateAvailable()); - }, - - /** - * Implements method in interface for fetching hourly forecasts. - */ - fetchWeatherHourly () { - this.fetchData(this.getURL()) - .then((data) => { - const coordinates = this.resolveCoordinates(data); - const weatherObjects = this.convertWeatherDataGroupedBy(data.timeSeries, coordinates, "hour"); - this.setFetchedLocation(this.config.location || `(${coordinates.lat},${coordinates.lon})`); - this.setWeatherHourly(weatherObjects); - }) - .catch((error) => Log.error(`[weatherprovider.smhi] Could not load data: ${error.message}`)) - .finally(() => this.updateAvailable()); - }, - - /** - * Overrides method for setting config with checks for the precipitationValue being unset or invalid - * @param {object} config The configuration object - */ - setConfig (config) { - this.config = config; - if (!config.precipitationValue || ["pmin", "pmean", "pmedian", "pmax"].indexOf(config.precipitationValue) === -1) { - Log.log(`[weatherprovider.smhi] invalid or not set: ${config.precipitationValue}`); - config.precipitationValue = this.defaults.precipitationValue; +class SMHIProvider { + constructor (config) { + this.config = { + lat: 0, + lon: 0, + precipitationValue: "pmedian", // pmin, pmean, pmedian, pmax + type: "current", + updateInterval: 5 * 60 * 1000, + ...config + }; + + // Validate precipitationValue + if (!["pmin", "pmean", "pmedian", "pmax"].includes(this.config.precipitationValue)) { + Log.warn(`[smhi] Invalid precipitationValue: ${this.config.precipitationValue}, using pmedian`); + this.config.precipitationValue = "pmedian"; } - }, - - /** - * Of all the times returned find out which one is closest to the current time, should be the first if the data isn't old. - * @param {object[]} times Array of time objects - * @returns {object} The weatherdata closest to the current time - */ - getClosestToCurrentTime (times) { - let now = moment(); - let minDiff = undefined; - for (const time of times) { - let diff = Math.abs(moment(time.validTime).diff(now)); - if (!minDiff || diff < Math.abs(moment(minDiff.validTime).diff(now))) { - minDiff = time; + + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + } + + async initialize () { + try { + // SMHI requires max 6 decimal places + validateCoordinates(this.config, 6); + this.#initializeFetcher(); + } catch (error) { + Log.error("[smhi] Initialization failed:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: error.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } } - return minDiff; - }, - - /** - * Get the forecast url for the configured coordinates - * @returns {string} the url for the specified coordinates - */ - getURL () { - const formatter = new Intl.NumberFormat("en-US", { - minimumFractionDigits: 6, - maximumFractionDigits: 6 + } + + setCallbacks (onData, onError) { + this.onDataCallback = onData; + this.onErrorCallback = onError; + } + + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); + } + } + + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } + } + + #initializeFetcher () { + const url = this.#getUrl(); + + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + logContext: "weatherprovider.smhi" }); - const lon = formatter.format(this.config.lon); - const lat = formatter.format(this.config.lat); - return `https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/${lon}/lat/${lat}/data.json`; - }, - - /** - * Calculates the apparent temperature based on known atmospheric data. - * @param {object} weatherData Weatherdata to use for the calculation - * @returns {number} The apparent temperature - */ - 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.E * ((17.27 * Ta) / (237.7 + Ta)); - return Ta + 0.33 * p - 0.7 * ws - 4; - }, - - /** - * Converts the returned data into a WeatherObject with required properties set for both current weather and forecast. - * The returned units is always in metric system. - * Requires coordinates to determine if its daytime or nighttime to know which icon to use and also to set sunrise and sunset. - * @param {object} weatherData Weatherdata to convert - * @param {object} coordinates Coordinates of the locations of the weather - * @returns {WeatherObject} The converted weatherdata at the specified location - */ - convertWeatherDataToObject (weatherData, coordinates) { - let currentWeather = new WeatherObject(); - - currentWeather.date = moment(weatherData.validTime); - currentWeather.updateSunTime(coordinates.lat, coordinates.lon); - currentWeather.humidity = this.paramValue(weatherData, "r"); - currentWeather.temperature = this.paramValue(weatherData, "t"); - currentWeather.windSpeed = this.paramValue(weatherData, "ws"); - currentWeather.windFromDirection = this.paramValue(weatherData, "wd"); - currentWeather.weatherType = this.convertWeatherType(this.paramValue(weatherData, "Wsymb2"), currentWeather.isDayTime()); - currentWeather.feelsLikeTemp = this.calculateApparentTemperature(weatherData); - - /* - * Determine the precipitation amount and category and update the - * weatherObject with it, the value type to use can be configured or uses - * median as default. - */ - let precipitationValue = this.paramValue(weatherData, this.config.precipitationValue); - switch (this.paramValue(weatherData, "pcat")) { - // 0 = No precipitation + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + this.#handleResponse(data); + } catch (error) { + Log.error("[smhi] Failed to parse JSON:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + } + }); + + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } + + #handleResponse (data) { + try { + if (!data.timeSeries || !Array.isArray(data.timeSeries)) { + throw new Error("Invalid weather data"); + } + + const coordinates = this.#resolveCoordinates(data); + let weatherData; + + switch (this.config.type) { + case "current": + weatherData = this.#generateCurrentWeather(data.timeSeries, coordinates); + break; + case "forecast": + case "daily": + weatherData = this.#generateForecast(data.timeSeries, coordinates); + break; + case "hourly": + weatherData = this.#generateHourly(data.timeSeries, coordinates); + break; + default: + Log.error(`[smhi] Unknown weather type: ${this.config.type}`); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: `Unknown weather type: ${this.config.type}`, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; + } + + if (this.onDataCallback) { + this.onDataCallback(weatherData); + } + } catch (error) { + Log.error("[smhi] Error processing weather data:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: error.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + } + } + + #generateCurrentWeather (timeSeries, coordinates) { + const closest = this.#getClosestToCurrentTime(timeSeries); + return this.#convertWeatherDataToObject(closest, coordinates); + } + + #generateForecast (timeSeries, coordinates) { + const filled = this.#fillInGaps(timeSeries); + return this.#convertWeatherDataGroupedBy(filled, coordinates, "day"); + } + + #generateHourly (timeSeries, coordinates) { + const filled = this.#fillInGaps(timeSeries); + return this.#convertWeatherDataGroupedBy(filled, coordinates, "hour"); + } + + #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); + + if (minDiff === null || diff < minDiff) { + minDiff = diff; + closest = time; + } + } + + return closest; + } + + #convertWeatherDataToObject (weatherData, coordinates) { + const date = new Date(weatherData.validTime); + 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), + feelsLikeTemp: this.#calculateApparentTemperature(weatherData), + sunrise: sunrise, + sunset: sunset, + snow: 0, + rain: 0, + precipitationAmount: 0 + }; + + // Determine precipitation amount and category + const precipitationValue = this.#paramValue(weatherData, this.config.precipitationValue); + const pcat = this.#paramValue(weatherData, "pcat"); + + switch (pcat) { case 1: // Snow - currentWeather.snow += precipitationValue; - currentWeather.precipitationAmount += precipitationValue; + current.snow = precipitationValue; + current.precipitationAmount = precipitationValue; break; - case 2: // Snow and rain, treat it as 50/50 snow and rain - currentWeather.snow += precipitationValue / 2; - currentWeather.rain += precipitationValue / 2; - currentWeather.precipitationAmount += precipitationValue; + case 2: // Snow and rain (50/50 split) + 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 - currentWeather.rain += precipitationValue; - currentWeather.precipitationAmount += precipitationValue; + current.rain = precipitationValue; + current.precipitationAmount = precipitationValue; break; + // case 0: No precipitation - defaults already set to 0 } - return currentWeather; - }, - - /** - * Takes all the data points and converts it to one WeatherObject per day. - * @param {object[]} allWeatherData Array of weatherdata - * @param {object} coordinates Coordinates of the locations of the weather - * @param {string} groupBy The interval to use for grouping the data (day, hour) - * @returns {WeatherObject[]} Array of weather objects - */ - convertWeatherDataGroupedBy (allWeatherData, coordinates, groupBy = "day") { - let currentWeather; - let result = []; - - let allWeatherObjects = this.fillInGaps(allWeatherData).map((weatherData) => this.convertWeatherDataToObject(weatherData, coordinates)); + return current; + } + + #convertWeatherDataGroupedBy (allWeatherData, coordinates, groupBy = "day") { + const result = []; + let currentWeather = null; let dayWeatherTypes = []; + const allWeatherObjects = allWeatherData.map((data) => this.#convertWeatherDataToObject(data, coordinates)); + for (const weatherObject of allWeatherObjects) { - //If its the first object or if a day/hour change we need to reset the summary object - if (!currentWeather || !currentWeather.date.isSame(weatherObject.date, groupBy)) { - currentWeather = new WeatherObject(); + const objDate = new Date(weatherObject.date); + + // Check if we need a new group (day or hour change) + const needNewGroup = !currentWeather || !this.#isSamePeriod(currentWeather.date, objDate, groupBy); + + if (needNewGroup) { + currentWeather = { + date: objDate, + temperature: weatherObject.temperature, + minTemperature: Infinity, + maxTemperature: -Infinity, + snow: 0, + rain: 0, + precipitationAmount: 0, + sunrise: weatherObject.sunrise, + sunset: weatherObject.sunset + }; dayWeatherTypes = []; - currentWeather.temperature = weatherObject.temperature; - currentWeather.date = weatherObject.date; - currentWeather.minTemperature = Infinity; - currentWeather.maxTemperature = -Infinity; - currentWeather.snow = 0; - currentWeather.rain = 0; - currentWeather.precipitationAmount = 0; result.push(currentWeather); } - //Keep track of what icons have been used for each hour of daytime and use the middle one for the forecast - if (weatherObject.isDayTime()) { + // Track weather types during daytime + const { sunrise: daySunrise, sunset: daySunset } = getSunTimes(objDate, coordinates.lat, coordinates.lon); + const isDay = isDayTime(objDate, daySunrise, daySunset); + + if (isDay) { dayWeatherTypes.push(weatherObject.weatherType); } + + // Use median weather type from daytime hours if (dayWeatherTypes.length > 0) { currentWeather.weatherType = dayWeatherTypes[Math.floor(dayWeatherTypes.length / 2)]; } else { currentWeather.weatherType = weatherObject.weatherType; } - //All other properties is either a sum, min or max of each hour + // Aggregate min/max and precipitation currentWeather.minTemperature = Math.min(currentWeather.minTemperature, weatherObject.temperature); currentWeather.maxTemperature = Math.max(currentWeather.maxTemperature, weatherObject.temperature); currentWeather.snow += weatherObject.snow; @@ -216,116 +270,128 @@ WeatherProvider.register("smhi", { } return result; - }, - - /** - * Resolve coordinates from the response data (probably preferably to use - * this if it's not matching the config values exactly) - * @param {object} data Response data from the weather service - * @returns {{lon, lat}} the lat/long coordinates of the data - */ - resolveCoordinates (data) { - return { lat: data.geometry.coordinates[0][1], lon: data.geometry.coordinates[0][0] }; - }, - - /** - * The distance between the data points is increasing in the data the more distant the prediction is. - * Find these gaps and fill them with the previous hours data to make the data returned a complete set. - * @param {object[]} data Response data from the weather service - * @returns {object[]} Given data with filled gaps - */ - fillInGaps (data) { - let result = []; + } + + #isSamePeriod (date1, date2, groupBy) { + if (groupBy === "hour") { + return date1.getFullYear() === date2.getFullYear() + && date1.getMonth() === date2.getMonth() + && date1.getDate() === date2.getDate() + && date1.getHours() === date2.getHours(); + } else { // day + return date1.getFullYear() === date2.getFullYear() + && date1.getMonth() === date2.getMonth() + && date1.getDate() === date2.getDate(); + } + } + + #fillInGaps (data) { + if (data.length === 0) return []; + + const result = []; + result.push(data[0]); // Keep first data point + for (let i = 1; i < data.length; i++) { - let to = moment(data[i].validTime); - let from = moment(data[i - 1].validTime); - let hours = moment.duration(to.diff(from)).asHours(); - // For each hour add a datapoint but change the validTime - for (let j = 0; j < hours; j++) { - let current = Object.assign({}, data[i]); - current.validTime = from.clone().add(j, "hours").toISOString(); + const from = new Date(data[i - 1].validTime); + const to = new Date(data[i].validTime); + 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) + for (let j = 1; j < hours; j++) { + const current = { ...data[i - 1] }; + const newTime = new Date(from); + newTime.setHours(from.getHours() + j); + current.validTime = newTime.toISOString(); result.push(current); } + + // Push original data point + result.push(data[i]); } + return result; - }, - - /** - * Helper method to get a property from the returned data set. - * @param {object} currentWeatherData Weatherdata to get from - * @param {string} name The name of the property - * @returns {string} The value of the property in the weatherdata - */ - paramValue (currentWeatherData, name) { - return currentWeatherData.parameters.filter((p) => p.name === name).flatMap((p) => p.values)[0]; - }, - - /** - * Map the icon value from SMHI to an icon that MagicMirror² understands. - * Uses different icons depending on if its daytime or nighttime. - * SMHI's description of what the numeric value means is the comment after the case. - * @param {number} input The SMHI icon value - * @param {boolean} isDayTime True if the icon should be for daytime, false for nighttime - * @returns {string} The icon name for the MagicMirror - */ - convertWeatherType (input, isDayTime) { + } + + #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) { + return { + lat: data.geometry.coordinates[0][1], + lon: data.geometry.coordinates[0][0] + }; + } + + Log.warn("[smhi] Invalid coordinate structure in response, using config values"); + return { + lat: this.config.lat, + lon: this.config.lon + }; + } + + #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)); + + return Ta + 0.33 * p - 0.7 * ws - 4; + } + + #paramValue (weatherData, name) { + const param = weatherData.parameters.find((p) => p.name === name); + return param ? param.values[0] : null; + } + + #convertWeatherType (input, isDayTime) { switch (input) { case 1: return isDayTime ? "day-sunny" : "night-clear"; // Clear sky case 2: return isDayTime ? "day-sunny-overcast" : "night-partly-cloudy"; // Nearly clear sky case 3: - return isDayTime ? "day-cloudy" : "night-cloudy"; // Variable cloudiness case 4: - return isDayTime ? "day-cloudy" : "night-cloudy"; // Halfclear sky + return isDayTime ? "day-cloudy" : "night-cloudy"; // Variable/halfclear cloudiness case 5: - return "cloudy"; // Cloudy sky case 6: - return "cloudy"; // Overcast + return "cloudy"; // Cloudy/overcast case 7: - return "fog"; // Fog + return "fog"; case 8: - return "showers"; // Light rain showers case 9: - return "showers"; // Moderate rain showers case 10: - return "showers"; // Heavy rain showers + return "showers"; // Light/moderate/heavy rain showers case 11: - return "thunderstorm"; // Thunderstorm + case 21: + return "thunderstorm"; case 12: - return "sleet"; // Light sleet showers case 13: - return "sleet"; // Moderate sleet showers case 14: - return "sleet"; // Heavy sleet showers - case 15: - return "snow"; // Light snow showers - case 16: - return "snow"; // Moderate snow showers - case 17: - return "snow"; // Heavy snow showers - case 18: - return "rain"; // Light rain - case 19: - return "rain"; // Moderate rain - case 20: - return "rain"; // Heavy rain - case 21: - return "thunderstorm"; // Thunder case 22: - return "sleet"; // Light sleet case 23: - return "sleet"; // Moderate sleet case 24: - return "sleet"; // Heavy sleet + return "sleet"; // Light/moderate/heavy sleet (showers) + case 15: + case 16: + case 17: case 25: - return "snow"; // Light snowfall case 26: - return "snow"; // Moderate snowfall case 27: - return "snow"; // Heavy snowfall + return "snow"; // Light/moderate/heavy snow (showers/fall) + case 18: + case 19: + case 20: + return "rain"; // Light/moderate/heavy rain default: - return ""; + return null; } } -}); + + #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`; + } +} + +module.exports = SMHIProvider; diff --git a/defaultmodules/weather/providers/ukmetofficedatahub.js b/defaultmodules/weather/providers/ukmetofficedatahub.js index 4f77a368a4..b55a6f2c91 100644 --- a/defaultmodules/weather/providers/ukmetofficedatahub.js +++ b/defaultmodules/weather/providers/ukmetofficedatahub.js @@ -1,243 +1,282 @@ -/* global WeatherProvider, WeatherObject */ +const Log = require("logger"); +const { getSunTimes } = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); -/* - * This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services). - * For more information on Data Hub, see https://www.metoffice.gov.uk/services/data/datapoint/notifications/weather-datahub - * Data available: - * Hourly data for next 2 days ("hourly") - https://www.metoffice.gov.uk/binaries/content/assets/metofficegovuk/pdf/data/global-spot-data-hourly.pdf - * 3-hourly data for the next 7 days ("3hourly") - https://www.metoffice.gov.uk/binaries/content/assets/metofficegovuk/pdf/data/global-spot-data-3-hourly.pdf - * Daily data for the next 7 days ("daily") - https://www.metoffice.gov.uk/binaries/content/assets/metofficegovuk/pdf/data/global-spot-data-daily.pdf - * - * NOTES - * This provider requires longitude/latitude coordinates, rather than a location ID (as with the previous Met Office provider) - * Provide the following in your config.js file: - * weatherProvider: "ukmetofficedatahub", - * apiBase: "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/", - * apiKey: "[YOUR API KEY]", - * lat: [LATITUDE (DECIMAL)], - * lon: [LONGITUDE (DECIMAL)] - * - * At time of writing, free accounts are limited to 360 requests a day per service (hourly, 3hourly, daily); take this in mind when - * setting your update intervals. For reference, 360 requests per day is once every 4 minutes. +/** + * UK Met Office Data Hub provider + * For more information: https://www.metoffice.gov.uk/services/data/datapoint/notifications/weather-datahub * - * Pay attention to the units of the supplied data from the Met Office - it is given in SI/metric units where applicable: - * - Temperatures are in degrees Celsius (°C) - * - Wind speeds are in metres per second (m/s) - * - Wind direction given in degrees (°) - * - Pressures are in Pascals (Pa) - * - Distances are in metres (m) - * - Probabilities and humidity are given as percentages (%) - * - Precipitation is measured in millimeters (mm) with rates per hour (mm/h) + * Data available: + * - Hourly data for next 2 days (for current weather) + * - 3-hourly data for next 7 days (for hourly forecasts) + * - Daily data for next 7 days (for daily forecasts) * - * See the PDFs linked above for more information on the data their corresponding units. + * Free accounts limited to 360 requests/day per service (once every 4 minutes) */ - -WeatherProvider.register("ukmetofficedatahub", { - // Set the name of the provider. - providerName: "UK Met Office (DataHub)", - - // Set the default config properties that is specific to this provider - defaults: { - apiBase: "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/", - apiKey: "", - lat: 0, - lon: 0 - }, - - // Build URL with query strings according to DataHub API (https://datahub.metoffice.gov.uk/docs/f/category/site-specific/type/site-specific/api-documentation#get-/point/hourly) - getUrl (forecastType) { - let queryStrings = "?"; - queryStrings += `latitude=${this.config.lat}`; - queryStrings += `&longitude=${this.config.lon}`; - queryStrings += `&includeLocationName=${true}`; - - // Return URL, making sure there is a trailing "/" in the base URL. - return this.config.apiBase + (this.config.apiBase.endsWith("/") ? "" : "/") + forecastType + queryStrings; - }, - - /* - * Build the list of headers for the request - * For DataHub requests, the API key/secret are sent in the headers rather than as query strings. - * Headers defined according to Data Hub API (https://datahub.metoffice.gov.uk/docs/f/category/site-specific/type/site-specific/api-documentation#get-/point/hourly) - */ - getHeaders () { - return { - accept: "application/json", - apikey: this.config.apiKey +class UkMetOfficeDataHubProvider { + constructor (config) { + this.config = { + apiBase: "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/", + apiKey: "", + lat: 0, + lon: 0, + type: "current", + updateInterval: 10 * 60 * 1000, + ...config }; - }, - - // Fetch data using supplied URL and request headers - async fetchWeather (url, headers) { - const response = await fetch(url, { headers: headers }); - - // Return JSON data - return response.json(); - }, - - // Fetch hourly forecast data (to use for current weather) - fetchCurrentWeather () { - this.fetchWeather(this.getUrl("hourly"), this.getHeaders()) - .then((data) => { - // Check data is usable - if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) { - - /* - * Did not receive usable new data. - * Maybe this needs a better check? - */ - Log.error("[weatherprovider.ukmetofficedatahub] Possibly bad current/hourly data?", data); - return; + + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + } + + setCallbacks (onDataCallback, onErrorCallback) { + this.onDataCallback = onDataCallback; + this.onErrorCallback = onErrorCallback; + } + + async initialize () { + if (!this.config.apiKey || this.config.apiKey === "YOUR_API_KEY_HERE") { + Log.error("[ukmetofficedatahub] No API key configured"); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "UK Met Office DataHub API key required. Get one at https://datahub.metoffice.gov.uk/", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; + } + + this.#initializeFetcher(); + } + + #initializeFetcher () { + const forecastType = this.#getForecastType(); + const url = this.#getUrl(forecastType); + + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + headers: { + Accept: "application/json", + apikey: this.config.apiKey + }, + logContext: "weatherprovider.ukmetofficedatahub" + }); + + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + this.#handleResponse(data); + } catch (error) { + Log.error("[ukmetofficedatahub] Parse error:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } + } + }); + + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } + + #getForecastType () { + switch (this.config.type) { + case "hourly": + return "three-hourly"; + case "forecast": + case "daily": + return "daily"; + case "current": + default: + return "hourly"; + } + } + + #getUrl (forecastType) { + const base = this.config.apiBase.endsWith("/") ? this.config.apiBase : `${this.config.apiBase}/`; + const queryStrings = `?latitude=${this.config.lat}&longitude=${this.config.lon}&includeLocationName=true`; + return `${base}${forecastType}${queryStrings}`; + } - // Set location name - this.setFetchedLocation(`${data.features[0].properties.location.name}`); - - // Generate current weather data - const currentWeather = this.generateWeatherObjectFromCurrentWeather(data); - this.setCurrentWeather(currentWeather); - }) - - // Catch any error(s) - .catch((error) => Log.error(`[weatherprovider.ukmetofficedatahub] Could not load data: ${error.message}`)) - - // Let the module know there is data available - .finally(() => this.updateAvailable()); - }, - - // Create a WeatherObject using current weather data (data for the current hour) - generateWeatherObjectFromCurrentWeather (currentWeatherData) { - const currentWeather = new WeatherObject(); - - // Extract the actual forecasts - let forecastDataHours = currentWeatherData.features[0].properties.timeSeries; - - // Define now - let nowUtc = moment.utc(); - - // Find hour that contains the current time - for (let hour in forecastDataHours) { - let forecastTime = moment.utc(forecastDataHours[hour].time); - if (nowUtc.isSameOrAfter(forecastTime) && nowUtc.isBefore(moment(forecastTime.add(1, "h")))) { - currentWeather.date = forecastTime; - currentWeather.windSpeed = forecastDataHours[hour].windSpeed10m; - currentWeather.windFromDirection = forecastDataHours[hour].windDirectionFrom10m; - currentWeather.temperature = forecastDataHours[hour].screenTemperature; - currentWeather.minTemperature = forecastDataHours[hour].minScreenAirTemp; - currentWeather.maxTemperature = forecastDataHours[hour].maxScreenAirTemp; - currentWeather.weatherType = this.convertWeatherType(forecastDataHours[hour].significantWeatherCode); - currentWeather.humidity = forecastDataHours[hour].screenRelativeHumidity; - currentWeather.rain = forecastDataHours[hour].totalPrecipAmount; - currentWeather.snow = forecastDataHours[hour].totalSnowAmount; - currentWeather.precipitationProbability = forecastDataHours[hour].probOfPrecipitation; - currentWeather.feelsLikeTemp = forecastDataHours[hour].feelsLikeTemperature; - - /* - * Pass on full details, so they can be used in custom templates - * Note the units of the supplied data when using this (see top of file) - */ - currentWeather.rawData = forecastDataHours[hour]; + #handleResponse (data) { + if (!data || !data.features || !data.features[0] || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) { + Log.error("[ukmetofficedatahub] No usable data received"); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "No usable data in API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } + return; } - /* - * Determine the sunrise/sunset times - (still) not supplied in UK Met Office data - * Passes {longitude, latitude} to SunCalc, could pass height to, but - * SunCalc.getTimes doesn't take that into account - */ - currentWeather.updateSunTime(this.config.lat, this.config.lon); - - return currentWeather; - }, - - // Fetch daily forecast data - fetchWeatherForecast () { - this.fetchWeather(this.getUrl("daily"), this.getHeaders()) - .then((data) => { - // Check data is usable - if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) { - - /* - * Did not receive usable new data. - * Maybe this needs a better check? - */ - Log.error("[weatherprovider.ukmetofficedatahub] Possibly bad forecast data?", data); - return; + let weatherData = null; + + switch (this.config.type) { + case "current": + weatherData = this.#generateCurrent(data); + break; + case "forecast": + case "daily": + weatherData = this.#generateDaily(data); + break; + case "hourly": + weatherData = this.#generateHourly(data); + break; + default: + Log.error(`[ukmetofficedatahub] Unknown weather type: ${this.config.type}`); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: `Unknown weather type: ${this.config.type}`, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } + return; + } + + if (weatherData && this.onDataCallback) { + this.onDataCallback(weatherData); + } + } + + #generateCurrent (data) { + const timeSeries = data.features[0].properties.timeSeries; + const now = new Date(); + + // Find the hour that contains current time + for (const hour of timeSeries) { + const forecastTime = new Date(hour.time); + const oneHourLater = new Date(forecastTime.getTime() + 60 * 60 * 1000); + + if (now >= forecastTime && now < oneHourLater) { + const current = { + date: forecastTime, + temperature: hour.screenTemperature || null, + minTemperature: hour.minScreenAirTemp || null, + maxTemperature: hour.maxScreenAirTemp || null, + windSpeed: hour.windSpeed10m || null, + windFromDirection: hour.windDirectionFrom10m || null, + weatherType: this.#convertWeatherType(hour.significantWeatherCode), + humidity: hour.screenRelativeHumidity || null, + rain: hour.totalPrecipAmount || 0, + snow: hour.totalSnowAmount || 0, + precipitationAmount: (hour.totalPrecipAmount || 0) + (hour.totalSnowAmount || 0), + precipitationProbability: hour.probOfPrecipitation || null, + feelsLikeTemp: hour.feelsLikeTemperature || null, + sunrise: null, + sunset: null + }; + + // Calculate sunrise/sunset using SunCalc + const { sunrise, sunset } = getSunTimes(now, this.config.lat, this.config.lon); + current.sunrise = sunrise; + current.sunset = sunset; + + return current; + } + } + + // Fallback to first hour if no match found + const firstHour = timeSeries[0]; + const current = { + date: new Date(firstHour.time), + temperature: firstHour.screenTemperature || null, + windSpeed: firstHour.windSpeed10m || null, + windFromDirection: firstHour.windDirectionFrom10m || null, + weatherType: this.#convertWeatherType(firstHour.significantWeatherCode), + humidity: firstHour.screenRelativeHumidity || null, + rain: firstHour.totalPrecipAmount || 0, + snow: firstHour.totalSnowAmount || 0, + precipitationAmount: (firstHour.totalPrecipAmount || 0) + (firstHour.totalSnowAmount || 0), + precipitationProbability: firstHour.probOfPrecipitation || null, + feelsLikeTemp: firstHour.feelsLikeTemperature || null, + sunrise: null, + sunset: null + }; + + const { sunrise, sunset } = getSunTimes(now, this.config.lat, this.config.lon); + current.sunrise = sunrise; + current.sunset = sunset; + + return current; + } - // Set location name - this.setFetchedLocation(`${data.features[0].properties.location.name}`); - - // Generate the forecast data - const forecast = this.generateWeatherObjectsFromForecast(data); - this.setWeatherForecast(forecast); - }) - - // Catch any error(s) - .catch((error) => Log.error(`[weatherprovider.ukmetofficedatahub] Could not load data: ${error.message}`)) - - // Let the module know there is new data available - .finally(() => this.updateAvailable()); - }, - - // Create a WeatherObject for each day using daily forecast data - generateWeatherObjectsFromForecast (forecasts) { - const dailyForecasts = []; - - // Extract the actual forecasts - let forecastDataDays = forecasts.features[0].properties.timeSeries; - - // Define today - let today = moment.utc().startOf("date"); - - // Go through each day in the forecasts - for (let day in forecastDataDays) { - const forecastWeather = new WeatherObject(); - - // Get date of forecast - let forecastDate = moment.utc(forecastDataDays[day].time); - - // Check if forecast is for today or in the future (i.e., ignore yesterday's forecast) - if (forecastDate.isSameOrAfter(today)) { - forecastWeather.date = forecastDate; - forecastWeather.minTemperature = forecastDataDays[day].nightMinScreenTemperature; - forecastWeather.maxTemperature = forecastDataDays[day].dayMaxScreenTemperature; - - // Using daytime forecast values - forecastWeather.windSpeed = forecastDataDays[day].midday10MWindSpeed; - forecastWeather.windFromDirection = forecastDataDays[day].midday10MWindDirection; - forecastWeather.weatherType = this.convertWeatherType(forecastDataDays[day].daySignificantWeatherCode); - forecastWeather.precipitationProbability = forecastDataDays[day].dayProbabilityOfPrecipitation; - forecastWeather.temperature = forecastDataDays[day].dayMaxScreenTemperature; - forecastWeather.humidity = forecastDataDays[day].middayRelativeHumidity; - forecastWeather.rain = forecastDataDays[day].dayProbabilityOfRain; - forecastWeather.snow = forecastDataDays[day].dayProbabilityOfSnow; - forecastWeather.feelsLikeTemp = forecastDataDays[day].dayMaxFeelsLikeTemp; - - /* - * Pass on full details, so they can be used in custom templates - * Note the units of the supplied data when using this (see top of file) - */ - forecastWeather.rawData = forecastDataDays[day]; - - dailyForecasts.push(forecastWeather); + #generateDaily (data) { + const timeSeries = data.features[0].properties.timeSeries; + const days = []; + const today = new Date(); + today.setHours(0, 0, 0, 0); + + for (const day of timeSeries) { + const forecastDate = new Date(day.time); + forecastDate.setHours(0, 0, 0, 0); + + // Only include today and future days + if (forecastDate >= today) { + days.push({ + date: new Date(day.time), + minTemperature: day.nightMinScreenTemperature || null, + maxTemperature: day.dayMaxScreenTemperature || null, + temperature: day.dayMaxScreenTemperature || null, + windSpeed: day.midday10MWindSpeed || null, + windFromDirection: day.midday10MWindDirection || null, + weatherType: this.#convertWeatherType(day.daySignificantWeatherCode), + humidity: day.middayRelativeHumidity || null, + rain: day.dayProbabilityOfRain || 0, + snow: day.dayProbabilityOfSnow || 0, + precipitationAmount: 0, + precipitationProbability: day.dayProbabilityOfPrecipitation || null, + feelsLikeTemp: day.dayMaxFeelsLikeTemp || null + }); } } - return dailyForecasts; - }, + return days; + } + + #generateHourly (data) { + const timeSeries = data.features[0].properties.timeSeries; + const hours = []; + + for (const hour of timeSeries) { + // 3-hourly data uses maxScreenAirTemp/minScreenAirTemp, not screenTemperature + const temp = hour.screenTemperature !== undefined + ? hour.screenTemperature + : (hour.maxScreenAirTemp !== undefined && hour.minScreenAirTemp !== undefined) + ? (hour.maxScreenAirTemp + hour.minScreenAirTemp) / 2 + : null; + + hours.push({ + date: new Date(hour.time), + temperature: temp, + windSpeed: hour.windSpeed10m || null, + windFromDirection: hour.windDirectionFrom10m || null, + weatherType: this.#convertWeatherType(hour.significantWeatherCode), + humidity: hour.screenRelativeHumidity || null, + rain: hour.totalPrecipAmount || 0, + snow: hour.totalSnowAmount || 0, + precipitationAmount: (hour.totalPrecipAmount || 0) + (hour.totalSnowAmount || 0), + precipitationProbability: hour.probOfPrecipitation || null, + feelsLikeTemp: hour.feelsLikeTemp || null + }); + } - // Set the fetched location name. - setFetchedLocation (name) { - this.fetchedLocationName = name; - }, + return hours; + } - /* - * Match the Met Office "significant weather code" to a weathericons.css icon - * Use: https://metoffice.apiconnect.ibmcloud.com/metoffice/production/node/264 - * and: https://erikflowers.github.io/weather-icons/ + /** + * Convert Met Office significant weather code to weathericons.css icon + * See: https://metoffice.apiconnect.ibmcloud.com/metoffice/production/node/264 + * @param {number} weatherType - Met Office weather code + * @returns {string|null} Weathericons.css icon name or null */ - convertWeatherType (weatherType) { + #convertWeatherType (weatherType) { const weatherTypes = { 0: "night-clear", 1: "day-sunny", @@ -271,6 +310,20 @@ WeatherProvider.register("ukmetofficedatahub", { 30: "thunderstorm" }; - return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; + return weatherTypes[weatherType] || null; + } + + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); + } + } + + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } } -}); +} + +module.exports = UkMetOfficeDataHubProvider; diff --git a/defaultmodules/weather/providers/weatherapi.js b/defaultmodules/weather/providers/weatherapi.js index e0bf3c9fb4..46aef7f87b 100644 --- a/defaultmodules/weather/providers/weatherapi.js +++ b/defaultmodules/weather/providers/weatherapi.js @@ -1,297 +1,357 @@ -/* global WeatherProvider, WeatherObject */ - -/* - * This class is a provider for Weather API, - * see https://www.weatherapi.com/docs/ - */ +const Log = require("logger"); +const { convertKmhToMs, cardinalToDegrees } = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); const WEATHER_API_BASE = "https://api.weatherapi.com/v1"; -const EMPTY_RESPONSE_DATA = { - location: { - name: "", - region: "", - country: "", - lat: 0, - lon: 0, - tz_id: "", - localtime_epoch: 0, - localtime: "" - }, - forecast: { - forecastday: [] + +class WeatherAPIProvider { + constructor (config) { + this.config = { + apiBase: WEATHER_API_BASE, + lat: 0, + lon: 0, + type: "current", + apiKey: "", + lang: "en", + maxEntries: 5, + maxNumberOfDays: 5, + updateInterval: 10 * 60 * 1000, + ...config + }; + + this.locationName = null; + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; } -}; - -WeatherProvider.register("weatherapi", { - /* - * Set the name of the provider. - * Not strictly required but helps for debugging. - */ - providerName: "Weather API", - - // Set the default config properties that is specific to this provider - defaults: { - apiBase: WEATHER_API_BASE, - lat: 0, - lon: 0, - type: "current", - apiKey: "" - }, - - requestForecast () { - return new Promise((resolve, reject) => { - this.fetchData(this.getForecastUrl()) - .then((data) => resolve(data)) - .catch((request) => reject(request)); - }); - }, - preProcessResponses (responseData) { - // Ensure nested structures - responseData.location ??= {}; - responseData.current ??= {}; - responseData.current.condition ??= {}; - responseData.forecast ??= {}; - responseData.forecast.forecastday ??= []; - responseData.forecast.forecastday = responseData.forecast.forecastday.map((fd) => ({ - ...fd, - astro: fd.astro ?? {}, - day: fd.day ?? {}, - hour: fd.hour ?? [] - })); + async initialize () { + this.#validateConfig(); + this.#initializeFetcher(); + } - const locationParts = [responseData.location.name, responseData.location.region, responseData.location.country].map((v) => `${v}`.trim()).filter((v) => v !== ""); + setCallbacks (onData, onError) { + this.onDataCallback = onData; + this.onErrorCallback = onError; + } - if (locationParts.length > 0) { - this.setFetchedLocation(locationParts.join(", ").trim()); + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); } + } - return responseData; - }, - - fetchCurrentWeather () { - this.requestForecast() - .then((data) => this.preProcessResponses(data)) - .then((data) => this.parseWeatherApiResponse(data)) - .then((parsedData) => { - if (!parsedData) { - // No usable data? - return; - } + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } + } - const currentWeather = this.generateWeatherDayFromCurrentWeather(parsedData); - this.setCurrentWeather(currentWeather); - }) - .catch(function (err) { - Log.error("[weatherprovider.weatherapi] Could not load data ... ", err); - }) - .finally(() => this.updateAvailable()); - }, - - fetchWeatherForecast () { - this.requestForecast() - .then((data) => this.preProcessResponses(data)) - .then((data) => this.parseWeatherApiResponse(data)) - .then((parsedData) => { - if (!parsedData) { - // No usable data? - return; - } + #validateConfig () { + this.config.type = `${this.config.type ?? ""}`.trim().toLowerCase(); + + if (this.config.type === "forecast") { + this.config.type = "daily"; + } + + if (!["hourly", "daily", "current"].includes(this.config.type)) { + throw new Error(`Unknown weather type: ${this.config.type}`); + } + + if (!this.config.apiKey || `${this.config.apiKey}`.trim() === "") { + throw new Error("apiKey is required"); + } + + if (!Number.isFinite(this.config.lat) || !Number.isFinite(this.config.lon)) { + throw new Error("Latitude and longitude are required"); + } + } + + #initializeFetcher () { + const url = this.#getUrl(); + + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + headers: { "Cache-Control": "no-cache" }, + logContext: "weatherprovider.weatherapi" + }); - const dailyForecast = this.generateWeatherObjectsFromForecast(parsedData); - - this.setWeatherForecast(dailyForecast); - }) - .catch(function (err) { - Log.error("[weatherprovider.weatherapi] Could not load data ... ", err); - }) - .finally(() => this.updateAvailable()); - }, - - fetchWeatherHourly () { - this.requestForecast() - .then((data) => this.preProcessResponses(data)) - .then((data) => this.parseWeatherApiResponse(data)) - .then((parsedData) => { - if (!parsedData) { - // No usable data? - return; + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + this.#handleResponse(data); + } catch (error) { + Log.error("[weatherapi] Failed to parse JSON:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } + } + }); - const hourlyForecast = this.generateWeatherObjectsFromHourly(parsedData); - this.setWeatherHourly(hourlyForecast); - }) - .catch(function (request) { - Log.error("[weatherprovider.weatherapi] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - // Sanitize config - validateConfig () { - this.config.type = `${this.config.type ?? ""}`.trim().toLowerCase(); - Object.keys(this.defaults).forEach((key) => { - if (typeof this.config[key] === "undefined" || this.config[key] === null || `${this.config[key]}`.trim() === "") { - const message = `[weatherprovider.weatherapi] ${key} not configured`; - Log.error(message); - throw new Error(message); + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); } }); + } - if (this.config.type === "forecast") this.config.type = "daily"; - if (!["hourly", "daily", "current"].includes(this.config.type)) { - const message = `[weatherprovider.weatherapi] Unknown type: ${this.config.type}`; - Log.error(message); - throw new Error(message); + #handleResponse (data) { + let parsedData; + + try { + parsedData = this.#parseResponse(data); + } catch (error) { + Log.error("[weatherapi] Invalid API response:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Invalid API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; } - // fix values - if (this.config.type === "current") { - this.config.maxEntries = 1; - this.config.maxNumberOfDays = 1; - this.config.ignoreToday = false; - } else { - this.config.ignoreToday = !!this.config.ignoreToday; + try { + let weatherData; + + switch (this.config.type) { + case "current": + weatherData = this.#generateCurrent(parsedData); + break; + case "daily": + weatherData = this.#generateDaily(parsedData); + break; + case "hourly": + weatherData = this.#generateHourly(parsedData); + break; + default: + throw new Error(`Unknown weather type: ${this.config.type}`); + } + + if (this.onDataCallback && weatherData) { + this.onDataCallback(weatherData); + } + } catch (error) { + Log.error("[weatherapi] Error processing weather data:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: error.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } } - }, - - /** - * Overrides method for setting config to check if endpoint is correct for hourly - * @param {object} config The configuration object - */ - setConfig (config) { - this.fetchedLocationName = null; - this.config = { - lang: config.lang ?? "en", - ...this.defaults, - ...config - }; + } + + #getQueryParameters () { + const maxEntries = Number.isFinite(this.config.maxEntries) + ? Math.max(1, this.config.maxEntries) + : 5; - this.validateConfig(); - }, + const requestedDays = Number.isFinite(this.config.maxNumberOfDays) + ? Math.max(1, this.config.maxNumberOfDays) + : 5; - // Generate valid query params to perform the request - getForecastQueryParameters () { - let params = { + const hourlyDays = Math.max(1, Math.ceil(maxEntries / 24)); + const days = this.config.type === "hourly" + ? Math.min(14, Math.max(requestedDays, hourlyDays)) + : this.config.type === "daily" + ? Math.min(14, requestedDays) + : 1; + + const params = { q: `${this.config.lat},${this.config.lon}`, - unixdt: moment().valueOf(), - days: this.config.maxNumberOfDays, + days, lang: this.config.lang, - tp: 60, key: this.config.apiKey }; return Object.keys(params) - .filter((key) => !!params[key]) - .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`.trim()) + .filter((key) => params[key] !== undefined && params[key] !== null && `${params[key]}`.trim() !== "") + .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`) .join("&"); - }, - - // Create a URL from the config and base URL. - getForecastUrl () { - return `${this.config.apiBase}/forecast.json?${this.getForecastQueryParameters()}`; - }, - - // fix daylight-saving-time differences - checkDST (dt) { - const uxdt = moment.unix(dt); - const nowDST = moment().isDST(); - if (nowDST === moment(uxdt).isDST()) { - return uxdt; - } else { - return uxdt.add(nowDST ? +1 : -1, "hour"); + } + + #getUrl () { + return `${this.config.apiBase}/forecast.json?${this.#getQueryParameters()}`; + } + + #parseResponse (responseData) { + responseData.location ??= {}; + responseData.current ??= {}; + responseData.current.condition ??= {}; + responseData.forecast ??= {}; + responseData.forecast.forecastday ??= []; + responseData.forecast.forecastday = responseData.forecast.forecastday.map((forecastDay) => ({ + ...forecastDay, + astro: forecastDay.astro ?? {}, + day: forecastDay.day ?? {}, + hour: forecastDay.hour ?? [] + })); + + const locationParts = [ + responseData.location.name, + responseData.location.region, + responseData.location.country + ] + .map((value) => `${value}`.trim()) + .filter((value) => value !== ""); + + if (locationParts.length > 0) { + this.locationName = locationParts.join(", ").trim(); + } + + if ( + !responseData.location + || !responseData.current + || !responseData.forecast + || !Array.isArray(responseData.forecast.forecastday) + ) { + throw new Error("Invalid API response"); + } + + return responseData; + } + + #parseSunDatetime (forecastDay, key) { + const timeValue = forecastDay?.astro?.[key]; + if (!timeValue || !forecastDay?.date) { + return null; + } + + const match = /^\s*(\d{1,2}):(\d{2})\s*(AM|PM)\s*$/i.exec(timeValue); + if (!match) { + return null; + } + + let hour = parseInt(match[1], 10); + const minute = parseInt(match[2], 10); + const period = match[3].toUpperCase(); + + if (period === "PM" && hour !== 12) hour += 12; + if (period === "AM" && hour === 12) hour = 0; + + const date = new Date(`${forecastDay.date}T00:00:00`); + date.setHours(hour, minute, 0, 0); + return date; + } + + #toNumber (value) { + const number = parseFloat(value); + return Number.isFinite(number) ? number : null; + } + + #generateCurrent (data) { + const weather = data.forecast.forecastday[0] ?? {}; + const current = data.current ?? {}; + const currentWeather = { + date: current.last_updated_epoch ? new Date(current.last_updated_epoch * 1000) : new Date() + }; + + const humidity = this.#toNumber(current.humidity); + if (humidity !== null) currentWeather.humidity = humidity; + + const temperature = this.#toNumber(current.temp_c); + if (temperature !== null) currentWeather.temperature = temperature; + + const feelsLikeTemp = this.#toNumber(current.feelslike_c); + if (feelsLikeTemp !== null) currentWeather.feelsLikeTemp = feelsLikeTemp; + + const windSpeed = this.#toNumber(current.wind_kph); + if (windSpeed !== null) currentWeather.windSpeed = convertKmhToMs(windSpeed); + + const windFromDirection = this.#toNumber(current.wind_degree); + if (windFromDirection !== null) currentWeather.windFromDirection = windFromDirection; + + if (current.condition?.code !== undefined) { + currentWeather.weatherType = this.#convertWeatherType(current.condition.code, current.is_day === 1); } - }, - - // Transpose hourly and daily data matrices - transposeDataMatrix (data) { - return data.time.map((_, index) => Object.keys(data).reduce((row, key) => { - return { - ...row, - // Parse time values as moment.js instances - [key]: ["time", "sunrise", "sunset"].includes(key) ? this.checkDST(data[key][index]) : data[key][index] - }; - }, {})); - }, - - // Sanitize and validate API response - parseWeatherApiResponse (data) { - const _isObject = (obj) => obj && typeof obj === "object" && obj !== null && !Array.isArray(obj); - const _isArray = (obj) => obj && Array.isArray(obj); - - if (_isObject(data.location) && _isObject(data.current) && _isObject(data.forecast) && _isArray(data.forecast.forecastday)) { - return data; + + const sunrise = this.#parseSunDatetime(weather, "sunrise"); + const sunset = this.#parseSunDatetime(weather, "sunset"); + if (sunrise) currentWeather.sunrise = sunrise; + if (sunset) currentWeather.sunset = sunset; + + const minTemperature = this.#toNumber(weather.day?.mintemp_c); + if (minTemperature !== null) currentWeather.minTemperature = minTemperature; + + const maxTemperature = this.#toNumber(weather.day?.maxtemp_c); + if (maxTemperature !== null) currentWeather.maxTemperature = maxTemperature; + + const snow = this.#toNumber(current.snow_cm); + if (snow !== null) currentWeather.snow = snow * 10; + + const rain = this.#toNumber(current.precip_mm); + if (rain !== null) currentWeather.rain = rain; + + if (rain !== null || snow !== null) { + currentWeather.precipitationAmount = (rain ?? 0) + ((snow ?? 0) * 10); } - throw new Error("Invalid API response"); - }, - - // Parse sunrise and sunset moments - parseSunDatetime (forecastDay, key) { - const { date, astro } = forecastDay; - return moment(`${date} ${astro[key]}`, "YYYY-MM-DD hh:mm A"); - }, - - // Implement WeatherDay generator. - generateWeatherDayFromCurrentWeather (data) { - const fd = data.forecast.forecastday[0]; - const weather = new WeatherObject(); - - weather.date = moment(); - weather.humidity = parseFloat(data.current.humidity); - weather.temperature = parseFloat(data.current.temp_c); - weather.feelsLikeTemp = parseFloat(data.current.feelslike_c); - weather.windSpeed = parseFloat(data.current.wind_kph) * 0.2778; - weather.windFromDirection = parseFloat(data.current.wind_degree); - weather.weatherType = this.convertWeatherType(data.current.condition.code, data.current.is_day === 1); - weather.sunrise = this.parseSunDatetime(fd, "sunrise"); - weather.sunset = this.parseSunDatetime(fd, "sunset"); - // Optional - weather.minTemperature = parseFloat(fd.day.mintemp_c); - weather.maxTemperature = parseFloat(fd.day.maxtemp_c); - weather.snow = parseFloat(data.current.snow_cm * 10); - weather.rain = parseFloat(data.current.precip_mm); - weather.precipitationAmount = weather.rain + weather.snow; - weather.uv_index = parseFloat(data.current.uv); - - return weather; - }, - - // Implement WeatherForecast generator. - generateWeatherObjectsFromForecast (data) { + return currentWeather; + } + + #generateDaily (data) { const days = []; + const forecastDays = data.forecast.forecastday ?? []; + + for (const forecastDay of forecastDays) { + const weather = {}; + const dayDate = forecastDay.date_epoch + ? new Date(forecastDay.date_epoch * 1000) + : new Date(`${forecastDay.date}T00:00:00`); + + const precipitationProbability = forecastDay.hour?.length > 0 + ? (forecastDay.hour.reduce((sum, hourData) => { + const rain = this.#toNumber(hourData.will_it_rain) ?? 0; + const snow = this.#toNumber(hourData.will_it_snow) ?? 0; + return sum + ((rain + snow) / 2); + }, 0) / forecastDay.hour.length) * 100 + : null; + + const avgWindDegree = forecastDay.hour?.length > 0 + ? forecastDay.hour.reduce((sum, hourData) => { + return sum + (this.#toNumber(hourData.wind_degree) ?? 0); + }, 0) / forecastDay.hour.length + : null; + + weather.date = dayDate; + weather.minTemperature = this.#toNumber(forecastDay.day?.mintemp_c); + weather.maxTemperature = this.#toNumber(forecastDay.day?.maxtemp_c); + weather.weatherType = this.#convertWeatherType(forecastDay.day?.condition?.code, true); + + const maxWind = this.#toNumber(forecastDay.day?.maxwind_kph); + if (maxWind !== null) weather.windSpeed = convertKmhToMs(maxWind); + + if (avgWindDegree !== null) { + weather.windFromDirection = avgWindDegree; + } + + const sunrise = this.#parseSunDatetime(forecastDay, "sunrise"); + const sunset = this.#parseSunDatetime(forecastDay, "sunset"); + if (sunrise) weather.sunrise = sunrise; + if (sunset) weather.sunset = sunset; + + weather.temperature = this.#toNumber(forecastDay.day?.avgtemp_c); + weather.humidity = this.#toNumber(forecastDay.day?.avghumidity); + + const snow = this.#toNumber(forecastDay.day?.totalsnow_cm); + if (snow !== null) weather.snow = snow * 10; - for (const fd of data.forecast.forecastday) { - const weather = new WeatherObject(); - - const precipitationProbability - = (fd.hour.reduce((acc, h) => { - const idxValue = ((h.will_it_rain ?? 0) + (h.will_it_snow ?? 0)) / 2; - return acc + idxValue; - }, 0) - / fd.hour.length) - * 100; - - const avgwind_degree - = fd.hour.reduce((acc, h) => { - return acc + (h.wind_degree ?? 0); - }, 0) / fd.hour.length; - - weather.date = moment(fd.date).startOf("day"); - weather.minTemperature = parseFloat(fd.day.mintemp_c); - weather.maxTemperature = parseFloat(fd.day.maxtemp_c); - weather.weatherType = this.convertWeatherType(fd.day.condition.code, true); - weather.windSpeed = parseFloat(fd.day.maxwind_kph) * 0.2778; - weather.windFromDirection = parseFloat(avgwind_degree); - weather.sunrise = this.parseSunDatetime(fd, "sunrise"); - weather.sunset = this.parseSunDatetime(fd, "sunset"); - weather.temperature = parseFloat(fd.day.avgtemp_c); - weather.humidity = parseFloat(fd.day.avghumidity); - weather.snow = parseFloat(fd.day.totalsnow_cm * 10); - weather.rain = parseFloat(fd.day.totalprecip_mm); - weather.precipitationAmount = weather.rain + weather.snow; - weather.precipitationProbability = precipitationProbability; - weather.uv_index = parseFloat(fd.day.uv); + const rain = this.#toNumber(forecastDay.day?.totalprecip_mm); + if (rain !== null) weather.rain = rain; + + if (rain !== null || snow !== null) { + weather.precipitationAmount = (rain ?? 0) + ((snow ?? 0) * 10); + } + + if (precipitationProbability !== null) { + weather.precipitationProbability = precipitationProbability; + } + + weather.uv_index = this.#toNumber(forecastDay.day?.uv); days.push(weather); @@ -301,37 +361,56 @@ WeatherProvider.register("weatherapi", { } return days; - }, + } - // Implement WeatherHourly generator. - generateWeatherObjectsFromHourly (data) { + #generateHourly (data) { const hours = []; - const now = moment(); - const nowStart = moment(now).add(1, "hour").startOf("hour"); + const nowStart = new Date(); + nowStart.setMinutes(0, 0, 0); + nowStart.setHours(nowStart.getHours() + 1); - for (const fd of data.forecast.forecastday) { - for (const h of fd.hour) { - const currentMoment = moment(h.time, "YYYY-MM-DD HH:00"); - if (currentMoment.isBefore(nowStart)) { + for (const forecastDay of data.forecast.forecastday ?? []) { + for (const hourData of forecastDay.hour ?? []) { + const date = hourData.time_epoch + ? new Date(hourData.time_epoch * 1000) + : new Date(hourData.time); + + if (date < nowStart) { continue; } - const weather = new WeatherObject(); - - weather.date = currentMoment; - weather.sunrise = this.parseSunDatetime(fd, "sunrise"); - weather.sunset = this.parseSunDatetime(fd, "sunset"); - weather.minTemperature = parseFloat(fd.day.mintemp_c); - weather.maxTemperature = parseFloat(fd.day.maxtemp_c); - weather.humidity = parseFloat(h.humidity); - weather.windSpeed = parseFloat(h.wind_kph) * 0.2778; - weather.windFromDirection = parseFloat(h.wind_degree); - weather.weatherType = this.convertWeatherType(h.condition.code, h.is_day === 1); - weather.snow = parseFloat(h.snow_cm * 10); - weather.temperature = parseFloat(h.temp_c); - weather.precipitationAmount = parseFloat(h.precip_mm); - weather.precipitationProbability = ((h.will_it_rain ?? 0) + (h.will_it_snow ?? 0)) * 50; - weather.uv_index = parseFloat(h.uv); + const weather = { date }; + + const sunrise = this.#parseSunDatetime(forecastDay, "sunrise"); + const sunset = this.#parseSunDatetime(forecastDay, "sunset"); + if (sunrise) weather.sunrise = sunrise; + if (sunset) weather.sunset = sunset; + + weather.minTemperature = this.#toNumber(forecastDay.day?.mintemp_c); + weather.maxTemperature = this.#toNumber(forecastDay.day?.maxtemp_c); + weather.humidity = this.#toNumber(hourData.humidity); + + const windSpeed = this.#toNumber(hourData.wind_kph); + if (windSpeed !== null) weather.windSpeed = convertKmhToMs(windSpeed); + + const windDegree = this.#toNumber(hourData.wind_degree); + weather.windFromDirection = windDegree !== null + ? windDegree + : cardinalToDegrees(hourData.wind_dir); + + weather.weatherType = this.#convertWeatherType(hourData.condition?.code, hourData.is_day === 1); + + const snow = this.#toNumber(hourData.snow_cm); + if (snow !== null) weather.snow = snow * 10; + + weather.temperature = this.#toNumber(hourData.temp_c); + weather.precipitationAmount = this.#toNumber(hourData.precip_mm); + + const willRain = this.#toNumber(hourData.will_it_rain) ?? 0; + const willSnow = this.#toNumber(hourData.will_it_snow) ?? 0; + weather.precipitationProbability = (willRain + willSnow) * 50; + + weather.uv_index = this.#toNumber(hourData.uv); hours.push(weather); @@ -346,10 +425,9 @@ WeatherProvider.register("weatherapi", { } return hours; - }, + } - // Map icons from Dark Sky to our icons. - convertWeatherType (weathercode, isDayTime) { + #convertWeatherType (weatherCode, isDayTime) { const weatherConditions = { 1000: { day: "day-sunny", night: "night-clear" }, 1003: { day: "day-cloudy", night: "night-alt-cloudy" }, @@ -401,12 +479,12 @@ WeatherProvider.register("weatherapi", { 1282: { day: "day-snow-thunderstorm", night: "night-snow-thunderstorm" } }; - if (!Object.keys(weatherConditions).includes(`${weathercode}`)) return "na"; - return weatherConditions[`${weathercode}`][isDayTime ? "day" : "night"]; - }, + if (!Object.prototype.hasOwnProperty.call(weatherConditions, weatherCode)) { + return "na"; + } - // Define required scripts. - getScripts () { - return ["moment.js"]; + return weatherConditions[weatherCode][isDayTime ? "day" : "night"]; } -}); +} + +module.exports = WeatherAPIProvider; diff --git a/defaultmodules/weather/providers/weatherbit.js b/defaultmodules/weather/providers/weatherbit.js index 8423babb2b..14a6447668 100644 --- a/defaultmodules/weather/providers/weatherbit.js +++ b/defaultmodules/weather/providers/weatherbit.js @@ -1,138 +1,211 @@ -/* global WeatherProvider, WeatherObject */ +const Log = require("logger"); +const HTTPFetcher = require("#http_fetcher"); -/* - * This class is a provider for Weatherbit, - * see https://www.weatherbit.io/ +/** + * Weatherbit weather provider + * See: https://www.weatherbit.io/ */ -WeatherProvider.register("weatherbit", { +class WeatherbitProvider { + constructor (config) { + this.config = { + apiBase: "https://api.weatherbit.io/v2.0", + apiKey: "", + lat: 0, + lon: 0, + type: "current", + updateInterval: 10 * 60 * 1000, + ...config + }; - /* - * Set the name of the provider. - * Not strictly required, but helps for debugging. - */ - providerName: "Weatherbit", - - // Set the default config properties that is specific to this provider - defaults: { - apiBase: "https://api.weatherbit.io/v2.0", - apiKey: "", - lat: 0, - lon: 0 - }, - - fetchedLocation () { - return this.fetchedLocationName || ""; - }, - - fetchCurrentWeather () { - this.fetchData(this.getUrl()) - .then((data) => { - if (!data || !data.data[0] || typeof data.data[0].temp === "undefined") { - // No usable data? - return; - } + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + } + + setCallbacks (onDataCallback, onErrorCallback) { + this.onDataCallback = onDataCallback; + this.onErrorCallback = onErrorCallback; + } + + async initialize () { + if (!this.config.apiKey || this.config.apiKey === "YOUR_API_KEY_HERE") { + Log.error("[weatherbit] No API key configured"); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Weatherbit API key required. Get one at https://www.weatherbit.io/", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; + } + + this.#initializeFetcher(); + } + + #initializeFetcher () { + const url = this.#getUrl(); - const currentWeather = this.generateWeatherDayFromCurrentWeather(data); - this.setCurrentWeather(currentWeather); - }) - .catch(function (request) { - Log.error("[weatherprovider.weatherbit] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - fetchWeatherForecast () { - this.fetchData(this.getUrl()) - .then((data) => { - if (!data || !data.data) { - // No usable data? - return; + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + headers: { + Accept: "application/json" + }, + logContext: "weatherprovider.weatherbit" + }); + + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + this.#handleResponse(data); + } catch (error) { + Log.error("[weatherbit] Parse error:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } + } + }); - const forecast = this.generateWeatherObjectsFromForecast(data.data); - this.setWeatherForecast(forecast); + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } - this.fetchedLocationName = `${data.city_name}, ${data.state_code}`; - }) - .catch(function (request) { - Log.error("[weatherprovider.weatherbit] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, + #getUrl () { + const endpoint = this.#getWeatherEndpoint(); + return `${this.config.apiBase}${endpoint}?lat=${this.config.lat}&lon=${this.config.lon}&units=M&key=${this.config.apiKey}`; + } - /** - * Overrides method for setting config to check if endpoint is correct for hourly - * @param {object} config The configuration object - */ - setConfig (config) { - this.config = config; - if (!this.config.weatherEndpoint) { - switch (this.config.type) { - case "hourly": - this.config.weatherEndpoint = "/forecast/hourly"; - break; - case "daily": - case "forecast": - this.config.weatherEndpoint = "/forecast/daily"; - break; - case "current": - this.config.weatherEndpoint = "/current"; - break; - default: - Log.error("[weatherprovider.weatherbit] weatherEndpoint not configured and could not resolve it based on type"); + #getWeatherEndpoint () { + switch (this.config.type) { + case "hourly": + return "/forecast/hourly"; + case "daily": + case "forecast": + return "/forecast/daily"; + case "current": + default: + return "/current"; + } + } + + #handleResponse (data) { + if (!data || !data.data || data.data.length === 0) { + Log.error("[weatherbit] No usable data received"); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "No usable data in API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); } + return; + } + + let weatherData = null; + + switch (this.config.type) { + case "current": + weatherData = this.#generateCurrent(data); + break; + case "forecast": + case "daily": + weatherData = this.#generateDaily(data); + break; + case "hourly": + weatherData = this.#generateHourly(data); + break; + default: + Log.error(`[weatherbit] Unknown weather type: ${this.config.type}`); + break; + } + + if (weatherData && this.onDataCallback) { + this.onDataCallback(weatherData); } - }, + } - // Create a URL from the config and base URL. - getUrl () { - return `${this.config.apiBase}${this.config.weatherEndpoint}?lat=${this.config.lat}&lon=${this.config.lon}&units=M&key=${this.config.apiKey}`; - }, + #generateCurrent (data) { + if (!data.data[0] || typeof data.data[0].temp === "undefined") { + return null; + } - // Implement WeatherDay generator. - generateWeatherDayFromCurrentWeather (currentWeatherData) { - //Calculate TZ Offset and invert to convert Sunrise/Sunset times to Local - const d = new Date(); - let tzOffset = d.getTimezoneOffset(); - tzOffset = tzOffset * -1; + const current = data.data[0]; - const currentWeather = new WeatherObject(); + const weather = { + date: new Date(current.ts * 1000), + temperature: parseFloat(current.temp), + humidity: parseFloat(current.rh), + windSpeed: parseFloat(current.wind_spd), + windFromDirection: current.wind_dir || null, + weatherType: this.#convertWeatherType(current.weather.icon), + sunrise: null, + sunset: null + }; - currentWeather.date = moment.unix(currentWeatherData.data[0].ts); - currentWeather.humidity = parseFloat(currentWeatherData.data[0].rh); - currentWeather.temperature = parseFloat(currentWeatherData.data[0].temp); - currentWeather.windSpeed = parseFloat(currentWeatherData.data[0].wind_spd); - currentWeather.windFromDirection = currentWeatherData.data[0].wind_dir; - currentWeather.weatherType = this.convertWeatherType(currentWeatherData.data[0].weather.icon); - currentWeather.sunrise = moment(currentWeatherData.data[0].sunrise, "HH:mm").add(tzOffset, "m"); - currentWeather.sunset = moment(currentWeatherData.data[0].sunset, "HH:mm").add(tzOffset, "m"); + // Parse sunrise/sunset from HH:mm format (already in local time) + if (current.sunrise) { + const [hours, minutes] = current.sunrise.split(":"); + const sunrise = new Date(current.ts * 1000); + sunrise.setHours(parseInt(hours), parseInt(minutes), 0, 0); + weather.sunrise = sunrise; + } - this.fetchedLocationName = `${currentWeatherData.data[0].city_name}, ${currentWeatherData.data[0].state_code}`; + if (current.sunset) { + const [hours, minutes] = current.sunset.split(":"); + const sunset = new Date(current.ts * 1000); + sunset.setHours(parseInt(hours), parseInt(minutes), 0, 0); + weather.sunset = sunset; + } - return currentWeather; - }, + return weather; + } - generateWeatherObjectsFromForecast (forecasts) { + #generateDaily (data) { const days = []; - for (const forecast of forecasts) { - const weather = new WeatherObject(); + for (const forecast of data.data) { + days.push({ + date: new Date(forecast.datetime), + minTemperature: forecast.min_temp !== undefined ? parseFloat(forecast.min_temp) : null, + maxTemperature: forecast.max_temp !== undefined ? parseFloat(forecast.max_temp) : null, + precipitationAmount: forecast.precip !== undefined ? parseFloat(forecast.precip) : 0, + precipitationProbability: forecast.pop !== undefined ? parseFloat(forecast.pop) : null, + weatherType: this.#convertWeatherType(forecast.weather.icon) + }); + } + + return days; + } - weather.date = moment(forecast.datetime, "YYYY-MM-DD"); - weather.minTemperature = forecast.min_temp; - weather.maxTemperature = forecast.max_temp; - weather.precipitationAmount = forecast.precip; - weather.precipitationProbability = forecast.pop; - weather.weatherType = this.convertWeatherType(forecast.weather.icon); + #generateHourly (data) { + const hours = []; - days.push(weather); + for (const forecast of data.data) { + hours.push({ + date: new Date(forecast.timestamp_local), + temperature: forecast.temp !== undefined ? parseFloat(forecast.temp) : null, + precipitationAmount: forecast.precip !== undefined ? parseFloat(forecast.precip) : 0, + precipitationProbability: forecast.pop !== undefined ? parseFloat(forecast.pop) : null, + windSpeed: forecast.wind_spd !== undefined ? parseFloat(forecast.wind_spd) : null, + windFromDirection: forecast.wind_dir || null, + weatherType: this.#convertWeatherType(forecast.weather.icon) + }); } - return days; - }, + return hours; + } - // Map icons from Dark Sky to our icons. - convertWeatherType (weatherType) { + /** + * Convert Weatherbit icon codes to weathericons.css icons + * See: https://www.weatherbit.io/api/codes + * @param {string} weatherType - Weatherbit icon code + * @returns {string|null} Weathericons.css icon name or null + */ + #convertWeatherType (weatherType) { const weatherTypes = { t01d: "day-thunderstorm", t01n: "night-alt-thunderstorm", @@ -148,20 +221,20 @@ WeatherProvider.register("weatherbit", { d01n: "night-alt-sprinkle", d02d: "day-sprinkle", d02n: "night-alt-sprinkle", - d03d: "day-shower", - d03n: "night-alt-shower", - r01d: "day-shower", - r01n: "night-alt-shower", + d03d: "day-showers", + d03n: "night-alt-showers", + r01d: "day-showers", + r01n: "night-alt-showers", r02d: "day-rain", r02n: "night-alt-rain", r03d: "day-rain", r03n: "night-alt-rain", r04d: "day-sprinkle", r04n: "night-alt-sprinkle", - r05d: "day-shower", - r05n: "night-alt-shower", - r06d: "day-shower", - r06n: "night-alt-shower", + r05d: "day-showers", + r05n: "night-alt-showers", + r06d: "day-showers", + r06n: "night-alt-showers", f01d: "day-sleet", f01n: "night-alt-sleet", s01d: "day-snow", @@ -200,6 +273,20 @@ WeatherProvider.register("weatherbit", { u00n: "rain-mix" }; - return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; + return weatherTypes[weatherType] || null; + } + + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); + } + } + + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } } -}); +} + +module.exports = WeatherbitProvider; diff --git a/defaultmodules/weather/providers/weatherflow.js b/defaultmodules/weather/providers/weatherflow.js index 8e9fad6fd9..e4ba4a2006 100644 --- a/defaultmodules/weather/providers/weatherflow.js +++ b/defaultmodules/weather/providers/weatherflow.js @@ -1,123 +1,255 @@ -/* global WeatherProvider, WeatherObject, WeatherUtils */ +const Log = require("logger"); +const { convertKmhToMs } = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); -/* - * This class is a provider for Weatherflow. - * Note that the Weatherflow API does not provide snowfall. +/** + * WeatherFlow weather provider + * This class is a provider for WeatherFlow personal weather stations. + * Note that the WeatherFlow API does not provide snowfall. */ -WeatherProvider.register("weatherflow", { +class WeatherFlowProvider { + /** + * @param {object} config - Provider configuration + */ + constructor (config) { + this.config = config; + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + } - /* - * Set the name of the provider. - * Not strictly required, but helps for debugging + /** + * Set the callbacks for data and errors + * @param {(data: object) => void} onDataCallback - Called when new data is available + * @param {(error: object) => void} onErrorCallback - Called when an error occurs */ - providerName: "WeatherFlow", - - // Set the default config properties that is specific to this provider - defaults: { - apiBase: "https://swd.weatherflow.com/swd/rest/", - token: "", - stationid: "" - }, - - fetchCurrentWeather () { - this.fetchData(this.getUrl()) - .then((data) => { - const currentWeather = new WeatherObject(); - currentWeather.date = moment(); - - // Other available values: air_density, brightness, delta_t, dew_point, - // pressure_trend (i.e. rising/falling), sea_level_pressure, wind gust, and more. - - currentWeather.humidity = data.current_conditions.relative_humidity; - currentWeather.temperature = data.current_conditions.air_temperature; - currentWeather.feelsLikeTemp = data.current_conditions.feels_like; - currentWeather.windSpeed = WeatherUtils.convertWindToMs(data.current_conditions.wind_avg); - currentWeather.windFromDirection = data.current_conditions.wind_direction; - currentWeather.weatherType = this.convertWeatherType(data.current_conditions.icon); - currentWeather.uv_index = data.current_conditions.uv; - currentWeather.sunrise = moment.unix(data.forecast.daily[0].sunrise); - currentWeather.sunset = moment.unix(data.forecast.daily[0].sunset); - this.setCurrentWeather(currentWeather); - this.fetchedLocationName = data.location_name; - }) - .catch(function (request) { - Log.error("[weatherprovider.weatherflow] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - fetchWeatherForecast () { - this.fetchData(this.getUrl()) - .then((data) => { - const days = []; - - for (const forecast of data.forecast.daily) { - const weather = new WeatherObject(); - - weather.date = moment.unix(forecast.day_start_local); - weather.minTemperature = forecast.air_temp_low; - weather.maxTemperature = forecast.air_temp_high; - weather.precipitationProbability = forecast.precip_probability; - weather.weatherType = this.convertWeatherType(forecast.icon); - - // Must manually build UV and Precipitation from hourly - weather.precipitationAmount = 0.0; // This will sum up rain and snow - weather.precipitationUnits = "mm"; - weather.uv_index = 0; - - for (const hour of data.forecast.hourly) { - const hour_time = moment.unix(hour.time); - if (hour_time.day() === weather.date.day()) { // Iterate though until day is reached - // Get data from today - weather.uv_index = Math.max(weather.uv_index, hour.uv); - weather.precipitationAmount += (hour.precip ?? 0); - } else if (hour_time.diff(weather.date) >= 86400) { - break; // No more data to be found - } - } - days.push(weather); - } - this.setWeatherForecast(days); - this.fetchedLocationName = data.location_name; - }) - .catch(function (request) { - Log.error("[weatherprovider.weatherflow] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - fetchWeatherHourly () { - this.fetchData(this.getUrl()) - .then((data) => { - const hours = []; - for (const hour of data.forecast.hourly) { - const weather = new WeatherObject(); - - weather.date = moment.unix(hour.time); - weather.temperature = hour.air_temperature; - weather.feelsLikeTemp = hour.feels_like; - weather.humidity = hour.relative_humidity; - weather.windSpeed = hour.wind_avg; - weather.windFromDirection = hour.wind_direction; - weather.weatherType = this.convertWeatherType(hour.icon); - weather.precipitationProbability = hour.precip_probability; - weather.precipitationAmount = hour.precip; // NOTE: precipitation type is available - weather.precipitationUnits = "mm"; // Hardcoded via request, TODO: Add conversion - weather.uv_index = hour.uv; - - hours.push(weather); - if (hours.length >= 48) break; // 10 days of hours are available, best to trim down. + setCallbacks (onDataCallback, onErrorCallback) { + this.onDataCallback = onDataCallback; + this.onErrorCallback = onErrorCallback; + } + + /** + * Initialize the provider + */ + async initialize () { + if (!this.config.token || this.config.token === "YOUR_API_TOKEN_HERE") { + Log.error("[weatherflow] No API token configured. Get one at https://tempestwx.com/"); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "WeatherFlow API token required. Get one at https://tempestwx.com/", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; + } + + if (!this.config.stationid) { + Log.error("[weatherflow] No station ID configured"); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "WeatherFlow station ID required", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return; + } + + this.#initializeFetcher(); + } + + /** + * Initialize the HTTP fetcher + */ + #initializeFetcher () { + const url = this.#getUrl(); + + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + headers: { + "Cache-Control": "no-cache", + Accept: "application/json" + }, + logContext: "weatherprovider.weatherflow" + }); + + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + const processed = this.#processData(data); + this.onDataCallback(processed); + } catch (error) { + Log.error("[weatherflow] Failed to parse JSON:", error); + } + }); + + this.fetcher.on("error", (errorInfo) => { + // HTTPFetcher already logged the error with logContext + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } + + /** + * Generate the URL for API requests + * @returns {string} The API URL + */ + #getUrl () { + const base = this.config.apiBase || "https://swd.weatherflow.com/swd/rest/"; + return `${base}better_forecast?station_id=${this.config.stationid}&units_temp=c&units_wind=kph&units_pressure=mb&units_precip=mm&units_distance=km&token=${this.config.token}`; + } + + /** + * Process the raw API data + * @param {object} data - Raw API response + * @returns {object} Processed weather data + */ + #processData (data) { + try { + let weatherData; + if (this.config.type === "current") { + weatherData = this.#generateCurrent(data); + } else if (this.config.type === "hourly") { + weatherData = this.#generateHourly(data); + } else { + weatherData = this.#generateDaily(data); + } + + return weatherData; + } catch (error) { + Log.error("[weatherflow] Data processing error:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to process weather data", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + return null; + } + } + + /** + * Generate current weather data + * @param {object} data - API response data + * @returns {object} Current weather object + */ + #generateCurrent (data) { + if (!data || !data.current_conditions || !data.forecast || !Array.isArray(data.forecast.daily) || data.forecast.daily.length === 0) { + Log.error("[weatherflow] Invalid current weather data structure"); + return null; + } + + const current = data.current_conditions; + const daily = data.forecast.daily[0]; + + const weather = { + date: new Date(), + 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, + weatherType: this.#convertWeatherType(current.icon), + uvIndex: current.uv || null, + sunrise: daily.sunrise ? new Date(daily.sunrise * 1000) : null, + sunset: daily.sunset ? new Date(daily.sunset * 1000) : null + }; + + return weather; + } + + /** + * Generate forecast data + * @param {object} data - API response data + * @returns {Array} Array of forecast objects + */ + #generateDaily (data) { + if (!data || !data.forecast || !Array.isArray(data.forecast.daily) || !Array.isArray(data.forecast.hourly)) { + Log.error("[weatherflow] Invalid forecast data structure"); + return []; + } + + const days = []; + + 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, + weatherType: this.#convertWeatherType(forecast.icon), + precipitationAmount: 0.0, + precipitationUnits: "mm", + uvIndex: 0 + }; + + // Build UV and precipitation from hourly data + for (const hour of data.forecast.hourly) { + const hourDate = new Date(hour.time * 1000); + const forecastDate = new Date(forecast.day_start_local * 1000); + + // Compare year, month, and day to ensure correct matching across month boundaries + 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; + } else if (hourDate > forecastDate) { + // Check if we've moved to the next day + const diffMs = hourDate - forecastDate; + if (diffMs >= 86400000) break; // 24 hours in ms } - this.setWeatherHourly(hours); - this.fetchedLocationName = data.location_name; - }) - .catch(function (request) { - Log.error("[weatherprovider.weatherflow] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - convertWeatherType (weatherType) { + } + + days.push(weather); + } + + return days; + } + + /** + * Generate hourly forecast data + * @param {object} data - API response data + * @returns {Array} Array of hourly forecast objects + */ + #generateHourly (data) { + if (!data || !data.forecast || !Array.isArray(data.forecast.hourly)) { + Log.error("[weatherflow] Invalid hourly data structure"); + return []; + } + + const hours = []; + + 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, + windSpeed: hour.wind_avg != null ? convertKmhToMs(hour.wind_avg) : null, + windFromDirection: hour.wind_direction || null, + weatherType: this.#convertWeatherType(hour.icon), + precipitationProbability: hour.precip_probability || null, + precipitationAmount: hour.precip || 0, + precipitationUnits: "mm", + uvIndex: hour.uv || null + }; + + hours.push(weather); + + // WeatherFlow provides 10 days of hourly data, trim to 48 hours + if (hours.length >= 48) break; + } + + return hours; + } + + /** + * Convert weather icon type + * @param {string} weatherType - WeatherFlow icon code + * @returns {string} Weather icon CSS class + */ + #convertWeatherType (weatherType) { const weatherTypes = { "clear-day": "day-sunny", "clear-night": "night-clear", @@ -140,11 +272,26 @@ WeatherProvider.register("weatherflow", { windy: "strong-wind" }; - return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; - }, + return weatherTypes[weatherType] || null; + } + + /** + * Start fetching data + */ + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); + } + } - // Create a URL from the config and base URL. - getUrl () { - return `${this.config.apiBase}better_forecast?station_id=${this.config.stationid}&units_temp=c&units_wind=kph&units_pressure=mb&units_precip=mm&units_distance=km&token=${this.config.token}`; + /** + * Stop fetching data + */ + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } } -}); +} + +module.exports = WeatherFlowProvider; diff --git a/defaultmodules/weather/providers/weathergov.js b/defaultmodules/weather/providers/weathergov.js index 7dae337b22..691b81045d 100644 --- a/defaultmodules/weather/providers/weathergov.js +++ b/defaultmodules/weather/providers/weathergov.js @@ -1,369 +1,404 @@ -/* global WeatherProvider, WeatherObject, WeatherUtils */ +const Log = require("logger"); +const { getSunTimes, isDayTime, getDateString, convertKmhToMs, cardinalToDegrees } = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); -/* - * Provider: weather.gov +/** + * Server-side weather provider for Weather.gov (US National Weather Service) + * Note: Only works for US locations, no API key required * https://weather-gov.github.io/api/general-faqs - * - * This class is a provider for weather.gov. - * Note that this is only for US locations (lat and lon) and does not require an API key - * Since it is free, there are some items missing - like sunrise, sunset */ +class WeatherGovProvider { + constructor (config) { + this.config = { + apiBase: "https://api.weather.gov/points/", + lat: 0, + lon: 0, + type: "current", + updateInterval: 10 * 60 * 1000, + ...config + }; + + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + this.locationName = null; + this.initRetryCount = 0; + this.initRetryTimer = null; + + // Weather.gov specific URLs (fetched during initialization) + this.forecastURL = null; + this.forecastHourlyURL = null; + this.forecastGridDataURL = null; + this.observationStationsURL = null; + this.stationObsURL = null; + } -WeatherProvider.register("weathergov", { - - /* - * Set the name of the provider. - * This isn't strictly necessary, since it will fallback to the provider identifier - * But for debugging (and future alerts) it would be nice to have the real name. - */ - providerName: "Weather.gov", - - // Set the default config properties that is specific to this provider - defaults: { - apiBase: "https://api.weather.gov/points/", - lat: 0, - lon: 0 - }, - - // Flag all needed URLs availability - configURLs: false, - - //This API has multiple urls involved - forecastURL: "tbd", - forecastHourlyURL: "tbd", - forecastGridDataURL: "tbd", - observationStationsURL: "tbd", - stationObsURL: "tbd", - - // Called to set the config, this config is the same as the weather module's config. - setConfig (config) { - this.config = config; - this.fetchWxGovURLs(this.config); - }, - - // This returns the name of the fetched location or an empty string. - fetchedLocation () { - return this.fetchedLocationName || ""; - }, - - // Overwrite the fetchCurrentWeather method. - fetchCurrentWeather () { - if (!this.configURLs) { - Log.info("[weatherprovider.weathergov] fetchCurrentWeather: fetch wx waiting on config URLs"); - return; + async initialize () { + // Add small random delay to prevent all instances from starting simultaneously + // This reduces parallel DNS lookups which can cause EAI_AGAIN errors + const staggerDelay = Math.random() * 3000; // 0-3 seconds + await new Promise((resolve) => setTimeout(resolve, staggerDelay)); + + try { + await this.#fetchWeatherGovURLs(); + this.#initializeFetcher(); + this.initRetryCount = 0; // Reset on success + } catch (error) { + const errorInfo = this.#categorizeError(error); + Log.error(`[weathergov] Initialization failed: ${errorInfo.message}`); + + // Retry on temporary errors (DNS, timeout, network) + if (errorInfo.isRetryable && this.initRetryCount < 5) { + this.initRetryCount++; + const delay = HTTPFetcher.calculateBackoffDelay(this.initRetryCount); + Log.info(`[weathergov] Will retry initialization in ${Math.round(delay / 1000)}s (attempt ${this.initRetryCount}/5)`); + this.initRetryTimer = setTimeout(() => this.initialize(), delay); + } else if (this.onErrorCallback) { + this.onErrorCallback({ + message: errorInfo.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } } - this.fetchData(this.stationObsURL) - .then((data) => { - if (!data || !data.properties) { - // Did not receive usable new data. - return; - } - const currentWeather = this.generateWeatherObjectFromCurrentWeather(data.properties); - this.setCurrentWeather(currentWeather); - }) - .catch(function (request) { - Log.error("[weatherprovider.weathergov] Could not load station obs data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - // Overwrite the fetchWeatherForecast method. - fetchWeatherForecast () { - if (!this.configURLs) { - Log.info("[weatherprovider.weathergov] fetchWeatherForecast: fetch wx waiting on config URLs"); - return; + } + + #categorizeError (error) { + const cause = error.cause || error; + const code = cause.code || ""; + + if (code === "EAI_AGAIN" || code === "ENOTFOUND") { + return { + message: "DNS lookup failed for api.weather.gov - check your internet connection", + isRetryable: true + }; } - this.fetchData(this.forecastURL) - .then((data) => { - if (!data || !data.properties || !data.properties.periods || !data.properties.periods.length) { - // Did not receive usable new data. - return; - } - const forecast = this.generateWeatherObjectsFromForecast(data.properties.periods); - this.setWeatherForecast(forecast); - }) - .catch(function (request) { - Log.error("[weatherprovider.weathergov] Could not load forecast hourly data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - // Overwrite the fetchWeatherHourly method. - fetchWeatherHourly () { - if (!this.configURLs) { - Log.info("[weatherprovider.weathergov] fetchWeatherHourly: fetch wx waiting on config URLs"); - return; + if (code === "ETIMEDOUT" || code === "ECONNREFUSED" || code === "ECONNRESET") { + return { + message: `Network error: ${code} - api.weather.gov may be temporarily unavailable`, + isRetryable: true + }; } - this.fetchData(this.forecastHourlyURL) - .then((data) => { - if (!data) { - - /* - * Did not receive usable new data. - * Maybe this needs a better check? - */ - return; - } - const hourly = this.generateWeatherObjectsFromHourly(data.properties.periods); - this.setWeatherHourly(hourly); - }) - .catch(function (request) { - Log.error("[weatherprovider.weathergov] Could not load data ... ", request); - }) - .finally(() => this.updateAvailable()); - }, - - /** Weather.gov Specific Methods - These are not part of the default provider methods */ - - /* - * Get specific URLs - */ - fetchWxGovURLs (config) { - this.fetchData(`${config.apiBase}/${config.lat},${config.lon}`) - .then((data) => { - if (!data || !data.properties) { - // points URL did not respond with usable data. - return; - } - this.fetchedLocationName = `${data.properties.relativeLocation.properties.city}, ${data.properties.relativeLocation.properties.state}`; - Log.log(`[weatherprovider.weathergov] Forecast location is ${this.fetchedLocationName}`); - this.forecastURL = `${data.properties.forecast}?units=si`; - this.forecastHourlyURL = `${data.properties.forecastHourly}?units=si`; - this.forecastGridDataURL = data.properties.forecastGridData; - this.observationStationsURL = data.properties.observationStations; - // with this URL, we chain another promise for the station obs URL - return this.fetchData(data.properties.observationStations); - }) - .then((obsData) => { - if (!obsData || !obsData.features) { - // obs station URL did not respond with usable data. - return; + if (error.name === "AbortError") { + return { + message: "Request timeout - api.weather.gov is responding slowly", + isRetryable: true + }; + } + + return { + message: error.message || "Unknown error", + isRetryable: false + }; + } + + setCallbacks (onData, onError) { + this.onDataCallback = onData; + this.onErrorCallback = onError; + } + + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); + } + } + + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); + } + if (this.initRetryTimer) { + clearTimeout(this.initRetryTimer); + this.initRetryTimer = null; + } + } + + async #fetchWeatherGovURLs () { + // Step 1: Get grid point data + const pointsUrl = `${this.config.apiBase}${this.config.lat},${this.config.lon}`; + + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 120000); // 120 second timeout - DNS can be slow + + try { + const pointsResponse = await fetch(pointsUrl, { + signal: controller.signal, + headers: { + "User-Agent": "MagicMirror", + Accept: "application/geo+json" } - this.stationObsURL = `${obsData.features[0].id}/observations/latest`; - }) - .catch((err) => { - Log.error("[weatherprovider.weathergov] fetchWxGovURLs error: ", err); - }) - .finally(() => { - // excellent, let's fetch some actual wx data - this.configURLs = true; - - // handle 'forecast' config, fall back to 'current' - if (config.type === "forecast") { - this.fetchWeatherForecast(); - } else if (config.type === "hourly") { - this.fetchWeatherHourly(); - } else { - this.fetchCurrentWeather(); + }); + + if (!pointsResponse.ok) { + throw new Error(`Failed to fetch grid point: HTTP ${pointsResponse.status}`); + } + + const pointsData = await pointsResponse.json(); + + if (!pointsData || !pointsData.properties) { + throw new Error("Invalid grid point data"); + } + + // Extract location name + const relLoc = pointsData.properties.relativeLocation?.properties; + if (relLoc) { + this.locationName = `${relLoc.city}, ${relLoc.state}`; + } + + // Store forecast URLs + this.forecastURL = `${pointsData.properties.forecast}?units=si`; + this.forecastHourlyURL = `${pointsData.properties.forecastHourly}?units=si`; + this.forecastGridDataURL = pointsData.properties.forecastGridData; + this.observationStationsURL = pointsData.properties.observationStations; + + // Step 2: Get observation station URL + const stationsResponse = await fetch(this.observationStationsURL, { + signal: controller.signal, + headers: { + "User-Agent": "MagicMirror", + Accept: "application/geo+json" } }); - }, - - /* - * Generate a WeatherObject based on hourlyWeatherInformation - * Weather.gov API uses specific units; API does not include choice of units - * ... object needs data in units based on config! - */ - generateWeatherObjectsFromHourly (forecasts) { - const days = []; - // variable for date - let weather = new WeatherObject(); - for (const forecast of forecasts) { - weather.date = moment(forecast.startTime.slice(0, 19)); - if (forecast.windSpeed.search(" ") < 0) { - weather.windSpeed = forecast.windSpeed; - } else { - weather.windSpeed = forecast.windSpeed.slice(0, forecast.windSpeed.search(" ")); + if (!stationsResponse.ok) { + throw new Error(`Failed to fetch observation stations: HTTP ${stationsResponse.status}`); } - weather.windSpeed = WeatherUtils.convertWindToMs(weather.windSpeed); - weather.windFromDirection = forecast.windDirection; - weather.temperature = forecast.temperature; - //assign probability of precipitation - if (forecast.probabilityOfPrecipitation.value === null) { - weather.precipitationProbability = 0; - } else { - weather.precipitationProbability = forecast.probabilityOfPrecipitation.value; + + const stationsData = await stationsResponse.json(); + + if (!stationsData || !stationsData.features || stationsData.features.length === 0) { + throw new Error("No observation stations found"); } - // use the forecast isDayTime attribute to help build the weatherType label - weather.weatherType = this.convertWeatherType(forecast.shortForecast, forecast.isDaytime); - days.push(weather); + this.stationObsURL = `${stationsData.features[0].id}/observations/latest`; + + Log.log(`[weathergov] Initialized for ${this.locationName}`); + } finally { + clearTimeout(timeoutId); + } + } - weather = new WeatherObject(); + #initializeFetcher () { + let url; + + switch (this.config.type) { + case "current": + url = this.stationObsURL; + break; + case "forecast": + case "daily": + url = this.forecastURL; + break; + case "hourly": + url = this.forecastHourlyURL; + break; + default: + url = this.stationObsURL; } - // push weather information to days array - days.push(weather); - return days; - }, - - /* - * Generate a WeatherObject based on currentWeatherInformation - * Weather.gov API uses specific units; API does not include choice of units - * ... object needs data in units based on config! - */ - generateWeatherObjectFromCurrentWeather (currentWeatherData) { - const currentWeather = new WeatherObject(); - - currentWeather.date = moment(currentWeatherData.timestamp); - currentWeather.temperature = currentWeatherData.temperature.value; - currentWeather.windSpeed = WeatherUtils.convertWindToMs(currentWeatherData.windSpeed.value); - currentWeather.windFromDirection = currentWeatherData.windDirection.value; - currentWeather.minTemperature = currentWeatherData.minTemperatureLast24Hours.value; - currentWeather.maxTemperature = currentWeatherData.maxTemperatureLast24Hours.value; - currentWeather.humidity = Math.round(currentWeatherData.relativeHumidity.value); - currentWeather.precipitationAmount = currentWeatherData.precipitationLastHour?.value ?? currentWeatherData.precipitationLast3Hours?.value; + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + timeout: 60000, // 60 seconds - weather.gov can be slow + headers: { + "User-Agent": "MagicMirror", + Accept: "application/geo+json", + "Cache-Control": "no-cache" + }, + logContext: "weatherprovider.weathergov" + }); + + this.fetcher.on("response", async (response) => { + try { + const data = await response.json(); + this.#handleResponse(data); + } catch (error) { + Log.error("[weathergov] Failed to parse JSON:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + } + }); + + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } + + #handleResponse (data) { + try { + let weatherData; + + switch (this.config.type) { + case "current": + if (!data.properties) { + throw new Error("Invalid current weather data"); + } + weatherData = this.#generateWeatherObjectFromCurrentWeather(data.properties); + break; + case "forecast": + case "daily": + if (!data.properties || !data.properties.periods) { + throw new Error("Invalid forecast data"); + } + weatherData = this.#generateWeatherObjectsFromForecast(data.properties.periods); + break; + case "hourly": + if (!data.properties || !data.properties.periods) { + throw new Error("Invalid hourly data"); + } + weatherData = this.#generateWeatherObjectsFromHourly(data.properties.periods); + break; + default: + throw new Error(`Unknown weather type: ${this.config.type}`); + } + + if (this.onDataCallback) { + this.onDataCallback(weatherData); + } + } catch (error) { + Log.error("[weathergov] Error processing weather data:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: error.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } + } + } + + #generateWeatherObjectFromCurrentWeather (currentWeatherData) { + const current = {}; + + current.date = new Date(currentWeatherData.timestamp); + current.temperature = currentWeatherData.temperature.value; + current.windSpeed = currentWeatherData.windSpeed.value; // Observations are already in m/s + current.windFromDirection = currentWeatherData.windDirection.value; + current.minTemperature = currentWeatherData.minTemperatureLast24Hours?.value; + current.maxTemperature = currentWeatherData.maxTemperatureLast24Hours?.value; + current.humidity = Math.round(currentWeatherData.relativeHumidity.value); + current.precipitationAmount = currentWeatherData.precipitationLastHour?.value ?? currentWeatherData.precipitationLast3Hours?.value; + + // Feels like temperature if (currentWeatherData.heatIndex.value !== null) { - currentWeather.feelsLikeTemp = currentWeatherData.heatIndex.value; + current.feelsLikeTemp = currentWeatherData.heatIndex.value; } else if (currentWeatherData.windChill.value !== null) { - currentWeather.feelsLikeTemp = currentWeatherData.windChill.value; + current.feelsLikeTemp = currentWeatherData.windChill.value; } else { - currentWeather.feelsLikeTemp = currentWeatherData.temperature.value; + current.feelsLikeTemp = currentWeatherData.temperature.value; } - // determine the sunrise/sunset times - not supplied in weather.gov data - currentWeather.updateSunTime(this.config.lat, this.config.lon); - - // update weatherType - currentWeather.weatherType = this.convertWeatherType(currentWeatherData.textDescription, currentWeather.isDayTime()); - - return currentWeather; - }, - - /* - * Generate WeatherObjects based on forecast information - */ - generateWeatherObjectsFromForecast (forecasts) { - return this.fetchForecastDaily(forecasts); - }, - - /* - * fetch forecast information for daily forecast. - */ - fetchForecastDaily (forecasts) { - // initial variable declaration + + // Calculate sunrise/sunset (not provided by weather.gov) + const { sunrise, sunset } = getSunTimes(current.date, this.config.lat, this.config.lon); + current.sunrise = sunrise; + current.sunset = sunset; + + // Determine if daytime + const isDay = isDayTime(current.date, current.sunrise, current.sunset); + current.weatherType = this.#convertWeatherType(currentWeatherData.textDescription, isDay); + + return current; + } + + #generateWeatherObjectsFromForecast (forecasts) { const days = []; - // variables for temperature range and rain let minTemp = []; let maxTemp = []; - // variable for date let date = ""; - let weather = new WeatherObject(); + let weather = {}; for (const forecast of forecasts) { - if (date !== moment(forecast.startTime).format("YYYY-MM-DD")) { - // calculate minimum/maximum temperature, specify rain amount - weather.minTemperature = Math.min.apply(null, minTemp); - weather.maxTemperature = Math.max.apply(null, maxTemp); - - // push weather information to days array - days.push(weather); - // create new weather-object - weather = new WeatherObject(); + const forecastDate = new Date(forecast.startTime); + const dateStr = getDateString(forecastDate); + + if (date !== dateStr) { + // New day + if (date !== "") { + weather.minTemperature = Math.min(...minTemp); + weather.maxTemperature = Math.max(...maxTemp); + days.push(weather); + } + weather = {}; minTemp = []; maxTemp = []; - //assign probability of precipitation - if (forecast.probabilityOfPrecipitation.value === null) { - weather.precipitationProbability = 0; - } else { - weather.precipitationProbability = forecast.probabilityOfPrecipitation.value; - } - - // set new date - date = moment(forecast.startTime).format("YYYY-MM-DD"); + date = dateStr; - // specify date - weather.date = moment(forecast.startTime); - - // use the forecast isDayTime attribute to help build the weatherType label - weather.weatherType = this.convertWeatherType(forecast.shortForecast, forecast.isDaytime); + weather.date = forecastDate; + weather.precipitationProbability = forecast.probabilityOfPrecipitation?.value ?? 0; + weather.weatherType = this.#convertWeatherType(forecast.shortForecast, forecast.isDaytime); } - if (moment(forecast.startTime).format("H") >= 8 && moment(forecast.startTime).format("H") <= 17) { - weather.weatherType = this.convertWeatherType(forecast.shortForecast, forecast.isDaytime); + // Update weather type for daytime hours (8am-5pm) + const hour = forecastDate.getHours(); + if (hour >= 8 && hour <= 17) { + weather.weatherType = this.#convertWeatherType(forecast.shortForecast, forecast.isDaytime); } - /* - * the same day as before - * add values from forecast to corresponding variables - */ minTemp.push(forecast.temperature); maxTemp.push(forecast.temperature); } - /* - * last day - * calculate minimum/maximum temperature - */ - weather.minTemperature = Math.min.apply(null, minTemp); - weather.maxTemperature = Math.max.apply(null, maxTemp); + // Last day + if (date !== "") { + weather.minTemperature = Math.min(...minTemp); + weather.maxTemperature = Math.max(...maxTemp); + days.push(weather); + } - // push weather information to days array - days.push(weather); - return days.slice(1); - }, + return days.slice(1); // Skip first incomplete day + } - /* - * Convert the icons to a more usable name. - */ - convertWeatherType (weatherType, isDaytime) { + #generateWeatherObjectsFromHourly (forecasts) { + const hours = []; - /* - * https://w1.weather.gov/xml/current_obs/weather.php - * There are way too many types to create, so lets just look for certain strings - */ + for (const forecast of forecasts) { + const weather = {}; - if (weatherType.includes("Cloudy") || weatherType.includes("Partly")) { - if (isDaytime) { - return "day-cloudy"; - } + weather.date = new Date(forecast.startTime); - return "night-cloudy"; - } else if (weatherType.includes("Overcast")) { - if (isDaytime) { - return "cloudy"; + // Parse wind speed + const windSpeedStr = forecast.windSpeed; + let windSpeed = windSpeedStr; + if (windSpeedStr.includes(" ")) { + windSpeed = windSpeedStr.split(" ")[0]; } + weather.windSpeed = convertKmhToMs(parseFloat(windSpeed)); + weather.windFromDirection = cardinalToDegrees(forecast.windDirection); + weather.temperature = forecast.temperature; + weather.precipitationProbability = forecast.probabilityOfPrecipitation?.value ?? 0; + weather.weatherType = this.#convertWeatherType(forecast.shortForecast, forecast.isDaytime); + + hours.push(weather); + } + + return hours; + } + + #convertWeatherType (weatherType, isDaytime) { + // https://w1.weather.gov/xml/current_obs/weather.php - return "night-cloudy"; + if (weatherType.includes("Cloudy") || weatherType.includes("Partly")) { + return isDaytime ? "day-cloudy" : "night-cloudy"; + } else if (weatherType.includes("Overcast")) { + return isDaytime ? "cloudy" : "night-cloudy"; } else if (weatherType.includes("Freezing") || weatherType.includes("Ice")) { return "rain-mix"; } else if (weatherType.includes("Snow")) { - if (isDaytime) { - return "snow"; - } - - return "night-snow"; + return isDaytime ? "snow" : "night-snow"; } else if (weatherType.includes("Thunderstorm")) { - if (isDaytime) { - return "thunderstorm"; - } - - return "night-thunderstorm"; + return isDaytime ? "thunderstorm" : "night-thunderstorm"; } else if (weatherType.includes("Showers")) { - if (isDaytime) { - return "showers"; - } - - return "night-showers"; + return isDaytime ? "showers" : "night-showers"; } else if (weatherType.includes("Rain") || weatherType.includes("Drizzle")) { - if (isDaytime) { - return "rain"; - } - - return "night-rain"; + return isDaytime ? "rain" : "night-rain"; } else if (weatherType.includes("Breezy") || weatherType.includes("Windy")) { - if (isDaytime) { - return "cloudy-windy"; - } - - return "night-alt-cloudy-windy"; + return isDaytime ? "cloudy-windy" : "night-alt-cloudy-windy"; } else if (weatherType.includes("Fair") || weatherType.includes("Clear") || weatherType.includes("Few") || weatherType.includes("Sunny")) { - if (isDaytime) { - return "day-sunny"; - } - - return "night-clear"; + return isDaytime ? "day-sunny" : "night-clear"; } else if (weatherType.includes("Dust") || weatherType.includes("Sand")) { return "dust"; } else if (weatherType.includes("Fog")) { @@ -376,4 +411,6 @@ WeatherProvider.register("weathergov", { return null; } -}); +} + +module.exports = WeatherGovProvider; diff --git a/defaultmodules/weather/providers/yr.js b/defaultmodules/weather/providers/yr.js index d5a6cb6d5c..3a4b4b0697 100644 --- a/defaultmodules/weather/providers/yr.js +++ b/defaultmodules/weather/providers/yr.js @@ -1,623 +1,467 @@ -/* global WeatherProvider, WeatherObject */ +const Log = require("logger"); +const { formatTimezoneOffset, getDateString, validateCoordinates } = require("../provider-utils"); +const HTTPFetcher = require("#http_fetcher"); -/* - * This class is a provider for Yr.no, a norwegian weather service. +/** + * Server-side weather provider for Yr.no (Norwegian Meteorological Institute) * Terms of service: https://developer.yr.no/doc/TermsOfService/ + * + * Note: Minimum update interval is 10 minutes (600000 ms) per API terms */ -WeatherProvider.register("yr", { - providerName: "Yr", - - // Set the default config properties that is specific to this provider - defaults: { - useCorsProxy: true, - apiBase: "https://api.met.no/weatherapi", - forecastApiVersion: "2.0", - sunriseApiVersion: "3.0", - altitude: 0, - currentForecastHours: 1 //1, 6 or 12 - }, +class YrProvider { + constructor (config) { + this.config = { + apiBase: "https://api.met.no/weatherapi", + forecastApiVersion: "2.0", + sunriseApiVersion: "3.0", + altitude: 0, + lat: 0, + lon: 0, + currentForecastHours: 1, // 1, 6 or 12 + type: "current", + updateInterval: 10 * 60 * 1000, // 10 minutes minimum + ...config + }; - start () { - if (typeof Storage === "undefined") { - //local storage unavailable - Log.error("[weatherprovider.yr] The Yr weather provider requires local storage."); - throw new Error("Local storage not available"); - } + // Enforce 10 minute minimum per API terms if (this.config.updateInterval < 600000) { - Log.warn("[weatherprovider.yr] The Yr weather provider requires a minimum update interval of 10 minutes (600 000 ms). The configuration has been adjusted to meet this requirement."); - this.delegate.config.updateInterval = 600000; + Log.warn("[yr] Minimum update interval is 10 minutes (600000 ms). Adjusting configuration."); + this.config.updateInterval = 600000; } - Log.info(`[weatherprovider.yr] ${this.providerName} started.`); - }, - - fetchCurrentWeather () { - this.getCurrentWeather() - .then((currentWeather) => { - this.setCurrentWeather(currentWeather); - this.updateAvailable(); - }) - .catch((error) => { - Log.error("[weatherprovider.yr] fetchCurrentWeather error:", error); - this.updateAvailable(); - }); - }, - async getCurrentWeather () { - const [weatherData, stellarData] = await Promise.all([this.getWeatherData(), this.getStellarData()]); - if (!stellarData) { - Log.warn("[weatherprovider.yr] No stellar data available."); - } - if (!weatherData.properties.timeseries || !weatherData.properties.timeseries[0]) { - Log.error("[weatherprovider.yr] No weather data available."); - return; - } - const currentTime = moment(); - let forecast = weatherData.properties.timeseries[0]; - let closestTimeInPast = currentTime.diff(moment(forecast.time)); - for (const forecastTime of weatherData.properties.timeseries) { - const comparison = currentTime.diff(moment(forecastTime.time)); - if (0 < comparison && comparison < closestTimeInPast) { - closestTimeInPast = comparison; - forecast = forecastTime; - } - } - const forecastXHours = this.getForecastForXHoursFrom(forecast.data); - forecast.weatherType = this.convertWeatherType(forecastXHours.summary.symbol_code, forecast.time); - forecast.precipitationAmount = forecastXHours.details?.precipitation_amount; - forecast.precipitationProbability = forecastXHours.details?.probability_of_precipitation; - forecast.minTemperature = forecastXHours.details?.air_temperature_min; - forecast.maxTemperature = forecastXHours.details?.air_temperature_max; - return this.getWeatherDataFrom(forecast, stellarData, weatherData.properties.meta.units); - }, - - getWeatherData () { - return new Promise((resolve, reject) => { - - /* - * If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. - * This is to avoid multiple similar calls to the API. - */ - let shouldWait = localStorage.getItem("yrIsFetchingWeatherData"); - if (shouldWait) { - const checkForGo = setInterval(function () { - shouldWait = localStorage.getItem("yrIsFetchingWeatherData"); - }, 100); - setTimeout(function () { - clearInterval(checkForGo); - shouldWait = false; - }, 5000); //Assume other fetch finished but failed to remove lock - const attemptFetchWeather = setInterval(() => { - if (!shouldWait) { - clearInterval(checkForGo); - clearInterval(attemptFetchWeather); - this.getWeatherDataFromYrOrCache(resolve, reject); - } - }, 100); - } else { - this.getWeatherDataFromYrOrCache(resolve, reject); - } - }); - }, - - getWeatherDataFromYrOrCache (resolve, reject) { - localStorage.setItem("yrIsFetchingWeatherData", "true"); - - let weatherData = this.getWeatherDataFromCache(); - if (this.weatherDataIsValid(weatherData)) { - localStorage.removeItem("yrIsFetchingWeatherData"); - Log.debug("[weatherprovider.yr] Weather data found in cache."); - resolve(weatherData); - } else { - this.getWeatherDataFromYr(weatherData?.downloadedAt) - .then((weatherData) => { - Log.debug("[weatherprovider.yr] Got weather data from yr."); - let data; - if (weatherData) { - this.cacheWeatherData(weatherData); - data = weatherData; - } else { - //Undefined if unchanged - data = this.getWeatherDataFromCache(); - } - resolve(data); - }) - .catch((err) => { - Log.error("[weatherprovider.yr] getWeatherDataFromYr error: ", err); - if (weatherData) { - Log.warn("[weatherprovider.yr] Using outdated cached weather data."); - resolve(weatherData); - } else { - reject("Unable to get weather data from Yr."); - } - }) - .finally(() => { - localStorage.removeItem("yrIsFetchingWeatherData"); - }); + this.fetcher = null; + this.onDataCallback = null; + this.onErrorCallback = null; + this.locationName = null; + + // Cache for sunrise/sunset data + this.stellarData = null; + this.stellarDataDate = null; + + // Cache for weather data (If-Modified-Since support) + this.weatherCache = { + data: null, + lastModified: null, + expires: null + }; + } + + async initialize () { + // Yr.no requires max 4 decimal places + validateCoordinates(this.config, 4); + await this.#fetchStellarData(); + this.#initializeFetcher(); + } + + setCallbacks (onData, onError) { + this.onDataCallback = onData; + this.onErrorCallback = onError; + } + + start () { + if (this.fetcher) { + this.fetcher.startPeriodicFetch(); } - }, - - weatherDataIsValid (weatherData) { - return ( - weatherData - && weatherData.timeout - && 0 < moment(weatherData.timeout).diff(moment()) - && (!weatherData.geometry || !weatherData.geometry.coordinates || !weatherData.geometry.coordinates.length < 2 || (weatherData.geometry.coordinates[0] === this.config.lat && weatherData.geometry.coordinates[1] === this.config.lon)) - ); - }, - - getWeatherDataFromCache () { - const weatherData = localStorage.getItem("weatherData"); - if (weatherData) { - return JSON.parse(weatherData); - } else { - return undefined; + } + + stop () { + if (this.fetcher) { + this.fetcher.clearTimer(); } - }, + } + + async #fetchStellarData () { + const today = getDateString(new Date()); - getWeatherDataFromYr (currentDataFetchedAt) { - const requestHeaders = [{ name: "Accept", value: "application/json" }]; - if (currentDataFetchedAt) { - requestHeaders.push({ name: "If-Modified-Since", value: currentDataFetchedAt }); + // Check if we already have today's data + if (this.stellarDataDate === today && this.stellarData) { + return; } - const expectedResponseHeaders = ["expires", "date"]; - - return this.fetchData(this.getForecastUrl(), "json", requestHeaders, expectedResponseHeaders) - .then((data) => { - if (!data || !data.headers) return data; - data.timeout = data.headers.find((header) => header.name === "expires").value; - data.downloadedAt = data.headers.find((header) => header.name === "date").value; - data.headers = undefined; - return data; - }) - .catch((err) => { - Log.error("[weatherprovider.yr] Could not load weather data.", err); - throw new Error(err); + const url = this.#getSunriseUrl(); + + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); + + const response = await fetch(url, { + headers: { + "User-Agent": "MagicMirror", + Accept: "application/json" + }, + signal: controller.signal }); - }, - getConfigOptions () { - if (!this.config.lat) { - Log.error("[weatherprovider.yr] Latitude not provided."); - throw new Error("Latitude not provided."); - } - if (!this.config.lon) { - Log.error("[weatherprovider.yr] Longitude not provided."); - throw new Error("Longitude not provided."); + clearTimeout(timeoutId); + + if (!response.ok) { + Log.warn(`[yr] Could not fetch stellar data: HTTP ${response.status}`); + this.stellarDataDate = today; + } else { + // Parse and store the stellar data + const data = await response.json(); + // Transform single-day response into array format expected by #getStellarInfoForDate + if (data && data.properties) { + this.stellarData = [{ + date: data.when.interval[0], // ISO date string + sunrise: data.properties.sunrise, + sunset: data.properties.sunset + }]; + } + this.stellarDataDate = today; + } + } catch (error) { + Log.warn("[yr] Failed to fetch stellar data:", error); } + } - let lat = this.config.lat.toString(); - let lon = this.config.lon.toString(); - const altitude = this.config.altitude ?? 0; - return { lat, lon, altitude }; - }, + #initializeFetcher () { + const url = this.#getForecastUrl(); - getForecastUrl () { - let { lat, lon, altitude } = this.getConfigOptions(); + const headers = { + "User-Agent": "MagicMirror", + Accept: "application/json" + }; - if (lat.includes(".") && lat.split(".")[1].length > 4) { - Log.warn("[weatherprovider.yr] Latitude is too specific for weather data. Do not use more than four decimals. Trimming to maximum length."); - const latParts = lat.split("."); - lat = `${latParts[0]}.${latParts[1].substring(0, 4)}`; - } - if (lon.includes(".") && lon.split(".")[1].length > 4) { - Log.warn("[weatherprovider.yr] Longitude is too specific for weather data. Do not use more than four decimals. Trimming to maximum length."); - const lonParts = lon.split("."); - lon = `${lonParts[0]}.${lonParts[1].substring(0, 4)}`; + // Add If-Modified-Since header if we have cached data + if (this.weatherCache.lastModified) { + headers["If-Modified-Since"] = this.weatherCache.lastModified; } - return `${this.config.apiBase}/locationforecast/${this.config.forecastApiVersion}/complete?&altitude=${altitude}&lat=${lat}&lon=${lon}`; - }, - - cacheWeatherData (weatherData) { - localStorage.setItem("weatherData", JSON.stringify(weatherData)); - }, - - getStellarData () { - - /* - * If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. - * This is to avoid multiple similar calls to the API. - */ - return new Promise((resolve, reject) => { - let shouldWait = localStorage.getItem("yrIsFetchingStellarData"); - if (shouldWait) { - const checkForGo = setInterval(function () { - shouldWait = localStorage.getItem("yrIsFetchingStellarData"); - }, 100); - setTimeout(function () { - clearInterval(checkForGo); - shouldWait = false; - }, 5000); //Assume other fetch finished but failed to remove lock - const attemptFetchWeather = setInterval(() => { - if (!shouldWait) { - clearInterval(checkForGo); - clearInterval(attemptFetchWeather); - this.getStellarDataFromYrOrCache(resolve, reject); + this.fetcher = new HTTPFetcher(url, { + reloadInterval: this.config.updateInterval, + headers, + logContext: "weatherprovider.yr" + }); + + this.fetcher.on("response", async (response) => { + try { + // Handle 304 Not Modified - use cached data + if (response.status === 304) { + Log.log("[yr] Data not modified, using cache"); + if (this.weatherCache.data) { + this.#handleResponse(this.weatherCache.data, true); } - }, 100); - } else { - this.getStellarDataFromYrOrCache(resolve, reject); + return; + } + + const data = await response.json(); + + // Store cache headers + const lastModified = response.headers.get("Last-Modified"); + const expires = response.headers.get("Expires"); + + if (lastModified) { + this.weatherCache.lastModified = lastModified; + } + if (expires) { + this.weatherCache.expires = expires; + } + this.weatherCache.data = data; + + // Update headers for next request + if (lastModified && this.fetcher) { + this.fetcher.customHeaders["If-Modified-Since"] = lastModified; + } + + this.#handleResponse(data, false); + } catch (error) { + Log.error("[yr] Failed to parse JSON:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: "Failed to parse API response", + translationKey: "MODULE_ERROR_UNSPECIFIED" + }); + } } }); - }, - - getStellarDataFromYrOrCache (resolve, reject) { - localStorage.setItem("yrIsFetchingStellarData", "true"); - - let stellarData = this.getStellarDataFromCache(); - const today = moment().format("YYYY-MM-DD"); - const tomorrow = moment().add(1, "days").format("YYYY-MM-DD"); - if (stellarData && stellarData.today && stellarData.today.date === today && stellarData.tomorrow && stellarData.tomorrow.date === tomorrow) { - Log.debug("[weatherprovider.yr] Stellar data found in cache."); - localStorage.removeItem("yrIsFetchingStellarData"); - resolve(stellarData); - } else if (stellarData && stellarData.tomorrow && stellarData.tomorrow.date === today) { - Log.debug("[weatherprovider.yr] Stellar data for today found in cache, but not for tomorrow."); - stellarData.today = stellarData.tomorrow; - this.getStellarDataFromYr(tomorrow) - .then((data) => { - if (data) { - data.date = tomorrow; - stellarData.tomorrow = data; - this.cacheStellarData(stellarData); - resolve(stellarData); - } else { - reject(`No stellar data returned from Yr for ${tomorrow}`); - } - }) - .catch((err) => { - Log.error("[weatherprovider.yr] getStellarDataFromYr error: ", err); - reject(`Unable to get stellar data from Yr for ${tomorrow}`); - }) - .finally(() => { - localStorage.removeItem("yrIsFetchingStellarData"); - }); - } else { - this.getStellarDataFromYr(today, 2) - .then((stellarData) => { - if (stellarData) { - const data = { - today: stellarData - }; - data.tomorrow = Object.assign({}, data.today); - data.today.date = today; - data.tomorrow.date = tomorrow; - this.cacheStellarData(data); - resolve(data); - } else { - Log.error(`[weatherprovider.yr] Something went wrong when fetching stellar data. Responses: ${stellarData}`); - reject(stellarData); - } - }) - .catch((err) => { - Log.error("[weatherprovider.yr] getStellarDataFromYr error: ", err); - reject("Unable to get stellar data from Yr."); - }) - .finally(() => { - localStorage.removeItem("yrIsFetchingStellarData"); + + this.fetcher.on("error", (errorInfo) => { + if (this.onErrorCallback) { + this.onErrorCallback(errorInfo); + } + }); + } + + async #handleResponse (data, fromCache = false) { + try { + if (!data.properties || !data.properties.timeseries) { + throw new Error("Invalid weather data"); + } + + // Refresh stellar data if needed (new day or using cached weather data) + if (fromCache) { + await this.#fetchStellarData(); + } + + let weatherData; + + switch (this.config.type) { + case "current": + weatherData = this.#generateCurrentWeather(data); + break; + case "forecast": + case "daily": + weatherData = this.#generateForecast(data); + break; + case "hourly": + weatherData = this.#generateHourly(data); + break; + default: + throw new Error(`Unknown weather type: ${this.config.type}`); + } + + if (this.onDataCallback) { + this.onDataCallback(weatherData); + } + } catch (error) { + Log.error("[yr] Error processing weather data:", error); + if (this.onErrorCallback) { + this.onErrorCallback({ + message: error.message, + translationKey: "MODULE_ERROR_UNSPECIFIED" }); + } } - }, - - getStellarDataFromCache () { - const stellarData = localStorage.getItem("stellarData"); - if (stellarData) { - return JSON.parse(stellarData); - } else { - return undefined; - } - }, - - getStellarDataFromYr (date, days = 1) { - const requestHeaders = [{ name: "Accept", value: "application/json" }]; - return this.fetchData(this.getStellarDataUrl(date, days), "json", requestHeaders) - .then((data) => { - Log.debug("[weatherprovider.yr] Got stellar data from yr."); - return data; - }) - .catch((err) => { - Log.error("[weatherprovider.yr] Could not load weather data.", err); - throw new Error(err); - }); - }, + } - getStellarDataUrl (date, days) { - let { lat, lon, altitude } = this.getConfigOptions(); + #generateCurrentWeather (data) { + const now = new Date(); + const timeseries = data.properties.timeseries; - if (lat.includes(".") && lat.split(".")[1].length > 4) { - Log.warn("[weatherprovider.yr] Latitude is too specific for stellar data. Do not use more than four decimals. Trimming to maximum length."); - const latParts = lat.split("."); - lat = `${latParts[0]}.${latParts[1].substring(0, 4)}`; - } - if (lon.includes(".") && lon.split(".")[1].length > 4) { - Log.warn("[weatherprovider.yr] Longitude is too specific for stellar data. Do not use more than four decimals. Trimming to maximum length."); - const lonParts = lon.split("."); - lon = `${lonParts[0]}.${lonParts[1].substring(0, 4)}`; - } + // Find closest forecast in the past + let forecast = timeseries[0]; + let closestDiff = Math.abs(now - new Date(forecast.time)); - let utcOffset = moment().utcOffset() / 60; - let utcOffsetPrefix = "%2B"; - if (utcOffset < 0) { - utcOffsetPrefix = "-"; - } - utcOffset = Math.abs(utcOffset); - let minutes = "00"; - if (utcOffset % 1 !== 0) { - minutes = "30"; + for (const entry of timeseries) { + const entryTime = new Date(entry.time); + const diff = now - entryTime; + + if (diff > 0 && diff < closestDiff) { + closestDiff = diff; + forecast = entry; + } } - let hours = Math.floor(utcOffset).toString(); - if (hours.length < 2) { - hours = `0${hours}`; + + const forecastXHours = this.#getForecastForXHours(forecast.data); + const stellarInfo = this.#getStellarInfoForDate(new Date(forecast.time)); + + const current = {}; + current.date = new Date(forecast.time); + current.temperature = forecast.data.instant.details.air_temperature; + current.windSpeed = forecast.data.instant.details.wind_speed; + current.windFromDirection = forecast.data.instant.details.wind_from_direction; + current.humidity = forecast.data.instant.details.relative_humidity; + current.weatherType = this.#convertWeatherType( + forecastXHours.summary?.symbol_code, + stellarInfo ? this.#isDayTime(current.date, stellarInfo) : true + ); + current.precipitationAmount = forecastXHours.details?.precipitation_amount; + current.precipitationProbability = forecastXHours.details?.probability_of_precipitation; + current.minTemperature = forecastXHours.details?.air_temperature_min; + current.maxTemperature = forecastXHours.details?.air_temperature_max; + + if (stellarInfo) { + current.sunrise = new Date(stellarInfo.sunrise.time); + current.sunset = new Date(stellarInfo.sunset.time); } - return `${this.config.apiBase}/sunrise/${this.config.sunriseApiVersion}/sun?lat=${lat}&lon=${lon}&date=${date}&offset=${utcOffsetPrefix}${hours}%3A${minutes}`; - }, - - cacheStellarData (data) { - localStorage.setItem("stellarData", JSON.stringify(data)); - }, - - getWeatherDataFrom (forecast, stellarData, units) { - const weather = new WeatherObject(); - - weather.date = moment(forecast.time); - weather.windSpeed = forecast.data.instant.details.wind_speed; - weather.windFromDirection = forecast.data.instant.details.wind_from_direction; - weather.temperature = forecast.data.instant.details.air_temperature; - weather.minTemperature = forecast.minTemperature; - weather.maxTemperature = forecast.maxTemperature; - weather.weatherType = forecast.weatherType; - weather.humidity = forecast.data.instant.details.relative_humidity; - weather.precipitationAmount = forecast.precipitationAmount; - weather.precipitationProbability = forecast.precipitationProbability; - weather.precipitationUnits = units.precipitation_amount; - - weather.sunrise = stellarData?.today?.properties?.sunrise?.time; - weather.sunset = stellarData?.today?.properties?.sunset?.time; - - return weather; - }, - - convertWeatherType (weatherType, weatherTime) { - const weatherHour = moment(weatherTime).format("HH"); - - const weatherTypes = { - clearsky_day: "day-sunny", - clearsky_night: "night-clear", - clearsky_polartwilight: weatherHour < 14 ? "sunrise" : "sunset", - cloudy: "cloudy", - fair_day: "day-sunny-overcast", - fair_night: "night-alt-partly-cloudy", - fair_polartwilight: "day-sunny-overcast", - fog: "fog", - heavyrain: "rain", // Possibly raindrops or raindrop - heavyrainandthunder: "thunderstorm", - heavyrainshowers_day: "day-rain", - heavyrainshowers_night: "night-alt-rain", - heavyrainshowers_polartwilight: "day-rain", - heavyrainshowersandthunder_day: "day-thunderstorm", - heavyrainshowersandthunder_night: "night-alt-thunderstorm", - heavyrainshowersandthunder_polartwilight: "day-thunderstorm", - heavysleet: "sleet", - heavysleetandthunder: "day-sleet-storm", - heavysleetshowers_day: "day-sleet", - heavysleetshowers_night: "night-alt-sleet", - heavysleetshowers_polartwilight: "day-sleet", - heavysleetshowersandthunder_day: "day-sleet-storm", - heavysleetshowersandthunder_night: "night-alt-sleet-storm", - heavysleetshowersandthunder_polartwilight: "day-sleet-storm", - heavysnow: "snow-wind", - heavysnowandthunder: "day-snow-thunderstorm", - heavysnowshowers_day: "day-snow-wind", - heavysnowshowers_night: "night-alt-snow-wind", - heavysnowshowers_polartwilight: "day-snow-wind", - heavysnowshowersandthunder_day: "day-snow-thunderstorm", - heavysnowshowersandthunder_night: "night-alt-snow-thunderstorm", - heavysnowshowersandthunder_polartwilight: "day-snow-thunderstorm", - lightrain: "rain-mix", - lightrainandthunder: "thunderstorm", - lightrainshowers_day: "day-rain-mix", - lightrainshowers_night: "night-alt-rain-mix", - lightrainshowers_polartwilight: "day-rain-mix", - lightrainshowersandthunder_day: "thunderstorm", - lightrainshowersandthunder_night: "thunderstorm", - lightrainshowersandthunder_polartwilight: "thunderstorm", - lightsleet: "day-sleet", - lightsleetandthunder: "day-sleet-storm", - lightsleetshowers_day: "day-sleet", - lightsleetshowers_night: "night-alt-sleet", - lightsleetshowers_polartwilight: "day-sleet", - lightsnow: "snowflake-cold", - lightsnowandthunder: "day-snow-thunderstorm", - lightsnowshowers_day: "day-snow-wind", - lightsnowshowers_night: "night-alt-snow-wind", - lightsnowshowers_polartwilight: "day-snow-wind", - lightssleetshowersandthunder_day: "day-sleet-storm", - lightssleetshowersandthunder_night: "night-alt-sleet-storm", - lightssleetshowersandthunder_polartwilight: "day-sleet-storm", - lightssnowshowersandthunder_day: "day-snow-thunderstorm", - lightssnowshowersandthunder_night: "night-alt-snow-thunderstorm", - lightssnowshowersandthunder_polartwilight: "day-snow-thunderstorm", - partlycloudy_day: "day-cloudy", - partlycloudy_night: "night-alt-cloudy", - partlycloudy_polartwilight: "day-cloudy", - rain: "rain", - rainandthunder: "thunderstorm", - rainshowers_day: "day-rain", - rainshowers_night: "night-alt-rain", - rainshowers_polartwilight: "day-rain", - rainshowersandthunder_day: "thunderstorm", - rainshowersandthunder_night: "lightning", - rainshowersandthunder_polartwilight: "thunderstorm", - sleet: "sleet", - sleetandthunder: "day-sleet-storm", - sleetshowers_day: "day-sleet", - sleetshowers_night: "night-alt-sleet", - sleetshowers_polartwilight: "day-sleet", - sleetshowersandthunder_day: "day-sleet-storm", - sleetshowersandthunder_night: "night-alt-sleet-storm", - sleetshowersandthunder_polartwilight: "day-sleet-storm", - snow: "snowflake-cold", - snowandthunder: "lightning", - snowshowers_day: "day-snow-wind", - snowshowers_night: "night-alt-snow-wind", - snowshowers_polartwilight: "day-snow-wind", - snowshowersandthunder_day: "day-snow-thunderstorm", - snowshowersandthunder_night: "night-alt-snow-thunderstorm", - snowshowersandthunder_polartwilight: "day-snow-thunderstorm" - }; - return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; - }, + return current; + } - getForecastForXHoursFrom (weather) { - if (this.config.currentForecastHours === 1) { - if (weather.next_1_hours) { - return weather.next_1_hours; - } else if (weather.next_6_hours) { - return weather.next_6_hours; - } else { - return weather.next_12_hours; + #generateForecast (data) { + const timeseries = data.properties.timeseries; + const dailyData = new Map(); + + // Collect all data points for each day + for (const entry of timeseries) { + const date = new Date(entry.time); + const dateStr = getDateString(date); + + if (!dailyData.has(dateStr)) { + dailyData.set(dateStr, { + date: date, + temps: [], + precip: [], + precipProb: [], + symbols: [] + }); } - } else if (this.config.currentForecastHours === 6) { - if (weather.next_6_hours) { - return weather.next_6_hours; - } else if (weather.next_12_hours) { - return weather.next_12_hours; - } else { - return weather.next_1_hours; + + const dayData = dailyData.get(dateStr); + + // Collect temperature from instant data + if (entry.data.instant?.details?.air_temperature !== undefined) { + dayData.temps.push(entry.data.instant.details.air_temperature); } - } else { - if (weather.next_12_hours) { - return weather.next_12_hours; - } else if (weather.next_6_hours) { - return weather.next_6_hours; - } else { - return weather.next_1_hours; + + // Collect data from forecast periods (prefer longer periods to avoid double-counting) + const forecast = entry.data.next_12_hours || entry.data.next_6_hours || entry.data.next_1_hours; + if (forecast) { + if (forecast.details?.precipitation_amount !== undefined) { + dayData.precip.push(forecast.details.precipitation_amount); + } + if (forecast.details?.probability_of_precipitation !== undefined) { + dayData.precipProb.push(forecast.details.probability_of_precipitation); + } + if (forecast.summary?.symbol_code) { + dayData.symbols.push(forecast.summary.symbol_code); + } } } - }, - - fetchWeatherHourly () { - this.getWeatherForecast("hourly") - .then((forecast) => { - this.setWeatherHourly(forecast); - this.updateAvailable(); - }) - .catch((error) => { - Log.error("[weatherprovider.yr] fetchWeatherHourly error: ", error); - this.updateAvailable(); - }); - }, - async getWeatherForecast (type) { - const [weatherData, stellarData] = await Promise.all([this.getWeatherData(), this.getStellarData()]); - if (!weatherData.properties.timeseries || !weatherData.properties.timeseries[0]) { - Log.error("[weatherprovider.yr] No weather data available."); - return; - } - if (!stellarData) { - Log.warn("[weatherprovider.yr] No stellar data available."); - } - let forecasts; - switch (type) { - case "hourly": - forecasts = this.getHourlyForecastFrom(weatherData); - break; - case "daily": - default: - forecasts = this.getDailyForecastFrom(weatherData); - break; + // Convert collected data to forecast objects + const days = []; + for (const [dateStr, data] of dailyData) { + const stellarInfo = this.#getStellarInfoForDate(data.date); + + const dayData = { + date: data.date, + minTemperature: data.temps.length > 0 ? Math.min(...data.temps) : null, + maxTemperature: data.temps.length > 0 ? Math.max(...data.temps) : null, + precipitationAmount: data.precip.length > 0 ? Math.max(...data.precip) : null, + precipitationProbability: data.precipProb.length > 0 ? Math.max(...data.precipProb) : null, + weatherType: data.symbols.length > 0 ? this.#convertWeatherType(data.symbols[0], true) : null + }; + + if (stellarInfo) { + dayData.sunrise = new Date(stellarInfo.sunrise.time); + dayData.sunset = new Date(stellarInfo.sunset.time); + } + + days.push(dayData); } - const series = []; - for (const forecast of forecasts) { - series.push(this.getWeatherDataFrom(forecast, stellarData, weatherData.properties.meta.units)); + + // Sort by date to ensure correct order + return days.sort((a, b) => a.date - b.date); + } + + #generateHourly (data) { + const hours = []; + const timeseries = data.properties.timeseries; + + for (const entry of timeseries) { + const forecast1h = entry.data.next_1_hours; + if (!forecast1h) continue; + + const date = new Date(entry.time); + const stellarInfo = this.#getStellarInfoForDate(date); + + const hourly = { + date: date, + temperature: entry.data.instant.details.air_temperature, + windSpeed: entry.data.instant.details.wind_speed, + windFromDirection: entry.data.instant.details.wind_from_direction, + humidity: entry.data.instant.details.relative_humidity, + precipitationAmount: forecast1h.details?.precipitation_amount, + precipitationProbability: forecast1h.details?.probability_of_precipitation, + weatherType: this.#convertWeatherType( + forecast1h.summary?.symbol_code, + stellarInfo ? this.#isDayTime(date, stellarInfo) : true + ) + }; + + hours.push(hourly); } - return series; - }, - getHourlyForecastFrom (weatherData) { - const series = []; + return hours; + } - const now = moment({ - year: moment().year(), - month: moment().month(), - day: moment().date(), - hour: moment().hour() - }); - for (const forecast of weatherData.properties.timeseries) { - if (now.isAfter(moment(forecast.time))) continue; - - forecast.symbol = forecast.data.next_1_hours?.summary?.symbol_code; - forecast.precipitationAmount = forecast.data.next_1_hours?.details?.precipitation_amount; - forecast.precipitationProbability = forecast.data.next_1_hours?.details?.probability_of_precipitation; - forecast.minTemperature = forecast.data.next_1_hours?.details?.air_temperature_min; - forecast.maxTemperature = forecast.data.next_1_hours?.details?.air_temperature_max; - forecast.weatherType = this.convertWeatherType(forecast.symbol, forecast.time); - series.push(forecast); + #getForecastForXHours (data) { + const hours = this.config.currentForecastHours; + + if (hours === 12 && data.next_12_hours) { + return data.next_12_hours; + } else if (hours === 6 && data.next_6_hours) { + return data.next_6_hours; + } else if (data.next_1_hours) { + return data.next_1_hours; } - return series; - }, - - getDailyForecastFrom (weatherData) { - const series = []; - - const days = weatherData.properties.timeseries.reduce(function (days, forecast) { - const date = moment(forecast.time).format("YYYY-MM-DD"); - days[date] = days[date] || []; - days[date].push(forecast); - return days; - }, Object.create(null)); - - Object.keys(days).forEach(function (time) { - let minTemperature = undefined; - let maxTemperature = undefined; - - //Default to first entry - let forecast = days[time][0]; - forecast.symbol = forecast.data.next_12_hours?.summary?.symbol_code; - forecast.precipitation = forecast.data.next_12_hours?.details?.precipitation_amount; - - //Coming days - let forecastDiffToEight = undefined; - for (const timeseries of days[time]) { - if (!timeseries.data.next_6_hours) continue; //next_6_hours has the most data - - if (!minTemperature || timeseries.data.next_6_hours.details.air_temperature_min < minTemperature) minTemperature = timeseries.data.next_6_hours.details.air_temperature_min; - if (!maxTemperature || maxTemperature < timeseries.data.next_6_hours.details.air_temperature_max) maxTemperature = timeseries.data.next_6_hours.details.air_temperature_max; - - let closestTime = Math.abs(moment(timeseries.time).local().set({ hour: 8, minute: 0, second: 0, millisecond: 0 }).diff(moment(timeseries.time).local())); - if ((forecastDiffToEight === undefined || closestTime < forecastDiffToEight) && timeseries.data.next_12_hours) { - forecastDiffToEight = closestTime; - forecast = timeseries; - } - } - const forecastXHours = forecast.data.next_12_hours ?? forecast.data.next_6_hours ?? forecast.data.next_1_hours; - if (forecastXHours) { - forecast.symbol = forecastXHours.summary?.symbol_code; - forecast.precipitationAmount = forecastXHours.details?.precipitation_amount ?? forecast.data.next_6_hours?.details?.precipitation_amount; // 6 hours is likely to have precipitation amount even if 12 hours does not - forecast.precipitationProbability = forecastXHours.details?.probability_of_precipitation; - forecast.minTemperature = minTemperature; - forecast.maxTemperature = maxTemperature; - - series.push(forecast); + + return data.next_6_hours || data.next_12_hours || data.next_1_hours || {}; + } + + #getStellarInfoForDate (date) { + if (!this.stellarData) return null; + + const dateStr = getDateString(date); + + for (const day of this.stellarData) { + const dayDate = day.date.split("T")[0]; + if (dayDate === dateStr) { + return day; } - }); - for (const forecast of series) { - forecast.weatherType = this.convertWeatherType(forecast.symbol, forecast.time); } - return series; - }, - - fetchWeatherForecast () { - this.getWeatherForecast("daily") - .then((forecast) => { - this.setWeatherForecast(forecast); - this.updateAvailable(); - }) - .catch((error) => { - Log.error("[weatherprovider.yr] fetchWeatherForecast error: ", error); - this.updateAvailable(); - }); + + return null; + } + + #isDayTime (date, stellarInfo) { + if (!stellarInfo || !stellarInfo.sunrise || !stellarInfo.sunset) { + return true; + } + + const sunrise = new Date(stellarInfo.sunrise.time); + const sunset = new Date(stellarInfo.sunset.time); + + return date >= sunrise && date < sunset; } -}); + + #convertWeatherType (symbolCode, isDayTime) { + if (!symbolCode) return null; + + // Yr.no uses symbol codes like "clearsky_day", "partlycloudy_night", etc. + const symbol = symbolCode.replace(/_day|_night/g, ""); + + const mappings = { + clearsky: isDayTime ? "day-sunny" : "night-clear", + fair: isDayTime ? "day-sunny" : "night-clear", + partlycloudy: isDayTime ? "day-cloudy" : "night-cloudy", + cloudy: "cloudy", + fog: "fog", + lightrainshowers: isDayTime ? "day-showers" : "night-showers", + rainshowers: isDayTime ? "showers" : "night-showers", + heavyrainshowers: isDayTime ? "day-rain" : "night-rain", + lightrain: isDayTime ? "day-sprinkle" : "night-sprinkle", + rain: isDayTime ? "rain" : "night-rain", + heavyrain: isDayTime ? "rain" : "night-rain", + lightsleetshowers: isDayTime ? "day-sleet" : "night-sleet", + sleetshowers: isDayTime ? "sleet" : "night-sleet", + heavysleetshowers: isDayTime ? "sleet" : "night-sleet", + lightsleet: isDayTime ? "day-sleet" : "night-sleet", + sleet: "sleet", + heavysleet: "sleet", + lightsnowshowers: isDayTime ? "day-snow" : "night-snow", + snowshowers: isDayTime ? "snow" : "night-snow", + heavysnowshowers: isDayTime ? "snow" : "night-snow", + lightsnow: isDayTime ? "day-snow" : "night-snow", + snow: "snow", + heavysnow: "snow", + lightrainandthunder: isDayTime ? "day-thunderstorm" : "night-thunderstorm", + rainandthunder: isDayTime ? "thunderstorm" : "night-thunderstorm", + heavyrainandthunder: isDayTime ? "thunderstorm" : "night-thunderstorm", + lightsleetandthunder: isDayTime ? "day-sleet-storm" : "night-sleet-storm", + sleetandthunder: isDayTime ? "day-sleet-storm" : "night-sleet-storm", + heavysleetandthunder: isDayTime ? "day-sleet-storm" : "night-sleet-storm", + lightsnowandthunder: isDayTime ? "day-snow-thunderstorm" : "night-snow-thunderstorm", + snowandthunder: isDayTime ? "day-snow-thunderstorm" : "night-snow-thunderstorm", + heavysnowandthunder: isDayTime ? "day-snow-thunderstorm" : "night-snow-thunderstorm" + }; + + return mappings[symbol] || null; + } + + #getForecastUrl () { + const { lat, lon, altitude } = this.config; + return `${this.config.apiBase}/locationforecast/${this.config.forecastApiVersion}/complete?altitude=${altitude}&lat=${lat}&lon=${lon}`; + } + + #getSunriseUrl () { + const { lat, lon } = this.config; + const today = getDateString(new Date()); + const offset = formatTimezoneOffset(-new Date().getTimezoneOffset()); + return `${this.config.apiBase}/sunrise/${this.config.sunriseApiVersion}/sun?lat=${lat}&lon=${lon}&date=${today}&offset=${offset}`; + } +} + +module.exports = YrProvider; diff --git a/defaultmodules/weather/weather.js b/defaultmodules/weather/weather.js index 4b33682c21..fc06af3734 100644 --- a/defaultmodules/weather/weather.js +++ b/defaultmodules/weather/weather.js @@ -1,4 +1,4 @@ -/* global WeatherProvider, WeatherUtils, formatTime */ +/* global WeatherProvider, WeatherUtils, WeatherObject, formatTime */ Module.register("weather", { // Default module config. @@ -45,8 +45,12 @@ Module.register("weather", { hourlyForecastIncrements: 1 }, - // Module properties. - weatherProvider: null, + // Module properties (all providers run server-side) + instanceId: null, + fetchedLocationName: null, + currentWeatherObject: null, + weatherForecastArray: null, + weatherHourlyArray: null, // Can be used by the provider to display location of event if nothing else is specified firstEvent: null, @@ -58,14 +62,18 @@ Module.register("weather", { // Return the scripts that are necessary for the weather module. getScripts () { - return ["moment.js", "weatherutils.js", "weatherobject.js", this.file("providers/overrideWrapper.js"), "weatherprovider.js", "suncalc.js", this.file(`providers/${this.config.weatherProvider.toLowerCase()}.js`)]; + // Only load client-side dependencies for rendering + // All providers run server-side via node_helper + return ["moment.js", "weatherutils.js", "weatherobject.js", "suncalc.js"]; }, // Override getHeader method. getHeader () { - if (this.config.appendLocationNameToHeader && this.weatherProvider) { - if (this.data.header) return `${this.data.header} ${this.weatherProvider.fetchedLocation()}`; - else return this.weatherProvider.fetchedLocation(); + if (this.config.appendLocationNameToHeader) { + const locationName = this.fetchedLocationName || ""; + + if (this.data.header && locationName) return `${this.data.header} ${locationName}`; + else if (locationName) return locationName; } return this.data.header ? this.data.header : ""; @@ -87,17 +95,30 @@ Module.register("weather", { this.config.showHumidity = this.config.showHumidity ? "wind" : "none"; } - // Initialize the weather provider. - this.weatherProvider = WeatherProvider.initialize(this.config.weatherProvider, this); + // All providers run server-side: generate unique instance ID and initialize via node_helper + this.instanceId = `${this.identifier}_${Date.now()}`; + + Log.log(`[weather] Initializing server-side provider with instance ID: ${this.instanceId}`); + + this.sendSocketNotification("INIT_WEATHER", { + instanceId: this.instanceId, + weatherProvider: this.config.weatherProvider, + ...this.config + }); - // Let the weather provider know we are starting. - this.weatherProvider.start(); + // Server-driven fetching - no client-side scheduling needed // Add custom filters this.addFilters(); + }, - // Schedule the first update. - this.scheduleUpdate(this.config.initialLoadDelay); + // Cleanup on module hide/suspend + stop () { + if (this.instanceId) { + this.sendSocketNotification("STOP_WEATHER", { + instanceId: this.instanceId + }); + } }, // Override notification handler. @@ -121,10 +142,71 @@ Module.register("weather", { this.indoorHumidity = this.roundValue(payload); this.updateDom(300); } else if (notification === "CURRENT_WEATHER_OVERRIDE" && this.config.allowOverrideNotification) { - this.weatherProvider.notificationReceived(payload); + // Override current weather with data from local sensors + if (this.currentWeatherObject) { + Object.assign(this.currentWeatherObject, payload); + this.updateDom(this.config.animationSpeed); + } + } + }, + + // Handle socket notifications from node_helper + socketNotificationReceived (notification, payload) { + if (payload.instanceId !== this.instanceId) { + return; + } + + if (notification === "WEATHER_INITIALIZED") { + Log.log(`[weather] Provider initialized, location: ${payload.locationName}`); + this.fetchedLocationName = payload.locationName; + this.updateDom(); + // Server-driven fetching - HTTPFetcher will send WEATHER_DATA automatically + } else if (notification === "WEATHER_DATA") { + this.handleWeatherData(payload); + } else if (notification === "WEATHER_ERROR") { + Log.error("[weather] Error from node_helper:", payload.error); } }, + handleWeatherData (payload) { + const { type, data } = payload; + + if (!data) { + return; + } + + // Convert plain objects to WeatherObject instances + switch (type) { + case "current": + this.currentWeatherObject = this.createWeatherObject(data); + break; + case "forecast": + case "daily": + this.weatherForecastArray = data.map((d) => this.createWeatherObject(d)); + break; + case "hourly": + this.weatherHourlyArray = data.map((d) => this.createWeatherObject(d)); + break; + default: + Log.warn(`Unknown weather data type: ${type}`); + break; + } + + this.updateAvailable(); + }, + + createWeatherObject (data) { + const weather = new WeatherObject(); + Object.assign(weather, { + ...data, + // Convert to moment objects for template compatibility + date: data.date ? moment(data.date) : null, + sunrise: data.sunrise ? moment(data.sunrise) : null, + sunset: data.sunset ? moment(data.sunset) : null + }); + return weather; + }, + // Select the template depending on the display type. getTemplate () { switch (this.config.type.toLowerCase()) { @@ -143,16 +225,12 @@ Module.register("weather", { // Add all the data to the template. getTemplateData () { - const currentData = this.weatherProvider.currentWeather(); - const forecastData = this.weatherProvider.weatherForecast(); - - // Skip some hourly forecast entries if configured - const hourlyData = this.weatherProvider.weatherHourly()?.filter((e, i) => (i + 1) % this.config.hourlyForecastIncrements === this.config.hourlyForecastIncrements - 1); + const hourlyData = this.weatherHourlyArray?.filter((e, i) => (i + 1) % this.config.hourlyForecastIncrements === this.config.hourlyForecastIncrements - 1); return { config: this.config, - current: currentData, - forecast: forecastData, + current: this.currentWeatherObject, + forecast: this.weatherForecastArray, hourly: hourlyData, indoor: { humidity: this.indoorHumidity, @@ -164,58 +242,50 @@ Module.register("weather", { // What to do when the weather provider has new information available? updateAvailable () { Log.log("[weather] New weather information available."); - // this value was changed from 0 to 300 to stabilize weather tests: this.updateDom(300); - this.scheduleUpdate(); - if (this.weatherProvider.currentWeather()) { - this.sendNotification("CURRENTWEATHER_TYPE", { type: this.weatherProvider.currentWeather().weatherType?.replace("-", "_") }); + const currentWeather = this.currentWeatherObject; + + if (currentWeather) { + this.sendNotification("CURRENTWEATHER_TYPE", { type: currentWeather.weatherType?.replace("-", "_") }); } const notificationPayload = { currentWeather: this.config.units === "imperial" - ? WeatherUtils.convertWeatherObjectToImperial(this.weatherProvider?.currentWeatherObject?.simpleClone()) ?? null - : this.weatherProvider?.currentWeatherObject?.simpleClone() ?? null, + ? WeatherUtils.convertWeatherObjectToImperial(currentWeather?.simpleClone()) ?? null + : currentWeather?.simpleClone() ?? null, forecastArray: this.config.units === "imperial" - ? this.weatherProvider?.weatherForecastArray?.map((ar) => WeatherUtils.convertWeatherObjectToImperial(ar.simpleClone())) ?? [] - : this.weatherProvider?.weatherForecastArray?.map((ar) => ar.simpleClone()) ?? [], + ? this.getForecastArray()?.map((ar) => WeatherUtils.convertWeatherObjectToImperial(ar.simpleClone())) ?? [] + : this.getForecastArray()?.map((ar) => ar.simpleClone()) ?? [], hourlyArray: this.config.units === "imperial" - ? this.weatherProvider?.weatherHourlyArray?.map((ar) => WeatherUtils.convertWeatherObjectToImperial(ar.simpleClone())) ?? [] - : this.weatherProvider?.weatherHourlyArray?.map((ar) => ar.simpleClone()) ?? [], - locationName: this.weatherProvider?.fetchedLocationName, - providerName: this.weatherProvider.providerName + ? this.getHourlyArray()?.map((ar) => WeatherUtils.convertWeatherObjectToImperial(ar.simpleClone())) ?? [] + : this.getHourlyArray()?.map((ar) => ar.simpleClone()) ?? [], + locationName: this.fetchedLocationName, + providerName: this.config.weatherProvider }; this.sendNotification("WEATHER_UPDATED", notificationPayload); }, - scheduleUpdate (delay = null) { - let nextLoad = this.config.updateInterval; - if (delay !== null && delay >= 0) { - nextLoad = delay; - } + getForecastArray () { + return this.weatherForecastArray; + }, - setTimeout(() => { - switch (this.config.type.toLowerCase()) { - case "current": - this.weatherProvider.fetchCurrentWeather(); - break; - case "hourly": - this.weatherProvider.fetchWeatherHourly(); - break; - case "daily": - case "forecast": - this.weatherProvider.fetchWeatherForecast(); - break; - default: - Log.error(`[weather] Invalid type ${this.config.type} configured (must be one of 'current', 'hourly', 'daily' or 'forecast')`); - } - }, nextLoad); + getHourlyArray () { + return this.weatherHourlyArray; }, + // scheduleUpdate removed - all providers use server-driven fetching via HTTPFetcher + roundValue (temperature) { + if (temperature === null || temperature === undefined) { + return ""; + } const decimals = this.config.roundTemp ? 0 : 1; const roundValue = parseFloat(temperature).toFixed(decimals); + if (roundValue === "NaN") { + return ""; + } return roundValue === "-0" ? 0 : roundValue; }, @@ -232,14 +302,18 @@ Module.register("weather", { function (value, type, valueUnit) { let formattedValue; if (type === "temperature") { - formattedValue = `${this.roundValue(WeatherUtils.convertTemp(value, this.config.tempUnits))}°`; - if (this.config.degreeLabel) { - if (this.config.tempUnits === "metric") { - formattedValue += "C"; - } else if (this.config.tempUnits === "imperial") { - formattedValue += "F"; - } else { - formattedValue += "K"; + if (value === null || value === undefined) { + formattedValue = ""; + } else { + formattedValue = `${this.roundValue(WeatherUtils.convertTemp(value, this.config.tempUnits))}°`; + if (this.config.degreeLabel) { + if (this.config.tempUnits === "metric") { + formattedValue += "C"; + } else if (this.config.tempUnits === "imperial") { + formattedValue += "F"; + } else { + formattedValue += "K"; + } } } } else if (type === "precip") { diff --git a/defaultmodules/weather/weatherobject.js b/defaultmodules/weather/weatherobject.js index 5d6801ce13..77e88f634a 100644 --- a/defaultmodules/weather/weatherobject.js +++ b/defaultmodules/weather/weatherobject.js @@ -66,9 +66,13 @@ class WeatherObject { * the date from the weather-forecast. * @param {Moment} date an optional date where you want to get the next * action for. Useful only in tests, defaults to the current time. - * @returns {string} "sunset" or "sunrise" + * @returns {string|null} "sunset", "sunrise", or null if sun data unavailable */ nextSunAction (date = moment()) { + // Return null if sunrise/sunset data is unavailable + if (!this.sunrise || !this.sunset) { + return null; + } return date.isBetween(this.sunrise, this.sunset) ? "sunset" : "sunrise"; } @@ -84,6 +88,10 @@ class WeatherObject { * @returns {boolean} true if it is at dayTime */ isDayTime () { + // Default to daytime if sunrise/sunset data unavailable + if (!this.sunrise || !this.sunset) { + return true; + } const now = !this.date ? moment() : this.date; return now.isBetween(this.sunrise, this.sunset, undefined, "[]"); } diff --git a/defaultmodules/weather/weatherprovider.js b/defaultmodules/weather/weatherprovider.js deleted file mode 100644 index 629d7e19d1..0000000000 --- a/defaultmodules/weather/weatherprovider.js +++ /dev/null @@ -1,165 +0,0 @@ -/* global Class, performWebRequest, OverrideWrapper */ - -// This class is the blueprint for a weather provider. -const WeatherProvider = Class.extend({ - // Weather Provider Properties - providerName: null, - defaults: {}, - - // The following properties have accessor methods. - // Try to not access them directly. - currentWeatherObject: null, - weatherForecastArray: null, - weatherHourlyArray: null, - fetchedLocationName: null, - - // The following properties will be set automatically. - // You do not need to overwrite these properties. - config: null, - delegate: null, - providerIdentifier: null, - - // Weather Provider Methods - // All the following methods can be overwritten, although most are good as they are. - - // Called when a weather provider is initialized. - init (config) { - this.config = config; - Log.info(`[weatherprovider] ${this.providerName} initialized.`); - }, - - // Called to set the config, this config is the same as the weather module's config. - setConfig (config) { - this.config = config; - Log.info(`[weatherprovider] ${this.providerName} config set.`, this.config); - }, - - // Called when the weather provider is about to start. - start () { - Log.info(`[weatherprovider] ${this.providerName} started.`); - }, - - // This method should start the API request to fetch the current weather. - // This method should definitely be overwritten in the provider. - fetchCurrentWeather () { - Log.warn(`[weatherprovider] ${this.providerName} does not override the fetchCurrentWeather method.`); - }, - - // This method should start the API request to fetch the weather forecast. - // This method should definitely be overwritten in the provider. - fetchWeatherForecast () { - Log.warn(`[weatherprovider] ${this.providerName} does not override the fetchWeatherForecast method.`); - }, - - // This method should start the API request to fetch the weather hourly. - // This method should definitely be overwritten in the provider. - fetchWeatherHourly () { - Log.warn(`[weatherprovider] ${this.providerName} does not override the fetchWeatherHourly method.`); - }, - - // This returns a WeatherDay object for the current weather. - currentWeather () { - return this.currentWeatherObject; - }, - - // This returns an array of WeatherDay objects for the weather forecast. - weatherForecast () { - return this.weatherForecastArray; - }, - - // This returns an object containing WeatherDay object(s) depending on the type of call. - weatherHourly () { - return this.weatherHourlyArray; - }, - - // This returns the name of the fetched location or an empty string. - fetchedLocation () { - return this.fetchedLocationName || ""; - }, - - // Set the currentWeather and notify the delegate that new information is available. - setCurrentWeather (currentWeatherObject) { - // We should check here if we are passing a WeatherDay - this.currentWeatherObject = currentWeatherObject; - }, - - // Set the weatherForecastArray and notify the delegate that new information is available. - setWeatherForecast (weatherForecastArray) { - // We should check here if we are passing a WeatherDay - this.weatherForecastArray = weatherForecastArray; - }, - - // Set the weatherHourlyArray and notify the delegate that new information is available. - setWeatherHourly (weatherHourlyArray) { - this.weatherHourlyArray = weatherHourlyArray; - }, - - // Set the fetched location name. - setFetchedLocation (name) { - this.fetchedLocationName = name; - }, - - // Notify the delegate that new weather is available. - updateAvailable () { - this.delegate.updateAvailable(this); - }, - - /** - * A convenience function to make requests. - * @param {string} url the url to fetch from - * @param {string} type what content-type to expect in the response, can be "json" or "xml" - * @param {Array.<{name: string, value:string}>} requestHeaders the HTTP headers to send - * @param {Array.} expectedResponseHeaders the expected HTTP headers to receive - * @returns {Promise} resolved when the fetch is done - */ - async fetchData (url, type = "json", requestHeaders = undefined, expectedResponseHeaders = undefined) { - const mockData = this.config.mockData; - if (mockData) { - const data = mockData.substring(1, mockData.length - 1); - return JSON.parse(data); - } - const useCorsProxy = typeof this.config.useCorsProxy !== "undefined" && this.config.useCorsProxy; - return performWebRequest(url, type, useCorsProxy, requestHeaders, expectedResponseHeaders, config.basePath); - } -}); - -/** - * Collection of registered weather providers. - */ -WeatherProvider.providers = []; - -/** - * Static method to register a new weather provider. - * @param {string} providerIdentifier The name of the weather provider - * @param {object} providerDetails The details of the weather provider - */ -WeatherProvider.register = function (providerIdentifier, providerDetails) { - WeatherProvider.providers[providerIdentifier.toLowerCase()] = WeatherProvider.extend(providerDetails); -}; - -/** - * Static method to initialize a new weather provider. - * @param {string} providerIdentifier The name of the weather provider - * @param {object} delegate The weather module - * @returns {object} The new weather provider - */ -WeatherProvider.initialize = function (providerIdentifier, delegate) { - const pi = providerIdentifier.toLowerCase(); - - const provider = new WeatherProvider.providers[pi](); - const config = Object.assign({}, provider.defaults, delegate.config); - - provider.delegate = delegate; - provider.setConfig(config); - - provider.providerIdentifier = pi; - if (!provider.providerName) { - provider.providerName = pi; - } - - if (config.allowOverrideNotification) { - return new OverrideWrapper(provider); - } - - return provider; -}; diff --git a/defaultmodules/weather/weatherutils.js b/defaultmodules/weather/weatherutils.js index 43a273b560..365441f0b5 100644 --- a/defaultmodules/weather/weatherutils.js +++ b/defaultmodules/weather/weatherutils.js @@ -25,6 +25,9 @@ const WeatherUtils = { * @returns {string} - A string with tha value and a unit postfix. */ convertPrecipitationUnit (value, valueUnit, outputUnit) { + if (value === null || value === undefined || isNaN(value)) { + return ""; + } if (valueUnit === "%") return `${value.toFixed(0)} ${valueUnit}`; let convertedValue = value; diff --git a/eslint.config.mjs b/eslint.config.mjs index 238efa961d..ee3af12c86 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -51,7 +51,7 @@ export default defineConfig([ "@stylistic/space-before-function-paren": ["error", "always"], "@stylistic/spaced-comment": "off", "dot-notation": "error", - eqeqeq: "error", + eqeqeq: ["error", "always", { null: "ignore" }], "id-length": "off", "import-x/extensions": "error", "import-x/newline-after-import": "error", @@ -146,6 +146,15 @@ export default defineConfig([ "vitest/prefer-to-have-length": "error" } }, + { + files: ["tests/unit/modules/default/weather/providers/*.js"], + rules: { + "import-x/namespace": "off", + "import-x/named": "off", + "import-x/default": "off", + "import-x/extensions": "off" + } + }, { files: ["tests/configs/modules/weather/*.js"], rules: { diff --git a/js/http_fetcher.js b/js/http_fetcher.js index f5a56fc46a..95a13ba5d2 100644 --- a/js/http_fetcher.js +++ b/js/http_fetcher.js @@ -42,6 +42,23 @@ const ERROR_TYPE_TO_TRANSLATION = { */ class HTTPFetcher extends EventEmitter { + /** + * Calculates exponential backoff delay for retries + * @param {number} attempt - Attempt number (1-based) + * @param {object} options - Configuration options + * @param {number} [options.baseDelay] - Initial delay in ms (default: 15s) + * @param {number} [options.maxDelay] - Maximum delay in ms (default: 5min) + * @returns {number} Delay in milliseconds + * @example + * HTTPFetcher.calculateBackoffDelay(1) // 15000 (15s) + * HTTPFetcher.calculateBackoffDelay(2) // 30000 (30s) + * HTTPFetcher.calculateBackoffDelay(3) // 60000 (60s) + * HTTPFetcher.calculateBackoffDelay(6) // 300000 (5min, capped) + */ + static calculateBackoffDelay (attempt, { baseDelay = 15000, maxDelay = 300000 } = {}) { + return Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay); + } + /** * Creates a new HTTPFetcher instance * @param {string} url - The URL to fetch @@ -55,6 +72,7 @@ class HTTPFetcher extends EventEmitter { * @param {object} [options.headers] - Additional headers to send * @param {number} [options.maxRetries] - Max retries for 5xx errors (default: 3) * @param {number} [options.timeout] - Request timeout in ms (default: 30000) + * @param {string} [options.logContext] - Optional context for log messages (e.g., provider name) */ constructor (url, options = {}) { super(); @@ -66,9 +84,11 @@ class HTTPFetcher extends EventEmitter { this.customHeaders = options.headers || {}; this.maxRetries = options.maxRetries || MAX_SERVER_BACKOFF; this.timeout = options.timeout || DEFAULT_TIMEOUT; + this.logContext = options.logContext ? `[${options.logContext}] ` : ""; this.reloadTimer = null; this.serverErrorCount = 0; + this.networkErrorCount = 0; } /** @@ -177,29 +197,29 @@ class HTTPFetcher extends EventEmitter { if (status === 401 || status === 403) { errorType = "AUTH_FAILURE"; delay = Math.max(this.reloadInterval * 5, THIRTY_MINUTES); - message = `Authentication failed (${status}). Waiting ${Math.round(delay / 60000)} minutes before retry.`; - Log.error(`${this.url} - ${message}`); + message = `Authentication failed (${status}). Check your API key. Waiting ${Math.round(delay / 60000)} minutes before retry.`; + Log.error(`${this.logContext}${this.url} - ${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.url} - ${message}`); + Log.warn(`${this.logContext}${this.url} - ${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.url} - ${message}`); + Log.error(`${this.logContext}${this.url} - ${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.url} - ${message}`); + Log.error(`${this.logContext}${this.url} - ${message}`); } else { message = `Unexpected HTTP status ${status}.`; - Log.error(`${this.url} - ${message}`); + Log.error(`${this.logContext}${this.url} - ${message}`); } return { @@ -224,7 +244,7 @@ class HTTPFetcher extends EventEmitter { errorType, translationKey: ERROR_TYPE_TO_TRANSLATION[errorType] || "MODULE_ERROR_UNSPECIFIED", retryAfter, - retryCount: this.serverErrorCount, + retryCount: errorType === "NETWORK_ERROR" ? this.networkErrorCount : this.serverErrorCount, url: this.url, originalError }; @@ -253,8 +273,9 @@ class HTTPFetcher extends EventEmitter { nextDelay = delay; this.emit("error", errorInfo); } else { - // Reset server error count on success + // Reset error counts on success this.serverErrorCount = 0; + this.networkErrorCount = 0; /** * Response event - fired when fetch succeeds @@ -267,13 +288,35 @@ class HTTPFetcher extends EventEmitter { const isTimeout = error.name === "AbortError"; const message = isTimeout ? `Request timeout after ${this.timeout}ms` : `Network error: ${error.message}`; - Log.error(`${this.url} - ${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 + } + + // 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}`); + } else { + Log.error(`${this.logContext}${shortUrl} - ${message} ${retryMessage}`); + } const errorInfo = this.#createErrorInfo( message, null, "NETWORK_ERROR", - this.reloadInterval, + nextDelay, error ); diff --git a/js/server.js b/js/server.js index 3bf892097f..9eba4f97df 100644 --- a/js/server.js +++ b/js/server.js @@ -6,7 +6,7 @@ const express = require("express"); const helmet = require("helmet"); const socketio = require("socket.io"); const Log = require("logger"); -const { cors, getHtml, getVersion, getStartup, getEnvVars } = require("#server_functions"); +const { getHtml, getVersion, getEnvVars, cors } = require("#server_functions"); const { ipAccessControl } = require(`${__dirname}/ip_access_control`); @@ -106,6 +106,9 @@ function Server (configObj) { app.use(directory, express.static(path.resolve(global.root_path + directory))); } + const startUp = new Date(); + const getStartup = (req, res) => res.send(startUp); + const getConfig = (req, res) => { if (config.hideConfigSecrets) { res.send(configObj.redactedConf); @@ -113,13 +116,12 @@ function Server (configObj) { res.send(configObj.fullConf); } }; + app.get("/config", (req, res) => getConfig(req, res)); app.get("/cors", async (req, res) => await cors(req, res)); app.get("/version", (req, res) => getVersion(req, res)); - app.get("/config", (req, res) => getConfig(req, res)); - app.get("/startup", (req, res) => getStartup(req, res)); app.get("/env", (req, res) => getEnvVars(req, res)); diff --git a/tests/configs/modules/weather/currentweather_compliments.js b/tests/configs/modules/weather/currentweather_compliments.js index 603fafa173..70bb1b8f01 100644 --- a/tests/configs/modules/weather/currentweather_compliments.js +++ b/tests/configs/modules/weather/currentweather_compliments.js @@ -16,10 +16,10 @@ let config = { module: "weather", position: "bottom_bar", config: { - location: "Munich", + lat: 48.14, + lon: 11.58, weatherProvider: "openweathermap", - weatherEndpoint: "/weather", - mockData: '"#####WEATHERDATA#####"' + apiKey: "test-api-key" } } ] diff --git a/tests/configs/modules/weather/currentweather_default.js b/tests/configs/modules/weather/currentweather_default.js index e5a9fdce4e..0e6e9f1752 100644 --- a/tests/configs/modules/weather/currentweather_default.js +++ b/tests/configs/modules/weather/currentweather_default.js @@ -8,11 +8,11 @@ let config = { module: "weather", position: "bottom_bar", config: { - location: "Munich", + lat: 48.14, + lon: 11.58, showHumidity: "feelslike", weatherProvider: "openweathermap", - weatherEndpoint: "/weather", - mockData: '"#####WEATHERDATA#####"' + apiKey: "test-api-key" } } ] diff --git a/tests/configs/modules/weather/currentweather_options.js b/tests/configs/modules/weather/currentweather_options.js index 0ddb8b7cf2..814fca5520 100644 --- a/tests/configs/modules/weather/currentweather_options.js +++ b/tests/configs/modules/weather/currentweather_options.js @@ -6,10 +6,10 @@ let config = { module: "weather", position: "bottom_bar", config: { - location: "Munich", + lat: 48.14, + lon: 11.58, weatherProvider: "openweathermap", - weatherEndpoint: "/weather", - mockData: '"#####WEATHERDATA#####"', + apiKey: "test-api-key", windUnits: "beaufort", showWindDirectionAsArrow: true, showSun: false, diff --git a/tests/configs/modules/weather/currentweather_units.js b/tests/configs/modules/weather/currentweather_units.js index 462b67f682..33baecd6b1 100644 --- a/tests/configs/modules/weather/currentweather_units.js +++ b/tests/configs/modules/weather/currentweather_units.js @@ -8,10 +8,10 @@ let config = { module: "weather", position: "bottom_bar", config: { - location: "Munich", + lat: 48.14, + lon: 11.58, weatherProvider: "openweathermap", - weatherEndpoint: "/weather", - mockData: '"#####WEATHERDATA#####"', + apiKey: "test-api-key", decimalSymbol: ",", showHumidity: "wind" } diff --git a/tests/configs/modules/weather/forecastweather_absolute.js b/tests/configs/modules/weather/forecastweather_absolute.js index ff18bdf973..01fc4f43a9 100644 --- a/tests/configs/modules/weather/forecastweather_absolute.js +++ b/tests/configs/modules/weather/forecastweather_absolute.js @@ -9,10 +9,10 @@ let config = { position: "bottom_bar", config: { type: "forecast", - location: "Munich", + lat: 48.14, + lon: 11.58, weatherProvider: "openweathermap", - weatherEndpoint: "/forecast/daily", - mockData: '"#####WEATHERDATA#####"', + apiKey: "test-api-key", absoluteDates: true } } diff --git a/tests/configs/modules/weather/forecastweather_default.js b/tests/configs/modules/weather/forecastweather_default.js index a53ba1273b..4cb23763bc 100644 --- a/tests/configs/modules/weather/forecastweather_default.js +++ b/tests/configs/modules/weather/forecastweather_default.js @@ -9,10 +9,10 @@ let config = { position: "bottom_bar", config: { type: "forecast", - location: "Munich", + lat: 48.14, + lon: 11.58, weatherProvider: "openweathermap", - weatherEndpoint: "/forecast/daily", - mockData: '"#####WEATHERDATA#####"' + apiKey: "test-api-key" } } ] diff --git a/tests/configs/modules/weather/forecastweather_options.js b/tests/configs/modules/weather/forecastweather_options.js index 0e80198814..25ff5bcde0 100644 --- a/tests/configs/modules/weather/forecastweather_options.js +++ b/tests/configs/modules/weather/forecastweather_options.js @@ -9,10 +9,10 @@ let config = { position: "bottom_bar", config: { type: "forecast", - location: "Munich", + lat: 48.14, + lon: 11.58, weatherProvider: "openweathermap", - weatherEndpoint: "/forecast/daily", - mockData: '"#####WEATHERDATA#####"', + apiKey: "test-api-key", showPrecipitationAmount: true, colored: true, tableClass: "myTableClass" diff --git a/tests/configs/modules/weather/forecastweather_units.js b/tests/configs/modules/weather/forecastweather_units.js index 73bcde9727..a71afaad56 100644 --- a/tests/configs/modules/weather/forecastweather_units.js +++ b/tests/configs/modules/weather/forecastweather_units.js @@ -9,10 +9,10 @@ let config = { position: "bottom_bar", config: { type: "forecast", - location: "Munich", + lat: 48.14, + lon: 11.58, weatherProvider: "openweathermap", - weatherEndpoint: "/forecast/daily", - mockData: '"#####WEATHERDATA#####"', + apiKey: "test-api-key", decimalSymbol: "_", showPrecipitationAmount: true } diff --git a/tests/configs/modules/weather/hourlyweather_default.js b/tests/configs/modules/weather/hourlyweather_default.js index 191ceab1d2..e7437b0920 100644 --- a/tests/configs/modules/weather/hourlyweather_default.js +++ b/tests/configs/modules/weather/hourlyweather_default.js @@ -8,11 +8,11 @@ let config = { module: "weather", position: "bottom_bar", config: { + lat: 48.14, + lon: 11.58, type: "hourly", - location: "Berlin", weatherProvider: "openweathermap", - weatherEndpoint: "/onecall", - mockData: '"#####WEATHERDATA#####"' + apiKey: "test-api-key" } } ] diff --git a/tests/configs/modules/weather/hourlyweather_options.js b/tests/configs/modules/weather/hourlyweather_options.js index c11d23dbd3..0e323a9f7f 100644 --- a/tests/configs/modules/weather/hourlyweather_options.js +++ b/tests/configs/modules/weather/hourlyweather_options.js @@ -8,11 +8,11 @@ let config = { module: "weather", position: "bottom_bar", config: { + lat: 48.14, + lon: 11.58, type: "hourly", - location: "Berlin", weatherProvider: "openweathermap", - weatherEndpoint: "/onecall", - mockData: '"#####WEATHERDATA#####"', + apiKey: "test-api-key", hourlyForecastIncrements: 2 } } diff --git a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js index 3dbbc41837..bc04a9917d 100644 --- a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js +++ b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js @@ -8,11 +8,11 @@ let config = { module: "weather", position: "bottom_bar", config: { + lat: 48.14, + lon: 11.58, type: "hourly", - location: "Berlin", weatherProvider: "openweathermap", - weatherEndpoint: "/onecall", - mockData: '"#####WEATHERDATA#####"', + apiKey: "test-api-key", showPrecipitationAmount: true, showPrecipitationProbability: true } diff --git a/tests/e2e/helpers/weather-functions.js b/tests/e2e/helpers/weather-functions.js index 6780ea42c1..8eb0c0699e 100644 --- a/tests/e2e/helpers/weather-functions.js +++ b/tests/e2e/helpers/weather-functions.js @@ -1,12 +1,108 @@ -const { injectMockData, cleanupMockData } = require("../../utils/weather_mocker"); +const fs = require("node:fs"); +const path = require("node:path"); +const weatherUtils = require("../../../defaultmodules/weather/provider-utils"); const helpers = require("./global-setup"); -exports.startApplication = async (configFileName, additionalMockData) => { - await helpers.startApplication(injectMockData(configFileName, additionalMockData)); +/** + * Inject mock weather data directly via socket communication + * This bypasses the weather provider and tests only client-side rendering + * @param {object} page - Playwright page + * @param {string} mockDataFile - Filename of mock data + */ +async function injectMockWeatherData (page, mockDataFile) { + const rawData = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../../mocks", mockDataFile)).toString()); + + // Validate that the fixture has at least one expected weather data type + if (!rawData.current && !rawData.daily && !rawData.hourly) { + throw new Error( + "Invalid weather fixture: missing current, daily, and hourly data. " + + `Available keys: ${Object.keys(rawData).join(", ")}` + ); + } + + // Determine weather type from the mock data structure + let type = "current"; + let data = null; + + const timezoneOffset = rawData.timezone_offset ? rawData.timezone_offset / 60 : 0; + + if (rawData.current) { + type = "current"; + // Mock what the provider would send for current weather + data = { + date: weatherUtils.applyTimezoneOffset(new Date(rawData.current.dt * 1000), timezoneOffset), + windSpeed: rawData.current.wind_speed, + windFromDirection: rawData.current.wind_deg, + sunrise: weatherUtils.applyTimezoneOffset(new Date(rawData.current.sunrise * 1000), timezoneOffset), + sunset: weatherUtils.applyTimezoneOffset(new Date(rawData.current.sunset * 1000), timezoneOffset), + temperature: rawData.current.temp, + weatherType: weatherUtils.convertWeatherType(rawData.current.weather[0].icon), + humidity: rawData.current.humidity, + feelsLikeTemp: rawData.current.feels_like + }; + } else if (rawData.daily) { + type = "forecast"; + data = rawData.daily.map((day) => ({ + date: weatherUtils.applyTimezoneOffset(new Date(day.dt * 1000), timezoneOffset), + minTemperature: day.temp.min, + maxTemperature: day.temp.max, + weatherType: weatherUtils.convertWeatherType(day.weather[0].icon), + rain: day.rain || 0, + snow: day.snow || 0, + precipitationAmount: (day.rain || 0) + (day.snow || 0) + })); + } else if (rawData.hourly) { + type = "hourly"; + data = rawData.hourly.map((hour) => ({ + date: weatherUtils.applyTimezoneOffset(new Date(hour.dt * 1000), timezoneOffset), + temperature: hour.temp, + feelsLikeTemp: hour.feels_like, + humidity: hour.humidity, + windSpeed: hour.wind_speed, + windFromDirection: hour.wind_deg, + weatherType: weatherUtils.convertWeatherType(hour.weather[0].icon), + precipitationProbability: hour.pop != null ? hour.pop * 100 : undefined, + precipitationAmount: (hour.rain?.["1h"] || 0) + (hour.snow?.["1h"] || 0) + })); + } + + // Inject weather data by evaluating code in the browser context + await page.evaluate(({ type, data }) => { + // Find the weather module instance + const weatherModule = MM.getModules().find((m) => m.name === "weather"); + if (weatherModule) { + // Send INITIALIZED first + weatherModule.socketNotificationReceived("WEATHER_INITIALIZED", { + instanceId: weatherModule.instanceId, + locationName: "Munich" + }); + // Then send the actual data + weatherModule.socketNotificationReceived("WEATHER_DATA", { + instanceId: weatherModule.instanceId, + type: type, + data: data + }); + } + }, { type, data }); +} + +exports.startApplication = async (configFileName, mockDataFile) => { + await helpers.startApplication(configFileName); await helpers.getDocument(); + + // If mock data file is provided, inject it + if (mockDataFile) { + const page = helpers.getPage(); + // Wait for weather module to initialize + // eslint-disable-next-line playwright/no-wait-for-selector + await page.waitForSelector(".weather", { timeout: 5000 }); + await injectMockWeatherData(page, mockDataFile); + // Wait for data to be rendered + // eslint-disable-next-line playwright/no-wait-for-selector + await page.waitForSelector(".weather .weathericon", { timeout: 2000 }); + } }; exports.stopApplication = async () => { await helpers.stopApplication(); - cleanupMockData(); }; diff --git a/tests/e2e/modules/weather_current_spec.js b/tests/e2e/modules/weather_current_spec.js index 9b2928792e..bb8b63e2ac 100644 --- a/tests/e2e/modules/weather_current_spec.js +++ b/tests/e2e/modules/weather_current_spec.js @@ -12,7 +12,7 @@ describe("Weather module", () => { describe("Current weather", () => { describe("Default configuration", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_default.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_default.js", "weather_onecall_current.json"); page = helpers.getPage(); }); @@ -38,7 +38,7 @@ describe("Weather module", () => { describe("Compliments Integration", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_compliments.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_compliments.js", "weather_onecall_current.json"); page = helpers.getPage(); }); @@ -51,7 +51,7 @@ describe("Weather module", () => { describe("Configuration Options", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_options.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_options.js", "weather_onecall_current.json"); page = helpers.getPage(); }); @@ -79,7 +79,7 @@ describe("Weather module", () => { describe("Current weather with imperial units", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_units.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_units.js", "weather_onecall_current.json"); page = helpers.getPage(); }); diff --git a/tests/e2e/modules/weather_forecast_spec.js b/tests/e2e/modules/weather_forecast_spec.js index 011ed35f49..435cc98ce5 100644 --- a/tests/e2e/modules/weather_forecast_spec.js +++ b/tests/e2e/modules/weather_forecast_spec.js @@ -11,7 +11,7 @@ describe("Weather module: Weather Forecast", () => { describe("Default configuration", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_default.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_default.js", "weather_onecall_forecast.json"); page = helpers.getPage(); }); @@ -58,7 +58,7 @@ describe("Weather module: Weather Forecast", () => { describe("Absolute configuration", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_absolute.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_absolute.js", "weather_onecall_forecast.json"); page = helpers.getPage(); }); @@ -73,7 +73,7 @@ describe("Weather module: Weather Forecast", () => { describe("Configuration Options", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_options.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_options.js", "weather_onecall_forecast.json"); page = helpers.getPage(); }); @@ -99,7 +99,7 @@ describe("Weather module: Weather Forecast", () => { describe("Forecast weather with imperial units", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_units.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_units.js", "weather_onecall_forecast.json"); page = helpers.getPage(); }); diff --git a/tests/e2e/modules/weather_hourly_spec.js b/tests/e2e/modules/weather_hourly_spec.js index a33503f3b2..d84bd69e72 100644 --- a/tests/e2e/modules/weather_hourly_spec.js +++ b/tests/e2e/modules/weather_hourly_spec.js @@ -11,7 +11,7 @@ describe("Weather module: Weather Hourly Forecast", () => { describe("Default configuration", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_default.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_default.js", "weather_onecall_hourly.json"); page = helpers.getPage(); }); @@ -26,7 +26,7 @@ describe("Weather module: Weather Hourly Forecast", () => { describe("Hourly weather options", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_options.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_options.js", "weather_onecall_hourly.json"); page = helpers.getPage(); }); @@ -43,7 +43,7 @@ describe("Weather module: Weather Hourly Forecast", () => { describe("Show precipitations", () => { beforeAll(async () => { - await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_showPrecipitation.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_showPrecipitation.js", "weather_onecall_hourly.json"); page = helpers.getPage(); }); diff --git a/tests/electron/helpers/weather-setup.js b/tests/electron/helpers/weather-setup.js index cb43054897..3bddaef1a1 100644 --- a/tests/electron/helpers/weather-setup.js +++ b/tests/electron/helpers/weather-setup.js @@ -1,6 +1,77 @@ -const { injectMockData } = require("../../utils/weather_mocker"); +const fs = require("node:fs"); +const path = require("node:path"); +const weatherUtils = require("../../../defaultmodules/weather/provider-utils"); const helpers = require("./global-setup"); +/** + * Inject mock weather data directly via socket communication + * This bypasses the weather provider and tests only client-side rendering + * @param {string} mockDataFile - Filename of mock data in tests/mocks + */ +async function injectMockWeatherData (mockDataFile) { + const rawData = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../../mocks", mockDataFile)).toString()); + + const timezoneOffset = rawData.timezone_offset ? rawData.timezone_offset / 60 : 0; + + let type = "current"; + let data = null; + + if (rawData.current) { + type = "current"; + data = { + date: weatherUtils.applyTimezoneOffset(new Date(rawData.current.dt * 1000), timezoneOffset), + windSpeed: rawData.current.wind_speed, + windFromDirection: rawData.current.wind_deg, + sunrise: weatherUtils.applyTimezoneOffset(new Date(rawData.current.sunrise * 1000), timezoneOffset), + sunset: weatherUtils.applyTimezoneOffset(new Date(rawData.current.sunset * 1000), timezoneOffset), + temperature: rawData.current.temp, + weatherType: weatherUtils.convertWeatherType(rawData.current.weather[0].icon), + humidity: rawData.current.humidity, + feelsLikeTemp: rawData.current.feels_like + }; + } else if (rawData.daily) { + type = "forecast"; + data = rawData.daily.map((day) => ({ + date: weatherUtils.applyTimezoneOffset(new Date(day.dt * 1000), timezoneOffset), + minTemperature: day.temp.min, + maxTemperature: day.temp.max, + weatherType: weatherUtils.convertWeatherType(day.weather[0].icon), + rain: day.rain || 0, + snow: day.snow || 0, + precipitationAmount: (day.rain || 0) + (day.snow || 0) + })); + } else if (rawData.hourly) { + type = "hourly"; + data = rawData.hourly.map((hour) => ({ + date: weatherUtils.applyTimezoneOffset(new Date(hour.dt * 1000), timezoneOffset), + temperature: hour.temp, + feelsLikeTemp: hour.feels_like, + humidity: hour.humidity, + windSpeed: hour.wind_speed, + windFromDirection: hour.wind_deg, + weatherType: weatherUtils.convertWeatherType(hour.weather[0].icon), + precipitationProbability: hour.pop != null ? hour.pop * 100 : undefined, + precipitationAmount: (hour.rain?.["1h"] || 0) + (hour.snow?.["1h"] || 0) + })); + } + + // Inject weather data by evaluating code in the browser context + await global.page.evaluate(({ type, data }) => { + const weatherModule = MM.getModules().find((m) => m.name === "weather"); + if (weatherModule) { + weatherModule.socketNotificationReceived("WEATHER_INITIALIZED", { + instanceId: weatherModule.instanceId, + locationName: "Munich" + }); + weatherModule.socketNotificationReceived("WEATHER_DATA", { + instanceId: weatherModule.instanceId, + type: type, + data: data + }); + } + }, { type, data }); +} + exports.getText = async (element, result) => { const elem = await helpers.getElement(element); await expect(elem).not.toBeNull(); @@ -14,6 +85,18 @@ exports.getText = async (element, result) => { return true; }; -exports.startApp = async (configFileName, systemDate) => { - await helpers.startApplication(injectMockData(configFileName), systemDate); +exports.startApp = async (configFileName, systemDate, mockDataFile = "weather_onecall_current.json") => { + await helpers.startApplication(configFileName, systemDate); + + // Wait for weather module to be present in DOM + await global.page.waitForSelector(".weather", { timeout: 5000 }); + + // Inject mock weather data + await injectMockWeatherData(mockDataFile); + + // Wait for weather content to be rendered + await global.page.waitForFunction(() => { + const weatherRoot = document.querySelector(".weather"); + return !!(weatherRoot && weatherRoot.textContent && weatherRoot.textContent.trim().length > 0); + }, { timeout: 5000 }); }; diff --git a/tests/electron/modules/weather_spec.js b/tests/electron/modules/weather_spec.js index fb362f805f..e300da90de 100644 --- a/tests/electron/modules/weather_spec.js +++ b/tests/electron/modules/weather_spec.js @@ -1,6 +1,5 @@ const helpers = require("../helpers/global-setup"); const weatherHelper = require("../helpers/weather-setup"); -const { cleanupMockData } = require("../../utils/weather_mocker"); const CURRENT_WEATHER_CONFIG = "tests/configs/modules/weather/currentweather_default.js"; const SUNRISE_DATE = "13 Jan 2019 00:30:00 GMT"; @@ -12,7 +11,6 @@ const EXPECTED_SUNSET_TEXT = "3:45 pm"; describe("Weather module", () => { afterEach(async () => { await helpers.stopApplication(); - cleanupMockData(); }); describe("Current weather with sunrise", () => { diff --git a/tests/mocks/weather_envcanada.xml b/tests/mocks/weather_envcanada.xml new file mode 100644 index 0000000000..ac8d6fcff3 --- /dev/null +++ b/tests/mocks/weather_envcanada.xml @@ -0,0 +1,871 @@ + + + https://dd.weather.gc.ca/doc/LICENCE_GENERAL.txt + + 2026 + 02 + 07 + 12 + 04 + 20260207120421 + Saturday February 07, 2026 at 12:04 UTC + + + 2026 + 02 + 07 + 07 + 04 + 20260207070421 + Saturday February 07, 2026 at 07:04 EST + + + North America + Canada + Ontario + Toronto + City of Toronto + + + + + 2026 + 02 + 07 + 09 + 06 + 20260207090653 + Saturday February 07, 2026 at 09:06 UTC + + + 2026 + 02 + 07 + 04 + 06 + 20260207040653 + Saturday February 07, 2026 at 04:06 EST + + + + + Toronto Pearson Int'l Airport + + 2026 + 02 + 07 + 12 + 00 + 20260207120000 + Saturday February 07, 2026 at 12:00 UTC + + + 2026 + 02 + 07 + 07 + 00 + 20260207070000 + Saturday February 07, 2026 at 07:00 EST + + Blowing Snow + 40 + -20.3 + -24.9 + -31 + 102.1 + 9.7 + 67 + + 19 + 33 + NNW + 346.0 + + + + + 2026 + 02 + 07 + 10 + 00 + 20260207100000 + Saturday February 07, 2026 at 10:00 UTC + + + 2026 + 02 + 07 + 05 + 00 + 20260207050000 + Saturday February 07, 2026 at 05:00 EST + + + Low minus 9. High minus 2. + -2 + -9 + + + Saturday + A mix of sun and cloud. 40 percent chance of flurries early this morning. Wind northwest 30 km/h gusting to 50. High minus 13. Wind chill minus 33 this morning and minus 22 this afternoon. Risk of frostbite. UV index 1 or low. + + A mix of sun and cloud. 40 percent chance of flurries early this morning. + + + 08 + 40 + Chance of flurries + + + High minus 13. + -13 + + + Wind northwest 30 km/h gusting to 50. + + 30 + 50 + NW + 32 + + + + + snow + + + Wind chill minus 33 this morning and minus 22 this afternoon. Risk of frostbite. + -33 + -22 + Risk of frostbite + + + 1 + UV index 1 or low. + + 40 + + + + Saturday night + Partly cloudy. Clearing late this evening. Wind northwest 20 km/h becoming light late this evening. Low minus 21. Wind chill minus 22 this evening and minus 28 overnight. Risk of frostbite. + + Partly cloudy. Clearing late this evening. + + + 35 + + Clearing + + + Low minus 21. + -21 + + + Wind northwest 20 km/h becoming light late this evening. + + 20 + 00 + NW + 32 + + + 10 + 00 + NW + 32 + + + + + + + + Wind chill minus 22 this evening and minus 28 overnight. Risk of frostbite. + -22 + -28 + Risk of frostbite + + 65 + + + + Sunday + Sunny. Wind up to 15 km/h. High minus 12. Wind chill minus 28 in the morning and minus 19 in the afternoon. Risk of frostbite. UV index 2 or low. + + Sunny. + + + 00 + + Sunny + + + High minus 12. + -12 + + + Wind up to 15 km/h. + + 10 + 00 + N + 36 + + + 15 + 00 + NW + 32 + + + + + + + + Wind chill minus 28 in the morning and minus 19 in the afternoon. Risk of frostbite. + -28 + -19 + Risk of frostbite + + + 2 + UV index 2 or low. + + 55 + + + + Sunday night + Cloudy periods. Low minus 14. + + Cloudy periods. + + + 32 + + Cloudy periods + + + Low minus 14. + -14 + + + + + + + + 60 + + + + Monday + Cloudy with 40 percent chance of flurries. High minus 6. + + Cloudy with 40 percent chance of flurries. + + + 16 + 40 + Chance of flurries + + + High minus 6. + -6 + + + + + snow + + + 65 + + + + Monday night + Cloudy with 30 percent chance of flurries. Low minus 8. + + Cloudy with 30 percent chance of flurries. + + + 16 + 30 + Chance of flurries + + + Low minus 8. + -8 + + + + + snow + + + 65 + + + + Tuesday + Cloudy with 30 percent chance of flurries. High minus 2. + + Cloudy with 30 percent chance of flurries. + + + 16 + 30 + Chance of flurries + + + High minus 2. + -2 + + + + + snow + + + 75 + + + + Tuesday night + Cloudy with 40 percent chance of flurries. Low minus 3. + + Cloudy with 40 percent chance of flurries. + + + 16 + 40 + Chance of flurries + + + Low minus 3. + -3 + + + + + snow + + + 80 + + + + Wednesday + Cloudy with 30 percent chance of flurries. High zero. + + Cloudy with 30 percent chance of flurries. + + + 16 + 30 + Chance of flurries + + + High zero. + 0 + + + + + snow + + + 80 + + + + Wednesday night + Cloudy periods. Low minus 6. + + Cloudy periods. + + + 32 + + Cloudy periods + + + Low minus 6. + -6 + + + + + + + + 90 + + + + Thursday + A mix of sun and cloud. High minus 2. + + A mix of sun and cloud. + + + 02 + + A mix of sun and cloud + + + High minus 2. + -2 + + + + + + + + 75 + + + + Thursday night + Cloudy periods. Low minus 7. + + Cloudy periods. + + + 32 + + Cloudy periods + + + Low minus 7. + -7 + + + + + + + + 75 + + + + Friday + A mix of sun and cloud. High minus 1. + + A mix of sun and cloud. + + + 02 + + A mix of sun and cloud + + + High minus 1. + -1 + + + + + + + + 75 + + + + + + 2026 + 02 + 07 + 10 + 00 + 20260207100000 + Saturday February 07, 2026 at 10:00 UTC + + + 2026 + 02 + 07 + 05 + 00 + 20260207050000 + Saturday February 07, 2026 at 05:00 EST + + + A mix of sun and cloud + 02 + -20 + 10 + -32 + + + 30 + NW + 50 + + + + A mix of sun and cloud + 02 + -19 + 10 + -32 + + + 30 + NW + 50 + + + 1 + + + + A mix of sun and cloud + 02 + -19 + 10 + -31 + + + 30 + NW + 50 + + + 1 + + + + A mix of sun and cloud + 02 + -18 + 10 + -30 + + + 30 + NW + 50 + + + 1 + + + + Mainly sunny + 01 + -16 + 10 + -28 + + + 30 + NW + 50 + + + 1 + + + + A mix of sun and cloud + 02 + -15 + 10 + -26 + + + 30 + NW + 50 + + + 1 + + + + A mix of sun and cloud + 02 + -14 + 10 + -25 + + + 30 + NW + 50 + + + 1 + + + + A mix of sun and cloud + 02 + -14 + 10 + -24 + + + 30 + NW + 50 + + + + A mix of sun and cloud + 02 + -13 + 10 + -23 + + + 30 + NW + 50 + + + + A mix of sun and cloud + 02 + -13 + 10 + -24 + + + 30 + NW + 50 + + + + Partly cloudy + 32 + -14 + 10 + -22 + + + 20 + NW + + + + + Partly cloudy + 32 + -14 + 10 + -23 + + + 20 + NW + + + + + Partly cloudy + 32 + -15 + 10 + -24 + + + 20 + NW + + + + + Partly cloudy + 32 + -16 + 0 + -25 + + + 20 + NW + + + + + Partly cloudy + 32 + -17 + 0 + -24 + + + 10 + NW + + + + + A few clouds + 31 + -18 + 0 + -24 + + + 10 + NW + + + + + A few clouds + 31 + -18 + 0 + -25 + + + 10 + NW + + + + + A few clouds + 31 + -19 + 0 + -26 + + + 10 + NW + + + + + Clear + 30 + -20 + 0 + -27 + + + 10 + NW + + + + + Clear + 30 + -20 + 0 + -28 + + + 10 + NW + + + + + Clear + 30 + -21 + 0 + -28 + + + 10 + NW + + + + + Clear + 30 + -21 + 0 + -28 + + + 10 + NW + + + + + Clear + 30 + -21 + 0 + -28 + + + 10 + N + + + + + Sunny + 00 + -21 + 0 + -28 + + + 10 + N + + + + + + The information provided here, for the times of the rise and set of the sun, is an estimate included as a convenience to our clients. Values shown here may differ from the official sunrise/sunset data available from (http://hia-iha.nrc-cnrc.gc.ca/sunrise_e.html) + + 2026 + 02 + 07 + 12 + 27 + 20260207122700 + Saturday February 07, 2026 at 12:27 UTC + + + 2026 + 02 + 07 + 07 + 27 + 20260207072700 + Saturday February 07, 2026 at 07:27 EST + + + 2026 + 02 + 07 + 22 + 37 + 20260207223700 + Saturday February 07, 2026 at 22:37 UTC + + + 2026 + 02 + 07 + 17 + 37 + 20260207173700 + Saturday February 07, 2026 at 17:37 EST + + + \ No newline at end of file diff --git a/tests/mocks/weather_envcanada_index.html b/tests/mocks/weather_envcanada_index.html new file mode 100644 index 0000000000..93d5a5d4a2 --- /dev/null +++ b/tests/mocks/weather_envcanada_index.html @@ -0,0 +1,427 @@ + + + + Index of /today/citypage_weather/ON/12 + + +

Index of /today/citypage_weather/ON/12

+
Icon  Name                                                     Last modified      Size  Description
[PARENTDIR] Parent Directory - +[   ] 20260207T120044.778Z_MSC_CitypageWeather_s0000024_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120044.827Z_MSC_CitypageWeather_s0000024_fr.xml 2026-02-07 12:00 36K +[   ] 20260207T120044.875Z_MSC_CitypageWeather_s0000022_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120044.919Z_MSC_CitypageWeather_s0000022_fr.xml 2026-02-07 12:00 37K +[   ] 20260207T120045.458Z_MSC_CitypageWeather_s0000588_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120045.502Z_MSC_CitypageWeather_s0000588_fr.xml 2026-02-07 12:00 36K +[   ] 20260207T120047.636Z_MSC_CitypageWeather_s0000546_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120047.636Z_MSC_CitypageWeather_s0000819_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120047.715Z_MSC_CitypageWeather_s0000546_fr.xml 2026-02-07 12:00 37K +[   ] 20260207T120047.715Z_MSC_CitypageWeather_s0000819_fr.xml 2026-02-07 12:00 37K +[   ] 20260207T120047.911Z_MSC_CitypageWeather_s0000646_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120047.960Z_MSC_CitypageWeather_s0000646_fr.xml 2026-02-07 12:00 37K +[   ] 20260207T120048.388Z_MSC_CitypageWeather_s0000512_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120048.388Z_MSC_CitypageWeather_s0000513_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120048.388Z_MSC_CitypageWeather_s0000790_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120048.526Z_MSC_CitypageWeather_s0000512_fr.xml 2026-02-07 12:00 36K +[   ] 20260207T120048.526Z_MSC_CitypageWeather_s0000513_fr.xml 2026-02-07 12:00 37K +[   ] 20260207T120048.526Z_MSC_CitypageWeather_s0000790_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120048.664Z_MSC_CitypageWeather_s0000765_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120048.664Z_MSC_CitypageWeather_s0000766_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120048.752Z_MSC_CitypageWeather_s0000765_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120048.752Z_MSC_CitypageWeather_s0000766_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120048.945Z_MSC_CitypageWeather_s0000782_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120048.994Z_MSC_CitypageWeather_s0000782_fr.xml 2026-02-07 12:00 37K +[   ] 20260207T120049.038Z_MSC_CitypageWeather_s0000585_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120049.038Z_MSC_CitypageWeather_s0000785_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120049.127Z_MSC_CitypageWeather_s0000585_fr.xml 2026-02-07 12:00 37K +[   ] 20260207T120049.127Z_MSC_CitypageWeather_s0000785_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120049.536Z_MSC_CitypageWeather_s0000411_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120049.536Z_MSC_CitypageWeather_s0000659_en.xml 2026-02-07 12:00 36K +[   ] 20260207T120049.536Z_MSC_CitypageWeather_s0000660_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120049.653Z_MSC_CitypageWeather_s0000411_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120049.653Z_MSC_CitypageWeather_s0000659_fr.xml 2026-02-07 12:00 37K +[   ] 20260207T120049.653Z_MSC_CitypageWeather_s0000660_fr.xml 2026-02-07 12:00 38K +[   ] 20260207T120052.583Z_MSC_CitypageWeather_s0000080_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120052.583Z_MSC_CitypageWeather_s0000454_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120052.665Z_MSC_CitypageWeather_s0000080_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120052.665Z_MSC_CitypageWeather_s0000454_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120055.400Z_MSC_CitypageWeather_s0000596_en.xml 2026-02-07 12:01 35K +[   ] 20260207T120055.400Z_MSC_CitypageWeather_s0000597_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120055.471Z_MSC_CitypageWeather_s0000596_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120055.471Z_MSC_CitypageWeather_s0000597_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120117.907Z_MSC_CitypageWeather_s0000744_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120117.907Z_MSC_CitypageWeather_s0000796_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120118.045Z_MSC_CitypageWeather_s0000744_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120118.045Z_MSC_CitypageWeather_s0000796_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120118.904Z_MSC_CitypageWeather_s0000572_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120118.904Z_MSC_CitypageWeather_s0000573_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120119.006Z_MSC_CitypageWeather_s0000572_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120119.006Z_MSC_CitypageWeather_s0000573_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120119.181Z_MSC_CitypageWeather_s0000765_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120119.181Z_MSC_CitypageWeather_s0000766_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120119.228Z_MSC_CitypageWeather_s0000765_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120119.228Z_MSC_CitypageWeather_s0000766_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120119.276Z_MSC_CitypageWeather_s0000395_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120119.276Z_MSC_CitypageWeather_s0000520_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120119.351Z_MSC_CitypageWeather_s0000395_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120119.351Z_MSC_CitypageWeather_s0000520_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120119.429Z_MSC_CitypageWeather_s0000724_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120119.429Z_MSC_CitypageWeather_s0000725_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120119.429Z_MSC_CitypageWeather_s0000726_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120119.429Z_MSC_CitypageWeather_s0000727_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120119.429Z_MSC_CitypageWeather_s0000728_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120119.665Z_MSC_CitypageWeather_s0000724_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120119.665Z_MSC_CitypageWeather_s0000725_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120119.665Z_MSC_CitypageWeather_s0000726_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120119.665Z_MSC_CitypageWeather_s0000727_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120119.665Z_MSC_CitypageWeather_s0000728_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120120.713Z_MSC_CitypageWeather_s0000752_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120120.713Z_MSC_CitypageWeather_s0000753_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120120.815Z_MSC_CitypageWeather_s0000752_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120120.815Z_MSC_CitypageWeather_s0000753_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120121.465Z_MSC_CitypageWeather_s0000538_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120121.465Z_MSC_CitypageWeather_s0000539_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120121.544Z_MSC_CitypageWeather_s0000538_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120121.544Z_MSC_CitypageWeather_s0000539_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120121.909Z_MSC_CitypageWeather_s0000637_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120121.909Z_MSC_CitypageWeather_s0000638_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120121.909Z_MSC_CitypageWeather_s0000639_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120121.909Z_MSC_CitypageWeather_s0000640_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120121.909Z_MSC_CitypageWeather_s0000641_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120121.909Z_MSC_CitypageWeather_s0000642_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120122.236Z_MSC_CitypageWeather_s0000637_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120122.236Z_MSC_CitypageWeather_s0000638_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120122.236Z_MSC_CitypageWeather_s0000639_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120122.236Z_MSC_CitypageWeather_s0000640_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120122.236Z_MSC_CitypageWeather_s0000641_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120122.236Z_MSC_CitypageWeather_s0000642_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120123.442Z_MSC_CitypageWeather_s0000707_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120123.442Z_MSC_CitypageWeather_s0000708_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120123.442Z_MSC_CitypageWeather_s0000710_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120123.575Z_MSC_CitypageWeather_s0000707_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120123.575Z_MSC_CitypageWeather_s0000708_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120123.575Z_MSC_CitypageWeather_s0000710_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120124.159Z_MSC_CitypageWeather_s0000628_en.xml 2026-02-07 12:01 35K +[   ] 20260207T120124.217Z_MSC_CitypageWeather_s0000628_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120125.748Z_MSC_CitypageWeather_s0000629_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120125.748Z_MSC_CitypageWeather_s0000631_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120125.748Z_MSC_CitypageWeather_s0000632_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120125.902Z_MSC_CitypageWeather_s0000629_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120125.902Z_MSC_CitypageWeather_s0000631_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120125.902Z_MSC_CitypageWeather_s0000632_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120126.136Z_MSC_CitypageWeather_s0000650_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120126.136Z_MSC_CitypageWeather_s0000651_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120126.234Z_MSC_CitypageWeather_s0000650_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120126.234Z_MSC_CitypageWeather_s0000651_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120126.402Z_MSC_CitypageWeather_s0000691_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120126.402Z_MSC_CitypageWeather_s0000692_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120126.591Z_MSC_CitypageWeather_s0000691_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120126.591Z_MSC_CitypageWeather_s0000692_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120127.205Z_MSC_CitypageWeather_s0000696_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120127.205Z_MSC_CitypageWeather_s0000697_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120127.205Z_MSC_CitypageWeather_s0000698_en.xml 2026-02-07 12:01 35K +[   ] 20260207T120127.458Z_MSC_CitypageWeather_s0000696_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120127.458Z_MSC_CitypageWeather_s0000697_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120127.458Z_MSC_CitypageWeather_s0000698_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120127.975Z_MSC_CitypageWeather_s0000374_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120128.092Z_MSC_CitypageWeather_s0000374_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120128.201Z_MSC_CitypageWeather_s0000761_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120128.201Z_MSC_CitypageWeather_s0000762_en.xml 2026-02-07 12:01 35K +[   ] 20260207T120128.201Z_MSC_CitypageWeather_s0000764_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120128.320Z_MSC_CitypageWeather_s0000761_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120128.320Z_MSC_CitypageWeather_s0000762_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120128.320Z_MSC_CitypageWeather_s0000764_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120129.744Z_MSC_CitypageWeather_s0000676_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120129.744Z_MSC_CitypageWeather_s0000677_en.xml 2026-02-07 12:01 35K +[   ] 20260207T120129.871Z_MSC_CitypageWeather_s0000676_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120129.871Z_MSC_CitypageWeather_s0000677_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120130.576Z_MSC_CitypageWeather_s0000069_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120131.204Z_MSC_CitypageWeather_s0000069_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120131.735Z_MSC_CitypageWeather_s0000691_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120131.735Z_MSC_CitypageWeather_s0000692_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120131.790Z_MSC_CitypageWeather_s0000691_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120131.790Z_MSC_CitypageWeather_s0000692_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120132.173Z_MSC_CitypageWeather_s0000232_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120132.173Z_MSC_CitypageWeather_s0000233_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120132.291Z_MSC_CitypageWeather_s0000232_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120132.291Z_MSC_CitypageWeather_s0000233_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120132.667Z_MSC_CitypageWeather_s0000325_en.xml 2026-02-07 12:01 39K +[   ] 20260207T120132.667Z_MSC_CitypageWeather_s0000326_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120132.667Z_MSC_CitypageWeather_s0000327_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120132.667Z_MSC_CitypageWeather_s0000328_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120132.667Z_MSC_CitypageWeather_s0000329_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120132.904Z_MSC_CitypageWeather_s0000325_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120132.904Z_MSC_CitypageWeather_s0000326_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120132.904Z_MSC_CitypageWeather_s0000327_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120132.904Z_MSC_CitypageWeather_s0000328_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120132.904Z_MSC_CitypageWeather_s0000329_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120133.465Z_MSC_CitypageWeather_s0000676_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120133.465Z_MSC_CitypageWeather_s0000677_en.xml 2026-02-07 12:01 35K +[   ] 20260207T120133.514Z_MSC_CitypageWeather_s0000676_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120133.514Z_MSC_CitypageWeather_s0000677_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120133.562Z_MSC_CitypageWeather_s0000761_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120133.562Z_MSC_CitypageWeather_s0000762_en.xml 2026-02-07 12:01 35K +[   ] 20260207T120133.562Z_MSC_CitypageWeather_s0000764_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120133.639Z_MSC_CitypageWeather_s0000761_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120133.639Z_MSC_CitypageWeather_s0000762_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120133.639Z_MSC_CitypageWeather_s0000764_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120136.411Z_MSC_CitypageWeather_s0000424_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120136.411Z_MSC_CitypageWeather_s0000425_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120136.411Z_MSC_CitypageWeather_s0000426_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120136.517Z_MSC_CitypageWeather_s0000424_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120136.517Z_MSC_CitypageWeather_s0000425_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120136.517Z_MSC_CitypageWeather_s0000426_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120139.492Z_MSC_CitypageWeather_s0000724_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120139.492Z_MSC_CitypageWeather_s0000725_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120139.492Z_MSC_CitypageWeather_s0000726_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120139.492Z_MSC_CitypageWeather_s0000727_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120139.492Z_MSC_CitypageWeather_s0000728_en.xml 2026-02-07 12:01 38K +[   ] 20260207T120139.618Z_MSC_CitypageWeather_s0000724_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120139.618Z_MSC_CitypageWeather_s0000725_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120139.618Z_MSC_CitypageWeather_s0000726_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120139.618Z_MSC_CitypageWeather_s0000727_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120139.618Z_MSC_CitypageWeather_s0000728_fr.xml 2026-02-07 12:01 39K +[   ] 20260207T120139.808Z_MSC_CitypageWeather_s0000826_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120139.851Z_MSC_CitypageWeather_s0000826_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120147.835Z_MSC_CitypageWeather_s0000548_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120147.835Z_MSC_CitypageWeather_s0000549_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120147.928Z_MSC_CitypageWeather_s0000548_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120147.928Z_MSC_CitypageWeather_s0000549_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120148.018Z_MSC_CitypageWeather_s0000747_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120148.018Z_MSC_CitypageWeather_s0000748_en.xml 2026-02-07 12:01 37K +[   ] 20260207T120148.089Z_MSC_CitypageWeather_s0000747_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120148.089Z_MSC_CitypageWeather_s0000748_fr.xml 2026-02-07 12:01 38K +[   ] 20260207T120148.161Z_MSC_CitypageWeather_s0000231_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120148.194Z_MSC_CitypageWeather_s0000231_fr.xml 2026-02-07 12:01 36K +[   ] 20260207T120150.484Z_MSC_CitypageWeather_s0000071_en.xml 2026-02-07 12:01 36K +[   ] 20260207T120150.649Z_MSC_CitypageWeather_s0000071_fr.xml 2026-02-07 12:01 37K +[   ] 20260207T120153.235Z_MSC_CitypageWeather_s0000023_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120153.276Z_MSC_CitypageWeather_s0000023_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120153.480Z_MSC_CitypageWeather_s0000072_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120153.480Z_MSC_CitypageWeather_s0000077_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120153.480Z_MSC_CitypageWeather_s0000434_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120153.480Z_MSC_CitypageWeather_s0000435_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120153.480Z_MSC_CitypageWeather_s0000436_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120153.708Z_MSC_CitypageWeather_s0000072_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120153.708Z_MSC_CitypageWeather_s0000077_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120153.708Z_MSC_CitypageWeather_s0000434_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120153.708Z_MSC_CitypageWeather_s0000435_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120153.708Z_MSC_CitypageWeather_s0000436_fr.xml 2026-02-07 12:02 38K +[   ] 20260207T120153.926Z_MSC_CitypageWeather_s0000437_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120153.960Z_MSC_CitypageWeather_s0000437_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120154.081Z_MSC_CitypageWeather_s0000073_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120154.081Z_MSC_CitypageWeather_s0000074_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120154.081Z_MSC_CitypageWeather_s0000075_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120154.216Z_MSC_CitypageWeather_s0000073_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120154.216Z_MSC_CitypageWeather_s0000074_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120154.216Z_MSC_CitypageWeather_s0000075_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120205.167Z_MSC_CitypageWeather_s0000428_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120205.205Z_MSC_CitypageWeather_s0000428_fr.xml 2026-02-07 12:02 36K +[   ] 20260207T120207.885Z_MSC_CitypageWeather_s0000680_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120207.885Z_MSC_CitypageWeather_s0000843_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120207.961Z_MSC_CitypageWeather_s0000680_fr.xml 2026-02-07 12:02 38K +[   ] 20260207T120207.961Z_MSC_CitypageWeather_s0000843_fr.xml 2026-02-07 12:02 38K +[   ] 20260207T120210.405Z_MSC_CitypageWeather_s0000455_en.xml 2026-02-07 12:02 38K +[   ] 20260207T120210.451Z_MSC_CitypageWeather_s0000455_fr.xml 2026-02-07 12:02 39K +[   ] 20260207T120210.675Z_MSC_CitypageWeather_s0000367_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120210.675Z_MSC_CitypageWeather_s0000368_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120210.758Z_MSC_CitypageWeather_s0000367_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120210.758Z_MSC_CitypageWeather_s0000368_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120211.358Z_MSC_CitypageWeather_s0000251_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120211.408Z_MSC_CitypageWeather_s0000251_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120221.954Z_MSC_CitypageWeather_s0000418_en.xml 2026-02-07 12:02 35K +[   ] 20260207T120221.954Z_MSC_CitypageWeather_s0000419_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120222.043Z_MSC_CitypageWeather_s0000418_fr.xml 2026-02-07 12:02 36K +[   ] 20260207T120222.043Z_MSC_CitypageWeather_s0000419_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120222.347Z_MSC_CitypageWeather_s0000451_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120222.347Z_MSC_CitypageWeather_s0000452_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120222.448Z_MSC_CitypageWeather_s0000451_fr.xml 2026-02-07 12:02 38K +[   ] 20260207T120222.448Z_MSC_CitypageWeather_s0000452_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120223.004Z_MSC_CitypageWeather_s0000550_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120223.050Z_MSC_CitypageWeather_s0000550_fr.xml 2026-02-07 12:02 38K +[   ] 20260207T120223.502Z_MSC_CitypageWeather_s0000763_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120223.539Z_MSC_CitypageWeather_s0000763_fr.xml 2026-02-07 12:02 36K +[   ] 20260207T120223.577Z_MSC_CitypageWeather_s0000469_en.xml 2026-02-07 12:02 38K +[   ] 20260207T120223.577Z_MSC_CitypageWeather_s0000470_en.xml 2026-02-07 12:02 38K +[   ] 20260207T120223.660Z_MSC_CitypageWeather_s0000469_fr.xml 2026-02-07 12:02 39K +[   ] 20260207T120223.660Z_MSC_CitypageWeather_s0000470_fr.xml 2026-02-07 12:02 39K +[   ] 20260207T120223.753Z_MSC_CitypageWeather_s0000103_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120223.753Z_MSC_CitypageWeather_s0000105_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120223.839Z_MSC_CitypageWeather_s0000103_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120223.839Z_MSC_CitypageWeather_s0000105_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120225.159Z_MSC_CitypageWeather_s0000528_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120225.159Z_MSC_CitypageWeather_s0000529_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120225.159Z_MSC_CitypageWeather_s0000530_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120225.159Z_MSC_CitypageWeather_s0000531_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120225.356Z_MSC_CitypageWeather_s0000528_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120225.356Z_MSC_CitypageWeather_s0000529_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120225.356Z_MSC_CitypageWeather_s0000530_fr.xml 2026-02-07 12:02 38K +[   ] 20260207T120225.356Z_MSC_CitypageWeather_s0000531_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120226.518Z_MSC_CitypageWeather_s0000582_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120226.518Z_MSC_CitypageWeather_s0000584_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120226.518Z_MSC_CitypageWeather_s0000773_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120226.630Z_MSC_CitypageWeather_s0000582_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120226.630Z_MSC_CitypageWeather_s0000584_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120226.630Z_MSC_CitypageWeather_s0000773_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120228.362Z_MSC_CitypageWeather_s0000235_en.xml 2026-02-07 12:02 38K +[   ] 20260207T120228.362Z_MSC_CitypageWeather_s0000236_en.xml 2026-02-07 12:02 38K +[   ] 20260207T120228.362Z_MSC_CitypageWeather_s0000237_en.xml 2026-02-07 12:02 38K +[   ] 20260207T120228.362Z_MSC_CitypageWeather_s0000238_en.xml 2026-02-07 12:02 38K +[   ] 20260207T120228.362Z_MSC_CitypageWeather_s0000240_en.xml 2026-02-07 12:02 38K +[   ] 20260207T120228.597Z_MSC_CitypageWeather_s0000235_fr.xml 2026-02-07 12:02 39K +[   ] 20260207T120228.597Z_MSC_CitypageWeather_s0000236_fr.xml 2026-02-07 12:02 39K +[   ] 20260207T120228.597Z_MSC_CitypageWeather_s0000237_fr.xml 2026-02-07 12:02 39K +[   ] 20260207T120228.597Z_MSC_CitypageWeather_s0000238_fr.xml 2026-02-07 12:02 39K +[   ] 20260207T120228.597Z_MSC_CitypageWeather_s0000240_fr.xml 2026-02-07 12:02 39K +[   ] 20260207T120228.829Z_MSC_CitypageWeather_s0000127_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120228.874Z_MSC_CitypageWeather_s0000127_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120238.436Z_MSC_CitypageWeather_s0000700_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120238.436Z_MSC_CitypageWeather_s0000701_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120238.436Z_MSC_CitypageWeather_s0000702_en.xml 2026-02-07 12:03 37K +[   ] 20260207T120238.436Z_MSC_CitypageWeather_s0000703_en.xml 2026-02-07 12:02 37K +[   ] 20260207T120238.436Z_MSC_CitypageWeather_s0000704_en.xml 2026-02-07 12:03 37K +[   ] 20260207T120238.621Z_MSC_CitypageWeather_s0000700_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120238.621Z_MSC_CitypageWeather_s0000701_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120238.621Z_MSC_CitypageWeather_s0000702_fr.xml 2026-02-07 12:02 38K +[   ] 20260207T120238.621Z_MSC_CitypageWeather_s0000703_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120238.621Z_MSC_CitypageWeather_s0000704_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120240.742Z_MSC_CitypageWeather_s0000104_en.xml 2026-02-07 12:02 36K +[   ] 20260207T120240.780Z_MSC_CitypageWeather_s0000104_fr.xml 2026-02-07 12:02 37K +[   ] 20260207T120252.049Z_MSC_CitypageWeather_s0000431_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120252.088Z_MSC_CitypageWeather_s0000431_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120253.001Z_MSC_CitypageWeather_s0000169_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120253.050Z_MSC_CitypageWeather_s0000169_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120255.032Z_MSC_CitypageWeather_s0000108_en.xml 2026-02-07 12:03 38K +[   ] 20260207T120255.032Z_MSC_CitypageWeather_s0000429_en.xml 2026-02-07 12:03 38K +[   ] 20260207T120255.032Z_MSC_CitypageWeather_s0000489_en.xml 2026-02-07 12:03 38K +[   ] 20260207T120255.158Z_MSC_CitypageWeather_s0000108_fr.xml 2026-02-07 12:03 39K +[   ] 20260207T120255.158Z_MSC_CitypageWeather_s0000429_fr.xml 2026-02-07 12:03 39K +[   ] 20260207T120255.158Z_MSC_CitypageWeather_s0000489_fr.xml 2026-02-07 12:03 39K +[   ] 20260207T120305.479Z_MSC_CitypageWeather_s0000705_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120305.479Z_MSC_CitypageWeather_s0000706_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120305.555Z_MSC_CitypageWeather_s0000705_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120305.555Z_MSC_CitypageWeather_s0000706_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120307.995Z_MSC_CitypageWeather_s0000517_en.xml 2026-02-07 12:03 35K +[   ] 20260207T120308.045Z_MSC_CitypageWeather_s0000517_fr.xml 2026-02-07 12:03 36K +[   ] 20260207T120312.670Z_MSC_CitypageWeather_s0000076_en.xml 2026-02-07 12:03 38K +[   ] 20260207T120312.703Z_MSC_CitypageWeather_s0000076_fr.xml 2026-02-07 12:03 39K +[   ] 20260207T120312.743Z_MSC_CitypageWeather_s0000281_en.xml 2026-02-07 12:03 37K +[   ] 20260207T120312.743Z_MSC_CitypageWeather_s0000414_en.xml 2026-02-07 12:03 37K +[   ] 20260207T120312.743Z_MSC_CitypageWeather_s0000415_en.xml 2026-02-07 12:03 38K +[   ] 20260207T120312.872Z_MSC_CitypageWeather_s0000281_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120312.872Z_MSC_CitypageWeather_s0000414_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120312.872Z_MSC_CitypageWeather_s0000415_fr.xml 2026-02-07 12:03 39K +[   ] 20260207T120323.523Z_MSC_CitypageWeather_s0000301_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120323.523Z_MSC_CitypageWeather_s0000302_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120323.523Z_MSC_CitypageWeather_s0000303_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120323.523Z_MSC_CitypageWeather_s0000304_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120323.523Z_MSC_CitypageWeather_s0000305_en.xml 2026-02-07 12:03 37K +[   ] 20260207T120323.760Z_MSC_CitypageWeather_s0000301_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120323.760Z_MSC_CitypageWeather_s0000302_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120323.760Z_MSC_CitypageWeather_s0000303_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120323.760Z_MSC_CitypageWeather_s0000304_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120323.760Z_MSC_CitypageWeather_s0000305_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120324.150Z_MSC_CitypageWeather_s0000168_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120324.203Z_MSC_CitypageWeather_s0000168_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120324.794Z_MSC_CitypageWeather_s0000165_en.xml 2026-02-07 12:03 38K +[   ] 20260207T120324.794Z_MSC_CitypageWeather_s0000166_en.xml 2026-02-07 12:03 38K +[   ] 20260207T120324.879Z_MSC_CitypageWeather_s0000165_fr.xml 2026-02-07 12:03 39K +[   ] 20260207T120324.879Z_MSC_CitypageWeather_s0000166_fr.xml 2026-02-07 12:03 39K +[   ] 20260207T120326.004Z_MSC_CitypageWeather_s0000266_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120326.004Z_MSC_CitypageWeather_s0000267_en.xml 2026-02-07 12:03 36K +[   ] 20260207T120326.077Z_MSC_CitypageWeather_s0000266_fr.xml 2026-02-07 12:03 37K +[   ] 20260207T120326.077Z_MSC_CitypageWeather_s0000267_fr.xml 2026-02-07 12:03 36K +[   ] 20260207T120334.963Z_MSC_CitypageWeather_s0000571_en.xml 2026-02-07 12:04 38K +[   ] 20260207T120335.008Z_MSC_CitypageWeather_s0000571_fr.xml 2026-02-07 12:04 39K +[   ] 20260207T120407.043Z_MSC_CitypageWeather_s0000422_en.xml 2026-02-07 12:04 38K +[   ] 20260207T120407.081Z_MSC_CitypageWeather_s0000422_fr.xml 2026-02-07 12:04 39K +[   ] 20260207T120410.902Z_MSC_CitypageWeather_s0000070_en.xml 2026-02-07 12:04 36K +[   ] 20260207T120410.951Z_MSC_CitypageWeather_s0000070_fr.xml 2026-02-07 12:04 37K +[   ] 20260207T120421.782Z_MSC_CitypageWeather_s0000458_en.xml 2026-02-07 12:04 37K +[   ] 20260207T120421.782Z_MSC_CitypageWeather_s0000658_en.xml 2026-02-07 12:05 37K +[   ] 20260207T120421.782Z_MSC_CitypageWeather_s0000786_en.xml 2026-02-07 12:04 37K +[   ] 20260207T120421.782Z_MSC_CitypageWeather_s0000787_en.xml 2026-02-07 12:05 38K +[   ] 20260207T120421.782Z_MSC_CitypageWeather_s0000789_en.xml 2026-02-07 12:04 37K +[   ] 20260207T120421.980Z_MSC_CitypageWeather_s0000458_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120421.980Z_MSC_CitypageWeather_s0000658_fr.xml 2026-02-07 12:04 37K +[   ] 20260207T120421.980Z_MSC_CitypageWeather_s0000786_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120421.980Z_MSC_CitypageWeather_s0000787_fr.xml 2026-02-07 12:04 39K +[   ] 20260207T120421.980Z_MSC_CitypageWeather_s0000789_fr.xml 2026-02-07 12:04 37K +[   ] 20260207T120503.727Z_MSC_CitypageWeather_s0000729_en.xml 2026-02-07 12:05 36K +[   ] 20260207T120503.727Z_MSC_CitypageWeather_s0000730_en.xml 2026-02-07 12:05 36K +[   ] 20260207T120503.727Z_MSC_CitypageWeather_s0000731_en.xml 2026-02-07 12:05 37K +[   ] 20260207T120503.727Z_MSC_CitypageWeather_s0000732_en.xml 2026-02-07 12:05 36K +[   ] 20260207T120503.926Z_MSC_CitypageWeather_s0000729_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120503.926Z_MSC_CitypageWeather_s0000730_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120503.926Z_MSC_CitypageWeather_s0000731_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120503.926Z_MSC_CitypageWeather_s0000732_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.127Z_MSC_CitypageWeather_s0000430_en.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.127Z_MSC_CitypageWeather_s0000623_en.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.217Z_MSC_CitypageWeather_s0000430_fr.xml 2026-02-07 12:05 38K +[   ] 20260207T120504.217Z_MSC_CitypageWeather_s0000623_fr.xml 2026-02-07 12:05 38K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000025_en.xml 2026-02-07 12:05 34K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000025_fr.xml 2026-02-07 12:05 35K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000088_en.xml 2026-02-07 12:05 34K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000088_fr.xml 2026-02-07 12:05 35K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000239_en.xml 2026-02-07 12:05 36K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000239_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000282_en.xml 2026-02-07 12:05 36K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000282_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000283_en.xml 2026-02-07 12:05 36K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000283_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000479_en.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000479_fr.xml 2026-02-07 12:05 38K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000630_en.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000630_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000815_en.xml 2026-02-07 12:05 36K +[   ] 20260207T120504.532Z_MSC_CitypageWeather_s0000815_fr.xml 2026-02-07 12:05 37K +[   ] 20260207T120611.878Z_MSC_CitypageWeather_s0000528_en.xml 2026-02-07 12:07 37K +[   ] 20260207T120611.878Z_MSC_CitypageWeather_s0000529_en.xml 2026-02-07 12:07 37K +[   ] 20260207T120611.878Z_MSC_CitypageWeather_s0000530_en.xml 2026-02-07 12:07 37K +[   ] 20260207T120611.878Z_MSC_CitypageWeather_s0000531_en.xml 2026-02-07 12:07 37K +[   ] 20260207T120611.965Z_MSC_CitypageWeather_s0000528_fr.xml 2026-02-07 12:06 38K +[   ] 20260207T120611.965Z_MSC_CitypageWeather_s0000529_fr.xml 2026-02-07 12:07 37K +[   ] 20260207T120611.965Z_MSC_CitypageWeather_s0000530_fr.xml 2026-02-07 12:07 38K +[   ] 20260207T120611.965Z_MSC_CitypageWeather_s0000531_fr.xml 2026-02-07 12:07 38K +[   ] 20260207T120612.072Z_MSC_CitypageWeather_s0000479_en.xml 2026-02-07 12:07 37K +[   ] 20260207T120612.109Z_MSC_CitypageWeather_s0000479_fr.xml 2026-02-07 12:07 38K +[   ] 20260207T120622.544Z_MSC_CitypageWeather_s0000630_en.xml 2026-02-07 12:07 37K +[   ] 20260207T120622.567Z_MSC_CitypageWeather_s0000630_fr.xml 2026-02-07 12:07 37K +[   ] 20260207T120622.795Z_MSC_CitypageWeather_s0000782_en.xml 2026-02-07 12:07 36K +[   ] 20260207T120622.821Z_MSC_CitypageWeather_s0000782_fr.xml 2026-02-07 12:07 37K +[   ] 20260207T120723.672Z_MSC_CitypageWeather_s0000588_en.xml 2026-02-07 12:08 36K +[   ] 20260207T120723.699Z_MSC_CitypageWeather_s0000588_fr.xml 2026-02-07 12:08 36K +[   ] 20260207T120740.860Z_MSC_CitypageWeather_s0000691_en.xml 2026-02-07 12:08 38K +[   ] 20260207T120740.860Z_MSC_CitypageWeather_s0000692_en.xml 2026-02-07 12:08 38K +[   ] 20260207T120740.911Z_MSC_CitypageWeather_s0000691_fr.xml 2026-02-07 12:08 39K +[   ] 20260207T120740.911Z_MSC_CitypageWeather_s0000692_fr.xml 2026-02-07 12:08 39K +[   ] 20260207T121451.572Z_MSC_CitypageWeather_s0000458_en.xml 2026-02-07 12:15 37K +[   ] 20260207T121451.572Z_MSC_CitypageWeather_s0000658_en.xml 2026-02-07 12:15 37K +[   ] 20260207T121451.572Z_MSC_CitypageWeather_s0000786_en.xml 2026-02-07 12:15 37K +[   ] 20260207T121451.572Z_MSC_CitypageWeather_s0000787_en.xml 2026-02-07 12:15 38K +[   ] 20260207T121451.572Z_MSC_CitypageWeather_s0000789_en.xml 2026-02-07 12:15 37K +[   ] 20260207T121451.691Z_MSC_CitypageWeather_s0000458_fr.xml 2026-02-07 12:15 37K +[   ] 20260207T121451.691Z_MSC_CitypageWeather_s0000658_fr.xml 2026-02-07 12:15 37K +[   ] 20260207T121451.691Z_MSC_CitypageWeather_s0000786_fr.xml 2026-02-07 12:15 37K +[   ] 20260207T121451.691Z_MSC_CitypageWeather_s0000787_fr.xml 2026-02-07 12:15 39K +[   ] 20260207T121451.691Z_MSC_CitypageWeather_s0000789_fr.xml 2026-02-07 12:15 37K +[   ] 20260207T122801.995Z_MSC_CitypageWeather_s0000430_en.xml 2026-02-07 12:28 37K +[   ] 20260207T122801.995Z_MSC_CitypageWeather_s0000623_en.xml 2026-02-07 12:28 37K +[   ] 20260207T122802.053Z_MSC_CitypageWeather_s0000430_fr.xml 2026-02-07 12:28 38K +[   ] 20260207T122802.053Z_MSC_CitypageWeather_s0000623_fr.xml 2026-02-07 12:28 38K +[   ] 20260207T124745.464Z_MSC_CitypageWeather_s0000752_en.xml 2026-02-07 12:47 36K +[   ] 20260207T124745.464Z_MSC_CitypageWeather_s0000753_en.xml 2026-02-07 12:47 36K +[   ] 20260207T124745.526Z_MSC_CitypageWeather_s0000752_fr.xml 2026-02-07 12:47 37K +[   ] 20260207T124745.526Z_MSC_CitypageWeather_s0000753_fr.xml 2026-02-07 12:47 37K +[   ] 20260207T124815.922Z_MSC_CitypageWeather_s0000458_en.xml 2026-02-07 12:48 37K +[   ] 20260207T124815.922Z_MSC_CitypageWeather_s0000658_en.xml 2026-02-07 12:48 37K +[   ] 20260207T124815.922Z_MSC_CitypageWeather_s0000786_en.xml 2026-02-07 12:48 37K +[   ] 20260207T124815.922Z_MSC_CitypageWeather_s0000787_en.xml 2026-02-07 12:48 38K +[   ] 20260207T124815.922Z_MSC_CitypageWeather_s0000789_en.xml 2026-02-07 12:48 37K +[   ] 20260207T124816.077Z_MSC_CitypageWeather_s0000458_fr.xml 2026-02-07 12:48 37K +[   ] 20260207T124816.077Z_MSC_CitypageWeather_s0000658_fr.xml 2026-02-07 12:48 37K +[   ] 20260207T124816.077Z_MSC_CitypageWeather_s0000786_fr.xml 2026-02-07 12:48 37K +[   ] 20260207T124816.077Z_MSC_CitypageWeather_s0000787_fr.xml 2026-02-07 12:48 39K +[   ] 20260207T124816.077Z_MSC_CitypageWeather_s0000789_fr.xml 2026-02-07 12:48 37K +
+ + diff --git a/tests/mocks/weather_onecall_current.json b/tests/mocks/weather_onecall_current.json new file mode 100644 index 0000000000..73b88d7a11 --- /dev/null +++ b/tests/mocks/weather_onecall_current.json @@ -0,0 +1,28 @@ +{ + "lat": 48.14, + "lon": 11.58, + "timezone": "Europe/Berlin", + "timezone_offset": 0, + "current": { + "dt": 1547387400, + "sunrise": 1547362817, + "sunset": 1547394301, + "temp": 1.49, + "feels_like": -5.6, + "pressure": 1005, + "humidity": 93.7, + "uvi": 0, + "clouds": 75, + "visibility": 7000, + "wind_speed": 11.8, + "wind_deg": 250, + "weather": [ + { + "id": 615, + "main": "Snow", + "description": "light rain and snow", + "icon": "13d" + } + ] + } +} diff --git a/tests/mocks/weather_onecall_forecast.json b/tests/mocks/weather_onecall_forecast.json new file mode 100644 index 0000000000..aa70f6e597 --- /dev/null +++ b/tests/mocks/weather_onecall_forecast.json @@ -0,0 +1,149 @@ +{ + "lat": 48.14, + "lon": 11.58, + "timezone": "Europe/Berlin", + "timezone_offset": 3600, + "daily": [ + { + "dt": 1568372400, + "sunrise": 1568350044, + "sunset": 1568395948, + "temp": { + "day": 24.44, + "min": 15.35, + "max": 24.44, + "night": 15.35, + "eve": 18, + "morn": 23.03 + }, + "pressure": 1031, + "humidity": 70, + "wind_speed": 3.35, + "wind_deg": 314, + "weather": [ + { + "id": 801, + "main": "Clouds", + "description": "few clouds", + "icon": "02d" + } + ], + "clouds": 21, + "pop": 0, + "uvi": 5 + }, + { + "dt": 1568458800, + "sunrise": 1568436525, + "sunset": 1568482223, + "temp": { + "day": 20.81, + "min": 13.56, + "max": 21.02, + "night": 13.56, + "eve": 16.6, + "morn": 15.88 + }, + "pressure": 1028, + "humidity": 72, + "wind_speed": 2.78, + "wind_deg": 266, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "clouds": 21, + "pop": 0.56, + "rain": 2.51, + "uvi": 4.5 + }, + { + "dt": 1568545200, + "sunrise": 1568523006, + "sunset": 1568568498, + "temp": { + "day": 22.93, + "min": 13.78, + "max": 22.93, + "night": 13.78, + "eve": 17.21, + "morn": 14.56 + }, + "pressure": 1024, + "humidity": 59, + "wind_speed": 2.17, + "wind_deg": 255, + "weather": [ + { + "id": 800, + "main": "Clear", + "description": "clear sky", + "icon": "01d" + } + ], + "clouds": 0, + "pop": 0, + "uvi": 5.2 + }, + { + "dt": 1568631600, + "sunrise": 1568609487, + "sunset": 1568654774, + "temp": { + "day": 23.39, + "min": 13.93, + "max": 23.39, + "night": 13.93, + "eve": 17.98, + "morn": 15.05 + }, + "pressure": 1023, + "humidity": 57, + "wind_speed": 1.93, + "wind_deg": 236, + "weather": [ + { + "id": 800, + "main": "Clear", + "description": "clear sky", + "icon": "01d" + } + ], + "clouds": 0, + "pop": 0, + "uvi": 5.1 + }, + { + "dt": 1568718000, + "sunrise": 1568695968, + "sunset": 1568741049, + "temp": { + "day": 20.64, + "min": 10.87, + "max": 20.64, + "night": 10.87, + "eve": 15.21, + "morn": 13.67 + }, + "pressure": 1021, + "humidity": 64, + "wind_speed": 2.44, + "wind_deg": 284, + "weather": [ + { + "id": 800, + "main": "Clear", + "description": "clear sky", + "icon": "01d" + } + ], + "clouds": 3, + "pop": 0, + "uvi": 4.9 + } + ] +} diff --git a/tests/mocks/weather_hourly.json b/tests/mocks/weather_onecall_hourly.json similarity index 99% rename from tests/mocks/weather_hourly.json rename to tests/mocks/weather_onecall_hourly.json index b0b2e66245..bcf2b806f6 100644 --- a/tests/mocks/weather_hourly.json +++ b/tests/mocks/weather_onecall_hourly.json @@ -1,7 +1,11 @@ { + "lat": 48.14, + "lon": 11.58, + "timezone": "Europe/Berlin", + "timezone_offset": 3600, "hourly": [ { - "dt": 1673204400, + "dt": 1673200800, "temp": 27.31, "feels_like": 29.59, "pressure": 1013, @@ -24,7 +28,7 @@ "pop": 0 }, { - "dt": 1673208000, + "dt": 1673204400, "temp": 27.31, "feels_like": 29.69, "pressure": 1013, @@ -47,7 +51,7 @@ "pop": 0 }, { - "dt": 1673211600, + "dt": 1673208000, "temp": 27.29, "feels_like": 29.65, "pressure": 1013, @@ -70,7 +74,7 @@ "pop": 0.12 }, { - "dt": 1673215200, + "dt": 1673211600, "temp": 27.21, "feels_like": 29.6, "pressure": 1013, @@ -96,7 +100,7 @@ } }, { - "dt": 1673218800, + "dt": 1673215200, "temp": 27.1, "feels_like": 29.39, "pressure": 1014, @@ -122,7 +126,7 @@ } }, { - "dt": 1673222400, + "dt": 1673218800, "temp": 26.95, "feels_like": 29.19, "pressure": 1013, @@ -145,7 +149,7 @@ "pop": 0.52 }, { - "dt": 1673226000, + "dt": 1673222400, "temp": 26.72, "feels_like": 28.83, "pressure": 1012, @@ -168,7 +172,7 @@ "pop": 0.08 }, { - "dt": 1673229600, + "dt": 1673226000, "temp": 26.57, "feels_like": 26.57, "pressure": 1012, @@ -191,7 +195,7 @@ "pop": 0.08 }, { - "dt": 1673233200, + "dt": 1673229600, "temp": 26.46, "feels_like": 26.46, "pressure": 1011, @@ -214,7 +218,7 @@ "pop": 0.04 }, { - "dt": 1673236800, + "dt": 1673233200, "temp": 26.38, "feels_like": 26.38, "pressure": 1011, @@ -237,7 +241,7 @@ "pop": 0 }, { - "dt": 1673240400, + "dt": 1673236800, "temp": 26.32, "feels_like": 26.32, "pressure": 1012, @@ -260,7 +264,7 @@ "pop": 0 }, { - "dt": 1673244000, + "dt": 1673240400, "temp": 26.32, "feels_like": 26.32, "pressure": 1012, @@ -283,7 +287,7 @@ "pop": 0 }, { - "dt": 1673247600, + "dt": 1673244000, "temp": 26.44, "feels_like": 26.44, "pressure": 1013, @@ -306,7 +310,7 @@ "pop": 0 }, { - "dt": 1673251200, + "dt": 1673247600, "temp": 26.45, "feels_like": 26.45, "pressure": 1013, @@ -329,7 +333,7 @@ "pop": 0 }, { - "dt": 1673254800, + "dt": 1673251200, "temp": 26.54, "feels_like": 26.54, "pressure": 1014, @@ -352,7 +356,7 @@ "pop": 0 }, { - "dt": 1673258400, + "dt": 1673254800, "temp": 26.61, "feels_like": 26.61, "pressure": 1013, @@ -375,7 +379,7 @@ "pop": 0 }, { - "dt": 1673262000, + "dt": 1673258400, "temp": 26.76, "feels_like": 28.9, "pressure": 1013, @@ -398,7 +402,7 @@ "pop": 0 }, { - "dt": 1673265600, + "dt": 1673262000, "temp": 26.91, "feels_like": 29.11, "pressure": 1012, @@ -421,7 +425,7 @@ "pop": 0 }, { - "dt": 1673269200, + "dt": 1673265600, "temp": 27.04, "feels_like": 29.27, "pressure": 1011, @@ -444,7 +448,7 @@ "pop": 0 }, { - "dt": 1673272800, + "dt": 1673269200, "temp": 27.12, "feels_like": 29.33, "pressure": 1011, @@ -467,7 +471,7 @@ "pop": 0 }, { - "dt": 1673276400, + "dt": 1673272800, "temp": 27.17, "feels_like": 29.33, "pressure": 1010, @@ -490,7 +494,7 @@ "pop": 0 }, { - "dt": 1673280000, + "dt": 1673276400, "temp": 27.28, "feels_like": 29.43, "pressure": 1011, @@ -513,7 +517,7 @@ "pop": 0 }, { - "dt": 1673283600, + "dt": 1673280000, "temp": 27.28, "feels_like": 29.43, "pressure": 1011, @@ -536,7 +540,7 @@ "pop": 0 }, { - "dt": 1673287200, + "dt": 1673283600, "temp": 27.34, "feels_like": 29.54, "pressure": 1012, @@ -559,7 +563,7 @@ "pop": 0 }, { - "dt": 1673290800, + "dt": 1673287200, "temp": 27.25, "feels_like": 29.38, "pressure": 1013, @@ -582,7 +586,7 @@ "pop": 0 }, { - "dt": 1673294400, + "dt": 1673290800, "temp": 27.25, "feels_like": 29.38, "pressure": 1014, @@ -605,7 +609,7 @@ "pop": 0 }, { - "dt": 1673298000, + "dt": 1673294400, "temp": 27.17, "feels_like": 29.24, "pressure": 1015, @@ -628,7 +632,7 @@ "pop": 0 }, { - "dt": 1673301600, + "dt": 1673298000, "temp": 27.07, "feels_like": 29.06, "pressure": 1015, @@ -651,7 +655,7 @@ "pop": 0 }, { - "dt": 1673305200, + "dt": 1673301600, "temp": 26.99, "feels_like": 29.09, "pressure": 1014, @@ -674,7 +678,7 @@ "pop": 0 }, { - "dt": 1673308800, + "dt": 1673305200, "temp": 26.83, "feels_like": 28.8, "pressure": 1014, @@ -697,7 +701,7 @@ "pop": 0 }, { - "dt": 1673312400, + "dt": 1673308800, "temp": 26.68, "feels_like": 28.54, "pressure": 1013, @@ -720,7 +724,7 @@ "pop": 0 }, { - "dt": 1673316000, + "dt": 1673312400, "temp": 26.54, "feels_like": 26.54, "pressure": 1013, @@ -743,7 +747,7 @@ "pop": 0 }, { - "dt": 1673319600, + "dt": 1673316000, "temp": 26.54, "feels_like": 26.54, "pressure": 1012, @@ -766,7 +770,7 @@ "pop": 0 }, { - "dt": 1673323200, + "dt": 1673319600, "temp": 26.43, "feels_like": 26.43, "pressure": 1012, @@ -789,7 +793,7 @@ "pop": 0 }, { - "dt": 1673326800, + "dt": 1673323200, "temp": 26.38, "feels_like": 26.38, "pressure": 1013, @@ -812,7 +816,7 @@ "pop": 0 }, { - "dt": 1673330400, + "dt": 1673326800, "temp": 26.36, "feels_like": 26.36, "pressure": 1013, @@ -835,7 +839,7 @@ "pop": 0 }, { - "dt": 1673334000, + "dt": 1673330400, "temp": 26.45, "feels_like": 26.45, "pressure": 1014, @@ -858,7 +862,7 @@ "pop": 0 }, { - "dt": 1673337600, + "dt": 1673334000, "temp": 26.54, "feels_like": 26.54, "pressure": 1014, @@ -881,7 +885,7 @@ "pop": 0 }, { - "dt": 1673341200, + "dt": 1673337600, "temp": 26.63, "feels_like": 26.63, "pressure": 1014, @@ -904,7 +908,7 @@ "pop": 0 }, { - "dt": 1673344800, + "dt": 1673341200, "temp": 26.62, "feels_like": 26.62, "pressure": 1014, @@ -927,7 +931,7 @@ "pop": 0 }, { - "dt": 1673348400, + "dt": 1673344800, "temp": 26.71, "feels_like": 28.81, "pressure": 1014, @@ -950,7 +954,7 @@ "pop": 0 }, { - "dt": 1673352000, + "dt": 1673348400, "temp": 26.81, "feels_like": 29, "pressure": 1013, @@ -973,7 +977,7 @@ "pop": 0 }, { - "dt": 1673355600, + "dt": 1673352000, "temp": 26.91, "feels_like": 29.19, "pressure": 1012, @@ -996,7 +1000,7 @@ "pop": 0 }, { - "dt": 1673359200, + "dt": 1673355600, "temp": 27.02, "feels_like": 29.32, "pressure": 1012, @@ -1019,7 +1023,7 @@ "pop": 0 }, { - "dt": 1673362800, + "dt": 1673359200, "temp": 27.03, "feels_like": 29.25, "pressure": 1011, @@ -1042,7 +1046,7 @@ "pop": 0 }, { - "dt": 1673366400, + "dt": 1673362800, "temp": 27.12, "feels_like": 29.42, "pressure": 1011, @@ -1065,7 +1069,7 @@ "pop": 0 }, { - "dt": 1673370000, + "dt": 1673366400, "temp": 27.1, "feels_like": 29.29, "pressure": 1012, @@ -1088,7 +1092,7 @@ "pop": 0 }, { - "dt": 1673373600, + "dt": 1673370000, "temp": 27.18, "feels_like": 29.54, "pressure": 1012, diff --git a/tests/mocks/weather_openmeteo_current.json b/tests/mocks/weather_openmeteo_current.json new file mode 100644 index 0000000000..478ee1d161 --- /dev/null +++ b/tests/mocks/weather_openmeteo_current.json @@ -0,0 +1,218 @@ +{ + "latitude": 40.78858, + "longitude": -73.9661, + "generationtime_ms": 0.7585287094116211, + "utc_offset_seconds": -18000, + "timezone": "America/New_York", + "timezone_abbreviation": "GMT-5", + "elevation": 20.0, + "current_units": { "time": "iso8601", "interval": "seconds", "temperature_2m": "°C", "relative_humidity_2m": "%", "weather_code": "wmo code", "wind_speed_10m": "km/h", "wind_direction_10m": "°" }, + "current": { "time": "2026-02-06T16:30", "interval": 900, "temperature_2m": -1.4, "relative_humidity_2m": 60, "weather_code": 3, "wind_speed_10m": 4.8, "wind_direction_10m": 138 }, + "hourly_units": { "time": "iso8601", "temperature_2m": "°C", "precipitation": "mm", "weather_code": "wmo code", "wind_speed_10m": "km/h" }, + "hourly": { + "time": [ + "2026-02-06T00:00", + "2026-02-06T01:00", + "2026-02-06T02:00", + "2026-02-06T03:00", + "2026-02-06T04:00", + "2026-02-06T05:00", + "2026-02-06T06:00", + "2026-02-06T07:00", + "2026-02-06T08:00", + "2026-02-06T09:00", + "2026-02-06T10:00", + "2026-02-06T11:00", + "2026-02-06T12:00", + "2026-02-06T13:00", + "2026-02-06T14:00", + "2026-02-06T15:00", + "2026-02-06T16:00", + "2026-02-06T17:00", + "2026-02-06T18:00", + "2026-02-06T19:00", + "2026-02-06T20:00", + "2026-02-06T21:00", + "2026-02-06T22:00", + "2026-02-06T23:00", + "2026-02-07T00:00", + "2026-02-07T01:00", + "2026-02-07T02:00", + "2026-02-07T03:00", + "2026-02-07T04:00", + "2026-02-07T05:00", + "2026-02-07T06:00", + "2026-02-07T07:00", + "2026-02-07T08:00", + "2026-02-07T09:00", + "2026-02-07T10:00", + "2026-02-07T11:00", + "2026-02-07T12:00", + "2026-02-07T13:00", + "2026-02-07T14:00", + "2026-02-07T15:00", + "2026-02-07T16:00", + "2026-02-07T17:00", + "2026-02-07T18:00", + "2026-02-07T19:00", + "2026-02-07T20:00", + "2026-02-07T21:00", + "2026-02-07T22:00", + "2026-02-07T23:00", + "2026-02-08T00:00", + "2026-02-08T01:00", + "2026-02-08T02:00", + "2026-02-08T03:00", + "2026-02-08T04:00", + "2026-02-08T05:00", + "2026-02-08T06:00", + "2026-02-08T07:00", + "2026-02-08T08:00", + "2026-02-08T09:00", + "2026-02-08T10:00", + "2026-02-08T11:00", + "2026-02-08T12:00", + "2026-02-08T13:00", + "2026-02-08T14:00", + "2026-02-08T15:00", + "2026-02-08T16:00", + "2026-02-08T17:00", + "2026-02-08T18:00", + "2026-02-08T19:00", + "2026-02-08T20:00", + "2026-02-08T21:00", + "2026-02-08T22:00", + "2026-02-08T23:00", + "2026-02-09T00:00", + "2026-02-09T01:00", + "2026-02-09T02:00", + "2026-02-09T03:00", + "2026-02-09T04:00", + "2026-02-09T05:00", + "2026-02-09T06:00", + "2026-02-09T07:00", + "2026-02-09T08:00", + "2026-02-09T09:00", + "2026-02-09T10:00", + "2026-02-09T11:00", + "2026-02-09T12:00", + "2026-02-09T13:00", + "2026-02-09T14:00", + "2026-02-09T15:00", + "2026-02-09T16:00", + "2026-02-09T17:00", + "2026-02-09T18:00", + "2026-02-09T19:00", + "2026-02-09T20:00", + "2026-02-09T21:00", + "2026-02-09T22:00", + "2026-02-09T23:00", + "2026-02-10T00:00", + "2026-02-10T01:00", + "2026-02-10T02:00", + "2026-02-10T03:00", + "2026-02-10T04:00", + "2026-02-10T05:00", + "2026-02-10T06:00", + "2026-02-10T07:00", + "2026-02-10T08:00", + "2026-02-10T09:00", + "2026-02-10T10:00", + "2026-02-10T11:00", + "2026-02-10T12:00", + "2026-02-10T13:00", + "2026-02-10T14:00", + "2026-02-10T15:00", + "2026-02-10T16:00", + "2026-02-10T17:00", + "2026-02-10T18:00", + "2026-02-10T19:00", + "2026-02-10T20:00", + "2026-02-10T21:00", + "2026-02-10T22:00", + "2026-02-10T23:00", + "2026-02-11T00:00", + "2026-02-11T01:00", + "2026-02-11T02:00", + "2026-02-11T03:00", + "2026-02-11T04:00", + "2026-02-11T05:00", + "2026-02-11T06:00", + "2026-02-11T07:00", + "2026-02-11T08:00", + "2026-02-11T09:00", + "2026-02-11T10:00", + "2026-02-11T11:00", + "2026-02-11T12:00", + "2026-02-11T13:00", + "2026-02-11T14:00", + "2026-02-11T15:00", + "2026-02-11T16:00", + "2026-02-11T17:00", + "2026-02-11T18:00", + "2026-02-11T19:00", + "2026-02-11T20:00", + "2026-02-11T21:00", + "2026-02-11T22:00", + "2026-02-11T23:00", + "2026-02-12T00:00", + "2026-02-12T01:00", + "2026-02-12T02:00", + "2026-02-12T03:00", + "2026-02-12T04:00", + "2026-02-12T05:00", + "2026-02-12T06:00", + "2026-02-12T07:00", + "2026-02-12T08:00", + "2026-02-12T09:00", + "2026-02-12T10:00", + "2026-02-12T11:00", + "2026-02-12T12:00", + "2026-02-12T13:00", + "2026-02-12T14:00", + "2026-02-12T15:00", + "2026-02-12T16:00", + "2026-02-12T17:00", + "2026-02-12T18:00", + "2026-02-12T19:00", + "2026-02-12T20:00", + "2026-02-12T21:00", + "2026-02-12T22:00", + "2026-02-12T23:00" + ], + "temperature_2m": [ + -7.1, -7.1, -8.5, -8.8, -9.0, -7.7, -9.2, -8.8, -8.9, -5.9, -3.4, -2.4, -1.3, -0.8, -0.5, -0.2, -0.7, -2.1, -3.2, -3.7, -4.4, -5.3, -6.2, -6.8, -6.5, -6.3, -6.5, -6.3, -5.8, -5.3, -8.5, -11.2, -12.7, -13.6, -13.9, -13.8, -13.5, -13.2, + -12.9, -13.0, -13.2, -14.0, -15.2, -16.1, -16.9, -17.4, -17.5, -17.7, -18.1, -18.5, -18.9, -19.4, -20.0, -20.5, -21.0, -21.5, -20.2, -18.3, -16.4, -14.2, -12.5, -10.8, -9.3, -8.9, -10.0, -10.6, -11.2, -11.8, -12.5, -12.9, -13.4, -13.9, + -14.9, -15.7, -16.6, -17.0, -17.3, -17.5, -17.7, -18.1, -15.5, -12.6, -10.5, -8.6, -7.1, -5.8, -4.9, -4.4, -4.1, -4.9, -7.1, -9.1, -9.7, -6.9, -6.5, -6.4, -6.1, -7.2, -9.6, -10.1, -10.5, -10.8, -10.8, -11.0, -9.1, -6.7, -4.8, -3.1, -2.3, + -1.7, -1.2, -0.8, -0.7, -1.1, -1.8, -1.7, -1.7, -1.9, -4.7, -5.3, -5.3, -5.1, -5.1, -4.8, -5.0, -1.9, -1.2, -0.3, 0.4, 0.6, 0.8, 0.8, 0.6, 0.5, 0.5, 0.6, 0.8, 1.3, 1.9, 2.0, 1.3, 0.1, -0.9, -1.3, -1.6, -1.8, -2.0, -2.3, -2.6, -3.2, -3.8, + -3.9, -3.1, -1.8, -0.8, -0.3, -0.1, 0.0, 0.0, -0.1, -0.5, -1.3, -2.4, -3.3, -4.0, -4.5, -5.0, -5.3 + ], + "precipitation": [ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.4, 1.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.3, 0.3, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + ], + "weather_code": [ + 0, 0, 0, 0, 2, 0, 3, 3, 3, 0, 3, 3, 3, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 71, 71, 3, 3, 3, 3, 3, 51, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 56, 71, 3, 3, 45, 45, 45, 45, 51, 51, 51, 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2 + ], + "wind_speed_10m": [ + 4.3, 9.3, 8.1, 3.3, 11.3, 8.2, 8.8, 7.2, 3.6, 7.2, 5.4, 4.7, 5.0, 1.5, 1.1, 3.9, 4.9, 5.8, 6.5, 5.8, 7.1, 9.3, 8.5, 6.6, 6.6, 6.9, 6.9, 7.5, 8.9, 12.0, 25.8, 27.3, 27.3, 27.0, 28.5, 30.5, 30.8, 30.0, 29.3, 28.3, 27.8, 27.5, 26.3, 24.5, + 25.7, 22.9, 21.9, 19.4, 18.7, 18.4, 21.0, 19.0, 19.1, 18.5, 17.0, 13.8, 13.3, 18.1, 18.6, 19.7, 20.4, 20.5, 20.9, 21.7, 24.2, 22.2, 20.2, 18.8, 15.9, 13.8, 12.8, 11.2, 7.9, 5.9, 4.9, 4.6, 4.3, 3.2, 2.9, 3.0, 5.2, 6.9, 7.5, 6.6, 6.6, 5.2, + 4.1, 5.3, 2.2, 1.9, 2.6, 1.1, 2.2, 4.0, 3.9, 5.2, 4.0, 2.2, 5.0, 4.4, 4.5, 4.7, 4.2, 5.8, 5.8, 7.9, 6.8, 6.0, 5.4, 4.2, 3.4, 3.5, 1.1, 2.8, 5.3, 5.8, 6.1, 4.9, 4.8, 3.3, 3.7, 2.2, 1.0, 1.4, 4.0, 4.4, 3.7, 6.9, 7.6, 7.3, 6.6, 5.5, 4.1, + 3.9, 4.9, 6.0, 7.3, 9.7, 14.1, 17.1, 16.9, 15.1, 14.0, 14.7, 16.4, 17.4, 18.0, 18.1, 17.6, 15.5, 12.9, 11.9, 13.2, 15.8, 18.2, 19.0, 19.2, 19.2, 19.5, 19.7, 19.7, 19.0, 18.0, 17.4, 17.4, 17.6, 17.9, 18.1 + ] + }, + "daily_units": { "time": "iso8601", "weather_code": "wmo code", "temperature_2m_max": "°C", "temperature_2m_min": "°C", "sunrise": "iso8601", "sunset": "iso8601", "precipitation_sum": "mm" }, + "daily": { + "time": ["2026-02-06", "2026-02-07", "2026-02-08", "2026-02-09", "2026-02-10", "2026-02-11", "2026-02-12"], + "weather_code": [3, 71, 3, 3, 3, 71, 3], + "temperature_2m_max": [-0.2, -5.3, -8.9, -4.1, -0.7, 2.0, 0.0], + "temperature_2m_min": [-9.2, -17.7, -21.5, -18.1, -11.0, -5.3, -5.3], + "sunrise": ["2026-02-06T07:00", "2026-02-07T06:59", "2026-02-08T06:58", "2026-02-09T06:56", "2026-02-10T06:55", "2026-02-11T06:54", "2026-02-12T06:53"], + "sunset": ["2026-02-06T17:19", "2026-02-07T17:20", "2026-02-08T17:21", "2026-02-09T17:23", "2026-02-10T17:24", "2026-02-11T17:25", "2026-02-12T17:26"], + "precipitation_sum": [0.0, 0.4, 0.0, 0.0, 0.0, 2.6, 0.0] + } +} diff --git a/tests/mocks/weather_openmeteo_current_weather.json b/tests/mocks/weather_openmeteo_current_weather.json new file mode 100644 index 0000000000..ba5f183161 --- /dev/null +++ b/tests/mocks/weather_openmeteo_current_weather.json @@ -0,0 +1,84 @@ +{ + "latitude": 48.14, + "longitude": 11.58, + "generationtime_ms": 0.3949403762817383, + "utc_offset_seconds": 3600, + "timezone": "Europe/Berlin", + "timezone_abbreviation": "GMT+1", + "elevation": 524.0, + "current_weather_units": { + "time": "unixtime", + "interval": "seconds", + "temperature": "°C", + "windspeed": "km/h", + "winddirection": "°", + "is_day": "", + "weathercode": "wmo code" + }, + "current_weather": { + "time": 1770477300, + "interval": 900, + "temperature": 8.5, + "windspeed": 4.7, + "winddirection": 9, + "is_day": 1, + "weathercode": 2 + }, + "hourly_units": { + "time": "unixtime", + "temperature_2m": "°C", + "windspeed_10m": "km/h", + "winddirection_10m": "°", + "relativehumidity_2m": "%" + }, + "hourly": { + "time": [ + 1770418800, 1770422400, 1770426000, 1770429600, 1770433200, 1770436800, 1770440400, 1770444000, 1770447600, 1770451200, 1770454800, 1770458400, 1770462000, 1770465600, 1770469200, 1770472800, 1770476400, 1770480000, 1770483600, + 1770487200, 1770490800, 1770494400, 1770498000, 1770501600, 1770505200, 1770508800, 1770512400, 1770516000, 1770519600, 1770523200, 1770526800, 1770530400, 1770534000, 1770537600, 1770541200, 1770544800, 1770548400, 1770552000, + 1770555600, 1770559200, 1770562800, 1770566400, 1770570000, 1770573600, 1770577200, 1770580800, 1770584400, 1770588000, 1770591600, 1770595200, 1770598800, 1770602400, 1770606000, 1770609600, 1770613200, 1770616800, 1770620400, + 1770624000, 1770627600, 1770631200, 1770634800, 1770638400, 1770642000, 1770645600, 1770649200, 1770652800, 1770656400, 1770660000, 1770663600, 1770667200, 1770670800, 1770674400, 1770678000, 1770681600, 1770685200, 1770688800, + 1770692400, 1770696000, 1770699600, 1770703200, 1770706800, 1770710400, 1770714000, 1770717600, 1770721200, 1770724800, 1770728400, 1770732000, 1770735600, 1770739200, 1770742800, 1770746400, 1770750000, 1770753600, 1770757200, + 1770760800, 1770764400, 1770768000, 1770771600, 1770775200, 1770778800, 1770782400, 1770786000, 1770789600, 1770793200, 1770796800, 1770800400, 1770804000, 1770807600, 1770811200, 1770814800, 1770818400, 1770822000, 1770825600, + 1770829200, 1770832800, 1770836400, 1770840000, 1770843600, 1770847200, 1770850800, 1770854400, 1770858000, 1770861600, 1770865200, 1770868800, 1770872400, 1770876000, 1770879600, 1770883200, 1770886800, 1770890400, 1770894000, + 1770897600, 1770901200, 1770904800, 1770908400, 1770912000, 1770915600, 1770919200, 1770922800, 1770926400, 1770930000, 1770933600, 1770937200, 1770940800, 1770944400, 1770948000, 1770951600, 1770955200, 1770958800, 1770962400, + 1770966000, 1770969600, 1770973200, 1770976800, 1770980400, 1770984000, 1770987600, 1770991200, 1770994800, 1770998400, 1771002000, 1771005600, 1771009200, 1771012800, 1771016400, 1771020000 + ], + "temperature_2m": [ + 6.4, 6.6, 6.3, 5.8, 5.7, 5.1, 5.0, 5.5, 5.2, 5.3, 6.2, 7.0, 7.9, 9.1, 9.5, 9.0, 8.6, 8.2, 7.2, 6.4, 5.5, 5.1, 4.7, 4.9, 4.5, 4.5, 4.5, 4.7, 3.8, 3.1, 3.2, 3.0, 3.6, 3.8, 3.5, 4.3, 5.2, 6.2, 6.6, 6.8, 6.4, 5.5, 4.7, 4.7, 4.3, 4.2, 4.1, + 3.9, 3.6, 3.4, 3.2, 3.0, 2.9, 2.8, 2.7, 2.6, 2.5, 2.8, 3.1, 3.7, 4.3, 4.6, 4.7, 4.7, 4.4, 4.0, 3.5, 3.0, 2.5, 1.9, 1.2, 0.7, 0.3, 0.0, -0.1, -0.4, -0.8, -1.1, -1.3, -1.2, -1.2, -1.0, 0.2, 1.9, 3.3, 5.0, 6.1, 6.8, 7.0, 6.4, 5.2, 4.2, 3.6, + 3.1, 2.8, 2.5, 2.2, 2.2, 2.3, 2.6, 2.9, 3.0, 3.0, 3.4, 4.7, 6.3, 7.7, 8.5, 9.0, 9.3, 9.2, 8.9, 8.6, 8.3, 8.1, 7.9, 7.6, 7.4, 7.2, 7.1, 7.0, 6.9, 6.7, 6.4, 6.2, 5.6, 5.2, 4.9, 6.1, 6.4, 6.6, 6.9, 7.1, 7.2, 7.2, 7.0, 6.8, 6.4, 5.9, 5.5, + 5.4, 5.3, 5.2, 5.0, 4.8, 4.6, 4.5, 4.5, 4.6, 4.6, 4.6, 4.8, 5.2, 5.8, 6.4, 7.2, 8.1, 8.6, 8.3, 7.6, 7.0, 6.5, 6.2, 5.8, 5.5, 5.2, 5.0, 4.9 + ], + "windspeed_10m": [ + 9.4, 9.5, 9.2, 9.1, 7.9, 6.6, 6.8, 7.6, 6.7, 6.0, 5.9, 5.9, 6.6, 4.5, 7.9, 7.7, 5.4, 4.2, 3.3, 1.4, 2.6, 1.6, 2.2, 1.5, 0.8, 2.3, 2.3, 1.3, 2.5, 1.8, 1.6, 1.1, 1.8, 2.9, 5.6, 9.1, 9.0, 7.8, 9.0, 9.8, 9.7, 9.8, 10.4, 9.1, 7.9, 8.2, 7.6, + 6.0, 6.2, 5.3, 5.0, 5.5, 6.2, 5.9, 6.2, 6.5, 5.9, 5.4, 6.2, 5.9, 6.7, 6.5, 6.2, 6.2, 5.8, 5.5, 4.7, 4.2, 3.2, 3.4, 3.2, 2.7, 2.9, 3.7, 2.9, 3.4, 3.2, 3.6, 3.1, 3.6, 3.8, 4.6, 4.8, 4.3, 5.5, 5.3, 5.2, 4.9, 4.4, 3.2, 2.2, 2.0, 2.2, 3.0, + 3.4, 3.6, 4.0, 4.9, 5.2, 5.2, 5.2, 5.5, 5.8, 6.5, 9.0, 13.2, 16.9, 19.3, 20.8, 21.7, 22.3, 22.1, 22.0, 21.5, 21.2, 20.9, 20.2, 20.0, 19.3, 18.9, 18.2, 17.4, 16.4, 15.3, 14.2, 12.8, 11.7, 11.2, 21.7, 21.5, 21.5, 22.1, 23.0, 23.7, 23.8, + 23.6, 23.0, 22.0, 20.5, 19.5, 19.2, 19.3, 19.3, 19.5, 19.5, 20.0, 20.9, 21.9, 23.2, 24.7, 26.1, 26.9, 26.3, 25.4, 24.6, 25.0, 25.6, 26.1, 25.5, 24.4, 22.9, 20.5, 17.9, 15.9, 14.8, 14.3, 14.2, 14.8 + ], + "winddirection_10m": [ + 247, 241, 244, 252, 240, 229, 245, 251, 234, 245, 256, 256, 261, 284, 300, 332, 356, 59, 84, 90, 164, 207, 189, 284, 243, 198, 321, 304, 172, 180, 207, 180, 79, 30, 45, 72, 74, 68, 74, 73, 75, 54, 56, 56, 66, 67, 82, 57, 69, 62, 60, 58, + 69, 79, 83, 87, 101, 98, 97, 95, 88, 89, 97, 97, 97, 113, 122, 121, 117, 108, 117, 113, 120, 119, 120, 122, 117, 127, 135, 135, 131, 129, 117, 95, 79, 62, 56, 54, 55, 63, 90, 135, 171, 194, 198, 180, 153, 144, 146, 155, 164, 169, 173, + 186, 209, 225, 232, 237, 242, 246, 247, 248, 249, 249, 249, 249, 248, 247, 246, 246, 245, 246, 244, 240, 240, 240, 242, 245, 249, 249, 249, 251, 253, 253, 252, 251, 250, 249, 246, 245, 244, 243, 243, 242, 242, 242, 243, 245, 246, 247, + 247, 247, 247, 245, 245, 247, 250, 252, 254, 254, 254, 252, 248, 245, 244, 245, 246, 247 + ], + "relativehumidity_2m": [ + 83, 81, 81, 84, 83, 85, 86, 88, 89, 89, 85, 82, 77, 65, 62, 68, 71, 73, 81, 87, 91, 91, 93, 93, 94, 94, 94, 94, 99, 97, 94, 93, 94, 95, 96, 91, 86, 79, 77, 77, 76, 81, 85, 82, 89, 88, 87, 87, 89, 90, 90, 91, 92, 93, 94, 94, 95, 93, 89, + 83, 80, 75, 75, 75, 76, 79, 82, 83, 86, 90, 93, 93, 93, 95, 95, 95, 95, 97, 98, 99, 99, 98, 92, 84, 79, 73, 69, 67, 67, 69, 73, 77, 80, 83, 85, 87, 88, 87, 83, 76, 73, 76, 81, 85, 84, 82, 79, 76, 74, 72, 72, 72, 73, 73, 73, 74, 75, 77, + 78, 77, 75, 74, 73, 73, 74, 78, 84, 87, 81, 80, 78, 77, 77, 77, 77, 77, 78, 80, 82, 84, 85, 86, 86, 86, 87, 87, 87, 88, 88, 88, 88, 86, 82, 78, 73, 69, 65, 63, 64, 68, 72, 76, 81, 84, 85, 85, 85, 85 + ] + }, + "daily_units": { + "time": "unixtime", + "temperature_2m_max": "°C", + "temperature_2m_min": "°C", + "sunrise": "unixtime", + "sunset": "unixtime" + }, + "daily": { + "time": [1770418800, 1770505200, 1770591600, 1770678000, 1770764400, 1770850800, 1770937200], + "temperature_2m_max": [9.5, 6.8, 4.7, 7.0, 9.3, 7.2, 8.6], + "temperature_2m_min": [4.7, 3.0, 0.7, -1.3, 2.2, 4.9, 4.5], + "sunrise": [1770445978, 1770532288, 1770618596, 1770704904, 1770791211, 1770877515, 1770963818], + "sunset": [1770481348, 1770567844, 1770654340, 1770740836, 1770827331, 1770913826, 1771000321] + } +} diff --git a/tests/mocks/weather_owm_onecall.json b/tests/mocks/weather_owm_onecall.json new file mode 100644 index 0000000000..0696e347cb --- /dev/null +++ b/tests/mocks/weather_owm_onecall.json @@ -0,0 +1,970 @@ +{ + "lat": 40.7767, + "lon": -73.9713, + "timezone": "America/New_York", + "timezone_offset": -18000, + "current": { + "dt": 1770414297, + "sunrise": 1770379257, + "sunset": 1770416341, + "temp": -0.27, + "feels_like": -3.9, + "pressure": 1004, + "humidity": 54, + "dew_point": -7.54, + "uvi": 0, + "clouds": 75, + "visibility": 10000, + "wind_speed": 3.09, + "wind_deg": 220, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }] + }, + "hourly": [ + { + "dt": 1770411600, + "temp": -0.66, + "feels_like": -3.52, + "pressure": 1004, + "humidity": 61, + "dew_point": -6.5, + "uvi": 0.18, + "clouds": 80, + "visibility": 10000, + "wind_speed": 2.24, + "wind_deg": 187, + "wind_gust": 3.73, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770415200, + "temp": -0.27, + "feels_like": -2.6, + "pressure": 1004, + "humidity": 54, + "dew_point": -7.54, + "uvi": 0, + "clouds": 75, + "visibility": 10000, + "wind_speed": 1.87, + "wind_deg": 169, + "wind_gust": 3.26, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770418800, + "temp": -1.03, + "feels_like": -3.4, + "pressure": 1004, + "humidity": 62, + "dew_point": -6.67, + "uvi": 0, + "clouds": 80, + "visibility": 10000, + "wind_speed": 1.81, + "wind_deg": 190, + "wind_gust": 3.93, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770422400, + "temp": -1.54, + "feels_like": -5.39, + "pressure": 1004, + "humidity": 71, + "dew_point": -5.59, + "uvi": 0, + "clouds": 85, + "wind_speed": 3.04, + "wind_deg": 232, + "wind_gust": 6.25, + "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }], + "pop": 0.2, + "snow": { "1h": 0.13 } + }, + { + "dt": 1770426000, + "temp": -2.25, + "feels_like": -5.2, + "pressure": 1004, + "humidity": 80, + "dew_point": -4.89, + "uvi": 0, + "clouds": 90, + "visibility": 235, + "wind_speed": 2.09, + "wind_deg": 224, + "wind_gust": 6.04, + "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }], + "pop": 1, + "snow": { "1h": 0.18 } + }, + { + "dt": 1770429600, + "temp": -2.79, + "feels_like": -6.29, + "pressure": 1003, + "humidity": 89, + "dew_point": -4.17, + "uvi": 0, + "clouds": 95, + "visibility": 177, + "wind_speed": 2.47, + "wind_deg": 217, + "wind_gust": 6.99, + "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }], + "pop": 1, + "snow": { "1h": 0.19 } + }, + { + "dt": 1770433200, + "temp": -3.46, + "feels_like": -7.71, + "pressure": 1002, + "humidity": 96, + "dew_point": -4.21, + "uvi": 0, + "clouds": 100, + "visibility": 501, + "wind_speed": 3.05, + "wind_deg": 236, + "wind_gust": 7.82, + "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }], + "pop": 1, + "snow": { "1h": 0.19 } + }, + { + "dt": 1770436800, + "temp": -3.88, + "feels_like": -7.67, + "pressure": 1001, + "humidity": 97, + "dew_point": -4.47, + "uvi": 0, + "clouds": 100, + "visibility": 424, + "wind_speed": 2.54, + "wind_deg": 234, + "wind_gust": 7.49, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0.8 + }, + { + "dt": 1770440400, + "temp": -3.78, + "feels_like": -7.68, + "pressure": 1001, + "humidity": 96, + "dew_point": -4.57, + "uvi": 0, + "clouds": 100, + "visibility": 2576, + "wind_speed": 2.66, + "wind_deg": 231, + "wind_gust": 7.51, + "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }], + "pop": 1, + "snow": { "1h": 0.14 } + }, + { + "dt": 1770444000, + "temp": -4.1, + "feels_like": -8.05, + "pressure": 1000, + "humidity": 96, + "dew_point": -4.92, + "uvi": 0, + "clouds": 100, + "visibility": 305, + "wind_speed": 2.65, + "wind_deg": 237, + "wind_gust": 7.6, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0.8 + }, + { + "dt": 1770447600, + "temp": -4.12, + "feels_like": -8.44, + "pressure": 1000, + "humidity": 95, + "dew_point": -4.97, + "uvi": 0, + "clouds": 100, + "visibility": 10000, + "wind_speed": 2.99, + "wind_deg": 247, + "wind_gust": 7.23, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770451200, + "temp": -4.9, + "feels_like": -9.33, + "pressure": 999, + "humidity": 95, + "dew_point": -5.82, + "uvi": 0, + "clouds": 100, + "visibility": 10000, + "wind_speed": 2.95, + "wind_deg": 256, + "wind_gust": 7.85, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770454800, + "temp": -4.84, + "feels_like": -9.36, + "pressure": 999, + "humidity": 94, + "dew_point": -5.93, + "uvi": 0, + "clouds": 100, + "visibility": 4481, + "wind_speed": 3.04, + "wind_deg": 273, + "wind_gust": 10.32, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770458400, + "temp": -5.46, + "feels_like": -12.46, + "pressure": 1000, + "humidity": 85, + "dew_point": -7.96, + "uvi": 0, + "clouds": 100, + "visibility": 9905, + "wind_speed": 7.66, + "wind_deg": 316, + "wind_gust": 11.92, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770462000, + "temp": -9.55, + "feels_like": -16.55, + "pressure": 1001, + "humidity": 76, + "dew_point": -13.6, + "uvi": 0, + "clouds": 100, + "visibility": 10000, + "wind_speed": 8.25, + "wind_deg": 315, + "wind_gust": 15.03, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770465600, + "temp": -12.37, + "feels_like": -19.37, + "pressure": 1002, + "humidity": 76, + "dew_point": -16.71, + "uvi": 0, + "clouds": 100, + "visibility": 10000, + "wind_speed": 8.55, + "wind_deg": 309, + "wind_gust": 15.72, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770469200, + "temp": -14.13, + "feels_like": -21.13, + "pressure": 1003, + "humidity": 76, + "dew_point": -18.65, + "uvi": 0.27, + "clouds": 100, + "visibility": 10000, + "wind_speed": 8.44, + "wind_deg": 308, + "wind_gust": 16.05, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770472800, + "temp": -13.41, + "feels_like": -20.41, + "pressure": 1004, + "humidity": 76, + "dew_point": -17.82, + "uvi": 0.72, + "clouds": 56, + "visibility": 10000, + "wind_speed": 8.4, + "wind_deg": 311, + "wind_gust": 16, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770476400, + "temp": -12.76, + "feels_like": -19.76, + "pressure": 1004, + "humidity": 78, + "dew_point": -16.79, + "uvi": 1.2, + "clouds": 52, + "visibility": 10000, + "wind_speed": 8.67, + "wind_deg": 317, + "wind_gust": 15.12, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770480000, + "temp": -12.33, + "feels_like": -19.33, + "pressure": 1005, + "humidity": 83, + "dew_point": -15.61, + "uvi": 1.56, + "clouds": 64, + "visibility": 3083, + "wind_speed": 8.8, + "wind_deg": 321, + "wind_gust": 15.19, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770483600, + "temp": -11.87, + "feels_like": -18.87, + "pressure": 1004, + "humidity": 82, + "dew_point": -15.28, + "uvi": 1.56, + "clouds": 71, + "visibility": 8917, + "wind_speed": 8.88, + "wind_deg": 322, + "wind_gust": 15.55, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770487200, + "temp": -11.69, + "feels_like": -18.69, + "pressure": 1005, + "humidity": 79, + "dew_point": -15.5, + "uvi": 1.57, + "clouds": 76, + "visibility": 10000, + "wind_speed": 9.46, + "wind_deg": 324, + "wind_gust": 16.31, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770490800, + "temp": -11.62, + "feels_like": -18.62, + "pressure": 1005, + "humidity": 77, + "dew_point": -15.73, + "uvi": 1.11, + "clouds": 100, + "visibility": 10000, + "wind_speed": 9.8, + "wind_deg": 327, + "wind_gust": 16.18, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770494400, + "temp": -12, + "feels_like": -19, + "pressure": 1006, + "humidity": 75, + "dew_point": -16.48, + "uvi": 0.59, + "clouds": 100, + "visibility": 10000, + "wind_speed": 9.97, + "wind_deg": 328, + "wind_gust": 16.89, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770498000, + "temp": -12.71, + "feels_like": -19.71, + "pressure": 1007, + "humidity": 74, + "dew_point": -17.39, + "uvi": 0.19, + "clouds": 100, + "visibility": 10000, + "wind_speed": 10.12, + "wind_deg": 328, + "wind_gust": 17.9, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770501600, + "temp": -13.43, + "feels_like": -20.43, + "pressure": 1009, + "humidity": 72, + "dew_point": -18.44, + "uvi": 0, + "clouds": 100, + "visibility": 10000, + "wind_speed": 10.09, + "wind_deg": 329, + "wind_gust": 18.24, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770505200, + "temp": -14.05, + "feels_like": -21.05, + "pressure": 1011, + "humidity": 72, + "dew_point": -19.28, + "uvi": 0, + "clouds": 99, + "visibility": 10000, + "wind_speed": 10.11, + "wind_deg": 329, + "wind_gust": 18.4, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770508800, + "temp": -14.31, + "feels_like": -21.31, + "pressure": 1013, + "humidity": 72, + "dew_point": -19.61, + "uvi": 0, + "clouds": 97, + "visibility": 10000, + "wind_speed": 10.18, + "wind_deg": 328, + "wind_gust": 18.77, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770512400, + "temp": -14.29, + "feels_like": -21.29, + "pressure": 1014, + "humidity": 72, + "dew_point": -19.51, + "uvi": 0, + "clouds": 97, + "visibility": 10000, + "wind_speed": 9.7, + "wind_deg": 330, + "wind_gust": 18.29, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770516000, + "temp": -14.14, + "feels_like": -21.14, + "pressure": 1015, + "humidity": 72, + "dew_point": -19.28, + "uvi": 0, + "clouds": 98, + "visibility": 10000, + "wind_speed": 9.38, + "wind_deg": 330, + "wind_gust": 17.25, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770519600, + "temp": -14.08, + "feels_like": -21.08, + "pressure": 1016, + "humidity": 73, + "dew_point": -19.05, + "uvi": 0, + "clouds": 99, + "visibility": 10000, + "wind_speed": 8.71, + "wind_deg": 329, + "wind_gust": 16.58, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770523200, + "temp": -14.19, + "feels_like": -21.19, + "pressure": 1016, + "humidity": 74, + "dew_point": -19.05, + "uvi": 0, + "clouds": 99, + "visibility": 10000, + "wind_speed": 8.24, + "wind_deg": 328, + "wind_gust": 15.71, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770526800, + "temp": -14.38, + "feels_like": -21.38, + "pressure": 1017, + "humidity": 74, + "dew_point": -19.34, + "uvi": 0, + "clouds": 99, + "visibility": 10000, + "wind_speed": 8.08, + "wind_deg": 326, + "wind_gust": 15.77, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770530400, + "temp": -14.74, + "feels_like": -21.74, + "pressure": 1018, + "humidity": 74, + "dew_point": -19.74, + "uvi": 0, + "clouds": 99, + "visibility": 10000, + "wind_speed": 7.81, + "wind_deg": 324, + "wind_gust": 15.4, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770534000, + "temp": -15.13, + "feels_like": -22.13, + "pressure": 1019, + "humidity": 73, + "dew_point": -20.25, + "uvi": 0, + "clouds": 93, + "visibility": 10000, + "wind_speed": 7.57, + "wind_deg": 325, + "wind_gust": 15.39, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770537600, + "temp": -15.57, + "feels_like": -22.57, + "pressure": 1019, + "humidity": 73, + "dew_point": -20.69, + "uvi": 0, + "clouds": 94, + "visibility": 10000, + "wind_speed": 7.36, + "wind_deg": 323, + "wind_gust": 15.29, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770541200, + "temp": -15.98, + "feels_like": -22.98, + "pressure": 1019, + "humidity": 73, + "dew_point": -21.2, + "uvi": 0, + "clouds": 88, + "visibility": 10000, + "wind_speed": 7.37, + "wind_deg": 321, + "wind_gust": 15.7, + "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770544800, + "temp": -16.36, + "feels_like": -23.36, + "pressure": 1020, + "humidity": 73, + "dew_point": -21.64, + "uvi": 0, + "clouds": 69, + "visibility": 10000, + "wind_speed": 7.62, + "wind_deg": 322, + "wind_gust": 16.29, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770548400, + "temp": -16.63, + "feels_like": -23.63, + "pressure": 1021, + "humidity": 74, + "dew_point": -21.86, + "uvi": 0, + "clouds": 57, + "visibility": 10000, + "wind_speed": 7.52, + "wind_deg": 323, + "wind_gust": 16.46, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], + "pop": 0 + }, + { + "dt": 1770552000, + "temp": -16.84, + "feels_like": -23.84, + "pressure": 1022, + "humidity": 74, + "dew_point": -22.06, + "uvi": 0, + "clouds": 48, + "visibility": 10000, + "wind_speed": 7.59, + "wind_deg": 324, + "wind_gust": 16.2, + "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03d" }], + "pop": 0 + }, + { + "dt": 1770555600, + "temp": -16.57, + "feels_like": -23.57, + "pressure": 1023, + "humidity": 74, + "dew_point": -21.63, + "uvi": 0.3, + "clouds": 2, + "visibility": 10000, + "wind_speed": 7.27, + "wind_deg": 325, + "wind_gust": 14.68, + "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }], + "pop": 0 + }, + { + "dt": 1770559200, + "temp": -15.7, + "feels_like": -22.7, + "pressure": 1023, + "humidity": 76, + "dew_point": -20.43, + "uvi": 0.77, + "clouds": 4, + "visibility": 10000, + "wind_speed": 7.26, + "wind_deg": 324, + "wind_gust": 13.65, + "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }], + "pop": 0 + }, + { + "dt": 1770562800, + "temp": -14.48, + "feels_like": -21.48, + "pressure": 1023, + "humidity": 77, + "dew_point": -18.94, + "uvi": 1.42, + "clouds": 5, + "visibility": 10000, + "wind_speed": 6.7, + "wind_deg": 324, + "wind_gust": 12.19, + "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }], + "pop": 0 + }, + { + "dt": 1770566400, + "temp": -13.34, + "feels_like": -20.34, + "pressure": 1023, + "humidity": 73, + "dew_point": -18.23, + "uvi": 1.98, + "clouds": 5, + "visibility": 10000, + "wind_speed": 6.59, + "wind_deg": 327, + "wind_gust": 10.06, + "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }], + "pop": 0 + }, + { + "dt": 1770570000, + "temp": -11.94, + "feels_like": -18.94, + "pressure": 1022, + "humidity": 74, + "dew_point": -16.63, + "uvi": 2.19, + "clouds": 6, + "visibility": 10000, + "wind_speed": 6.3, + "wind_deg": 325, + "wind_gust": 9.29, + "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }], + "pop": 0 + }, + { + "dt": 1770573600, + "temp": -10.51, + "feels_like": -17.51, + "pressure": 1022, + "humidity": 75, + "dew_point": -14.88, + "uvi": 1.95, + "clouds": 7, + "visibility": 10000, + "wind_speed": 5.98, + "wind_deg": 321, + "wind_gust": 8.89, + "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }], + "pop": 0 + }, + { + "dt": 1770577200, + "temp": -9.42, + "feels_like": -16.42, + "pressure": 1022, + "humidity": 75, + "dew_point": -13.63, + "uvi": 1.39, + "clouds": 72, + "visibility": 10000, + "wind_speed": 5.92, + "wind_deg": 317, + "wind_gust": 8.77, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + }, + { + "dt": 1770580800, + "temp": -8.96, + "feels_like": -15.96, + "pressure": 1023, + "humidity": 79, + "dew_point": -12.4, + "uvi": 0.73, + "clouds": 80, + "visibility": 10000, + "wind_speed": 6.03, + "wind_deg": 312, + "wind_gust": 10.13, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "pop": 0 + } + ], + "daily": [ + { + "dt": 1770397200, + "sunrise": 1770379257, + "sunset": 1770416341, + "moonrise": 1770435960, + "moonset": 1770386880, + "moon_phase": 0.66, + "summary": "Expect a day of partly cloudy with snow", + "temp": { "day": -2.5, "min": -11.86, "max": -0.27, "night": -3.88, "eve": -1.03, "morn": -10.39 }, + "feels_like": { "day": -2.5, "night": -7.67, "eve": -3.4, "morn": -14.33 }, + "pressure": 1006, + "humidity": 88, + "dew_point": -4.3, + "wind_speed": 3.05, + "wind_deg": 236, + "wind_gust": 7.82, + "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13d" }], + "clouds": 95, + "pop": 1, + "snow": 0.69, + "uvi": 2.22 + }, + { + "dt": 1770483600, + "sunrise": 1770465590, + "sunset": 1770502816, + "moonrise": 1770526200, + "moonset": 1770474600, + "moon_phase": 0.69, + "summary": "There will be snow until morning, then partly cloudy", + "temp": { "day": -11.87, "min": -14.31, "max": -3.78, "night": -14.19, "eve": -14.05, "morn": -9.55 }, + "feels_like": { "day": -18.87, "night": -21.19, "eve": -21.05, "morn": -16.55 }, + "pressure": 1004, + "humidity": 82, + "dew_point": -15.28, + "wind_speed": 10.18, + "wind_deg": 328, + "wind_gust": 18.77, + "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13d" }], + "clouds": 71, + "pop": 1, + "snow": 0.14, + "uvi": 1.57 + }, + { + "dt": 1770570000, + "sunrise": 1770551923, + "sunset": 1770589291, + "moonrise": 0, + "moonset": 1770562440, + "moon_phase": 0.72, + "summary": "Expect a day of partly cloudy with clear spells", + "temp": { "day": -11.94, "min": -16.84, "max": -8.96, "night": -13.75, "eve": -11.11, "morn": -16.63 }, + "feels_like": { "day": -18.94, "night": -20.33, "eve": -18.11, "morn": -23.63 }, + "pressure": 1022, + "humidity": 74, + "dew_point": -16.63, + "wind_speed": 8.08, + "wind_deg": 326, + "wind_gust": 16.46, + "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }], + "clouds": 6, + "pop": 0, + "uvi": 2.19 + }, + { + "dt": 1770656400, + "sunrise": 1770638253, + "sunset": 1770675765, + "moonrise": 1770616380, + "moonset": 1770650520, + "moon_phase": 0.75, + "summary": "The day will start with clear sky through the late morning hours, transitioning to partly cloudy", + "temp": { "day": -6.9, "min": -17.11, "max": -3.39, "night": -5.77, "eve": -7.87, "morn": -16.94 }, + "feels_like": { "day": -10.1, "night": -5.77, "eve": -7.87, "morn": -16.94 }, + "pressure": 1024, + "humidity": 78, + "dew_point": -10.38, + "wind_speed": 2.5, + "wind_deg": 319, + "wind_gust": 7.03, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "clouds": 83, + "pop": 0, + "uvi": 2.7 + }, + { + "dt": 1770742800, + "sunrise": 1770724583, + "sunset": 1770762240, + "moonrise": 1770706560, + "moonset": 1770739020, + "moon_phase": 0.79, + "summary": "There will be partly cloudy today", + "temp": { "day": -1.46, "min": -10, "max": -0.51, "night": -3.8, "eve": -1.57, "morn": -10 }, + "feels_like": { "day": -1.46, "night": -6.36, "eve": -3.98, "morn": -13.81 }, + "pressure": 1020, + "humidity": 94, + "dew_point": -2.47, + "wind_speed": 1.83, + "wind_deg": 2, + "wind_gust": 2.92, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "clouds": 56, + "pop": 0, + "uvi": 3.1 + }, + { + "dt": 1770829200, + "sunrise": 1770810911, + "sunset": 1770848714, + "moonrise": 1770796620, + "moonset": 1770827880, + "moon_phase": 0.82, + "summary": "The day will start with partly cloudy with snow through the late morning hours, transitioning to partly cloudy with rain", + "temp": { "day": 0.7, "min": -4.02, "max": 2.06, "night": -0.6, "eve": 2.06, "morn": -0.03 }, + "feels_like": { "day": 0.7, "night": -5, "eve": -2, "morn": -3.1 }, + "pressure": 1009, + "humidity": 100, + "dew_point": 0.64, + "wind_speed": 4.4, + "wind_deg": 311, + "wind_gust": 11.56, + "weather": [{ "id": 616, "main": "Snow", "description": "rain and snow", "icon": "13d" }], + "clouds": 100, + "pop": 1, + "rain": 4.38, + "snow": 2.17, + "uvi": 4 + }, + { + "dt": 1770915600, + "sunrise": 1770897237, + "sunset": 1770935188, + "moonrise": 1770886440, + "moonset": 1770917220, + "moon_phase": 0.85, + "summary": "There will be partly cloudy today", + "temp": { "day": 0.2, "min": -4.63, "max": 0.2, "night": -4.63, "eve": -2.9, "morn": -3.67 }, + "feels_like": { "day": -4.8, "night": -10.67, "eve": -8.49, "morn": -8.22 }, + "pressure": 1012, + "humidity": 81, + "dew_point": -2.81, + "wind_speed": 5.52, + "wind_deg": 301, + "wind_gust": 12.97, + "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03d" }], + "clouds": 50, + "pop": 0, + "uvi": 4 + }, + { + "dt": 1771002000, + "sunrise": 1770983562, + "sunset": 1771021662, + "moonrise": 1770975780, + "moonset": 1771007160, + "moon_phase": 0.88, + "summary": "Expect a day of partly cloudy with clear spells", + "temp": { "day": 0.38, "min": -6.39, "max": 0.95, "night": -1.17, "eve": -0.91, "morn": -6.39 }, + "feels_like": { "day": -3.92, "night": -6.3, "eve": -5.42, "morn": -12.89 }, + "pressure": 1017, + "humidity": 80, + "dew_point": -2.71, + "wind_speed": 5.27, + "wind_deg": 298, + "wind_gust": 14.69, + "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], + "clouds": 74, + "pop": 0, + "uvi": 4 + } + ] +} diff --git a/tests/mocks/weather_pirateweather.json b/tests/mocks/weather_pirateweather.json new file mode 100644 index 0000000000..75a13969b5 --- /dev/null +++ b/tests/mocks/weather_pirateweather.json @@ -0,0 +1,1665 @@ +{ + "latitude": 40.7128, + "longitude": -74.006, + "timezone": "America/New_York", + "offset": -5.0, + "elevation": 19, + "currently": { + "time": 1770414300, + "summary": "Overcast", + "icon": "cloudy", + "nearestStormDistance": 115.95, + "nearestStormBearing": 233, + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipType": "none", + "temperature": -0.26, + "apparentTemperature": -4.77, + "dewPoint": -7.89, + "humidity": 0.56, + "pressure": 1004.92, + "windSpeed": 2.32, + "windGust": 3.2, + "windBearing": 166, + "cloudCover": 0.97, + "uvIndex": 0.54, + "visibility": 16.09, + "ozone": 401.41 + }, + "minutely": { + "summary": "Overcast for the hour.", + "icon": "cloudy", + "data": [ + { "time": 1770414300, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414360, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414420, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414480, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414540, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414600, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414660, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414720, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414780, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414840, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414900, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770414960, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415020, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415080, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415140, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415200, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415260, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415320, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415380, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415440, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415500, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415560, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415620, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415680, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415740, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415800, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415860, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415920, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770415980, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416040, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416100, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416160, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416220, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416280, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416340, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416400, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416460, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416520, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416580, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416640, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416700, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416760, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416820, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416880, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770416940, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417000, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417060, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417120, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417180, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417240, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417300, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417360, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417420, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417480, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417540, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417600, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417660, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417720, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417780, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417840, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }, + { "time": 1770417900, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" } + ] + }, + "hourly": { + "summary": "Hazy tonight and windy starting tomorrow morning.", + "icon": "fog", + "data": [ + { + "time": 1770411600, + "summary": "Mostly Cloudy", + "icon": "partly-cloudy-day", + "precipIntensity": 0.0, + "precipProbability": 0.16, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -2.19, + "apparentTemperature": -6.47, + "dewPoint": -6.77, + "humidity": 0.7, + "pressure": 1005.22, + "windSpeed": 3.6, + "windGust": 4.7, + "windBearing": 200, + "cloudCover": 0.77, + "uvIndex": 1.12, + "visibility": 16.09, + "ozone": 402.15, + "nearestStormDistance": 108.83, + "nearestStormBearing": 258 + }, + { + "time": 1770415200, + "summary": "Mostly Cloudy", + "icon": "partly-cloudy-day", + "precipIntensity": 0.0, + "precipProbability": 0.16, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -2.11, + "apparentTemperature": -6.3, + "dewPoint": -6.64, + "humidity": 0.71, + "pressure": 1004.82, + "windSpeed": 3.6, + "windGust": 4.77, + "windBearing": 207, + "cloudCover": 0.8, + "uvIndex": 0.35, + "visibility": 14.72, + "ozone": 401.17, + "nearestStormDistance": 118.33, + "nearestStormBearing": 233 + }, + { + "time": 1770418800, + "summary": "Mostly Cloudy", + "icon": "partly-cloudy-night", + "precipIntensity": 0.0, + "precipProbability": 0.16, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -2.02, + "apparentTemperature": -6.13, + "dewPoint": -6.5, + "humidity": 0.71, + "pressure": 1004.19, + "windSpeed": 3.6, + "windGust": 4.83, + "windBearing": 213, + "cloudCover": 0.83, + "uvIndex": 0.01, + "visibility": 13.18, + "ozone": 403.38, + "nearestStormDistance": 63.25, + "nearestStormBearing": 270 + }, + { + "time": 1770422400, + "summary": "Mostly Cloudy", + "icon": "partly-cloudy-night", + "precipIntensity": 0.0, + "precipProbability": 0.16, + "precipIntensityError": 0.02, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -1.94, + "apparentTemperature": -5.96, + "dewPoint": -6.37, + "humidity": 0.72, + "pressure": 1004.33, + "windSpeed": 3.6, + "windGust": 4.9, + "windBearing": 220, + "cloudCover": 0.86, + "uvIndex": 0.0, + "visibility": 11.65, + "ozone": 406.37, + "nearestStormDistance": 34.89, + "nearestStormBearing": 225 + }, + { + "time": 1770426000, + "summary": "Mostly Cloudy", + "icon": "partly-cloudy-night", + "precipIntensity": 0.0, + "precipProbability": 0.22, + "precipIntensityError": 0.02, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -1.87, + "apparentTemperature": -6.11, + "dewPoint": -6.26, + "humidity": 0.73, + "pressure": 1003.94, + "windSpeed": 3.6, + "windGust": 4.93, + "windBearing": 223, + "cloudCover": 0.87, + "uvIndex": 0.0, + "visibility": 8.58, + "ozone": 408.33, + "nearestStormDistance": 21.08, + "nearestStormBearing": 270 + }, + { + "time": 1770429600, + "summary": "Overcast", + "icon": "cloudy", + "precipIntensity": 0.0, + "precipProbability": 0.27, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -1.79, + "apparentTemperature": -6.25, + "dewPoint": -6.15, + "humidity": 0.73, + "pressure": 1003.89, + "windSpeed": 3.6, + "windGust": 4.97, + "windBearing": 227, + "cloudCover": 0.88, + "uvIndex": 0.0, + "visibility": 5.5, + "ozone": 405.87, + "nearestStormDistance": 34.89, + "nearestStormBearing": 135 + }, + { + "time": 1770433200, + "summary": "Hazy", + "icon": "fog", + "precipIntensity": 0.0, + "precipProbability": 0.33, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -1.72, + "apparentTemperature": -6.4, + "dewPoint": -6.04, + "humidity": 0.74, + "pressure": 1003.77, + "windSpeed": 3.6, + "windGust": 5.0, + "windBearing": 230, + "cloudCover": 0.89, + "uvIndex": 0.0, + "visibility": 2.43, + "ozone": 406.71, + "nearestStormDistance": 21.08, + "nearestStormBearing": 90 + }, + { + "time": 1770436800, + "summary": "Hazy", + "icon": "fog", + "precipIntensity": 0.0, + "precipProbability": 0.33, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -1.89, + "apparentTemperature": -6.74, + "dewPoint": -6.17, + "humidity": 0.74, + "pressure": 1003.03, + "windSpeed": 3.87, + "windGust": 5.4, + "windBearing": 237, + "cloudCover": 0.86, + "uvIndex": 0.0, + "visibility": 2.73, + "ozone": 403.27, + "nearestStormDistance": 84.33, + "nearestStormBearing": 90 + }, + { + "time": 1770440400, + "summary": "Hazy", + "icon": "fog", + "precipIntensity": 0.0, + "precipProbability": 0.33, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -2.05, + "apparentTemperature": -7.07, + "dewPoint": -6.3, + "humidity": 0.73, + "pressure": 1002.42, + "windSpeed": 4.13, + "windGust": 5.8, + "windBearing": 243, + "cloudCover": 0.84, + "uvIndex": 0.0, + "visibility": 3.03, + "ozone": 408.05, + "nearestStormDistance": 105.41, + "nearestStormBearing": 90 + }, + { + "time": 1770444000, + "summary": "Hazy", + "icon": "fog", + "precipIntensity": 0.0, + "precipProbability": 0.33, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -2.22, + "apparentTemperature": -7.41, + "dewPoint": -6.43, + "humidity": 0.73, + "pressure": 1001.45, + "windSpeed": 4.4, + "windGust": 6.2, + "windBearing": 250, + "cloudCover": 0.81, + "uvIndex": 0.0, + "visibility": 3.33, + "ozone": 412.89, + "nearestStormDistance": 118.85, + "nearestStormBearing": 111 + }, + { + "time": 1770447600, + "summary": "Mostly Cloudy", + "icon": "partly-cloudy-night", + "precipIntensity": 0.0, + "precipProbability": 0.29, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -2.58, + "apparentTemperature": -8.29, + "dewPoint": -6.62, + "humidity": 0.74, + "pressure": 1000.84, + "windSpeed": 5.33, + "windGust": 7.5, + "windBearing": 260, + "cloudCover": 0.8, + "uvIndex": 0.0, + "visibility": 5.6, + "ozone": 417.97, + "nearestStormDistance": 118.85, + "nearestStormBearing": 111 + }, + { + "time": 1770451200, + "summary": "Mostly Cloudy", + "icon": "partly-cloudy-night", + "precipIntensity": 0.0, + "precipProbability": 0.24, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -2.95, + "apparentTemperature": -9.17, + "dewPoint": -6.82, + "humidity": 0.75, + "pressure": 1000.63, + "windSpeed": 6.27, + "windGust": 8.8, + "windBearing": 270, + "cloudCover": 0.78, + "uvIndex": 0.0, + "visibility": 8.4, + "ozone": 417.69, + "nearestStormDistance": 118.85, + "nearestStormBearing": 111 + }, + { + "time": 1770454800, + "summary": "Breezy and Mostly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.2, + "precipIntensityError": 0.04, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -3.31, + "apparentTemperature": -10.05, + "dewPoint": -7.01, + "humidity": 0.76, + "pressure": 1000.26, + "windSpeed": 7.2, + "windGust": 10.1, + "windBearing": 280, + "cloudCover": 0.77, + "uvIndex": 0.0, + "visibility": 2.3, + "ozone": 416.64, + "nearestStormDistance": 55.66, + "nearestStormBearing": 180 + }, + { + "time": 1770458400, + "summary": "Breezy and Mostly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.2, + "precipIntensityError": 0.04, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -4.07, + "apparentTemperature": -11.46, + "dewPoint": -8.19, + "humidity": 0.73, + "pressure": 1000.86, + "windSpeed": 8.13, + "windGust": 11.13, + "windBearing": 287, + "cloudCover": 0.73, + "uvIndex": 0.0, + "visibility": 2.5, + "ozone": 430.55, + "nearestStormDistance": 59.55, + "nearestStormBearing": 333 + }, + { + "time": 1770462000, + "summary": "Breezy and Mostly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.2, + "precipIntensityError": 0.04, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -4.82, + "apparentTemperature": -12.87, + "dewPoint": -9.36, + "humidity": 0.71, + "pressure": 1001.53, + "windSpeed": 9.07, + "windGust": 12.17, + "windBearing": 293, + "cloudCover": 0.69, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 444.39, + "nearestStormDistance": 63.25, + "nearestStormBearing": 90 + }, + { + "time": 1770465600, + "summary": "Windy and Mostly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.2, + "precipIntensityError": 0.04, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -5.58, + "apparentTemperature": -14.28, + "dewPoint": -10.54, + "humidity": 0.68, + "pressure": 1002.21, + "windSpeed": 10.0, + "windGust": 13.2, + "windBearing": 300, + "cloudCover": 0.65, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 445.07, + "nearestStormDistance": 101.31, + "nearestStormBearing": 63 + }, + { + "time": 1770469200, + "summary": "Windy and Partly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.16, + "precipIntensityError": 0.04, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -6.72, + "apparentTemperature": -15.95, + "dewPoint": -11.67, + "humidity": 0.68, + "pressure": 1003.26, + "windSpeed": 10.4, + "windGust": 14.17, + "windBearing": 303, + "cloudCover": 0.57, + "uvIndex": 0.21, + "visibility": 16.09, + "ozone": 446.52, + "nearestStormDistance": 118.85, + "nearestStormBearing": 111 + }, + { + "time": 1770472800, + "summary": "Windy and Partly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.11, + "precipIntensityError": 0.04, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -7.85, + "apparentTemperature": -17.63, + "dewPoint": -12.79, + "humidity": 0.68, + "pressure": 1003.8, + "windSpeed": 10.8, + "windGust": 15.13, + "windBearing": 307, + "cloudCover": 0.49, + "uvIndex": 1.08, + "visibility": 16.09, + "ozone": 451.89, + "nearestStormDistance": 68.99, + "nearestStormBearing": 108 + }, + { + "time": 1770476400, + "summary": "Windy and Partly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.07, + "precipIntensityError": 0.04, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -8.99, + "apparentTemperature": -19.3, + "dewPoint": -13.92, + "humidity": 0.68, + "pressure": 1004.89, + "windSpeed": 11.2, + "windGust": 16.1, + "windBearing": 310, + "cloudCover": 0.41, + "uvIndex": 2.15, + "visibility": 6.5, + "ozone": 449.97, + "nearestStormDistance": 63.25, + "nearestStormBearing": 90 + }, + { + "time": 1770480000, + "summary": "Windy and Partly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.07, + "precipIntensityError": 0.04, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.07, + "apparentTemperature": -19.26, + "dewPoint": -14.3, + "humidity": 0.66, + "pressure": 1005.63, + "windSpeed": 11.07, + "windGust": 16.07, + "windBearing": 313, + "cloudCover": 0.39, + "uvIndex": 2.87, + "visibility": 4.3, + "ozone": 447.68, + "nearestStormDistance": 129.75, + "nearestStormBearing": 80 + }, + { + "time": 1770483600, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.07, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.14, + "apparentTemperature": -19.23, + "dewPoint": -14.68, + "humidity": 0.64, + "pressure": 1006.14, + "windSpeed": 10.93, + "windGust": 16.03, + "windBearing": 317, + "cloudCover": 0.36, + "uvIndex": 3.23, + "visibility": 9.5, + "ozone": 460.33, + "nearestStormDistance": 63.25, + "nearestStormBearing": 90 + }, + { + "time": 1770487200, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.07, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.22, + "apparentTemperature": -19.19, + "dewPoint": -15.06, + "humidity": 0.62, + "pressure": 1006.64, + "windSpeed": 10.8, + "windGust": 16.0, + "windBearing": 320, + "cloudCover": 0.34, + "uvIndex": 3.23, + "visibility": 16.09, + "ozone": 466.32, + "nearestStormDistance": 84.43, + "nearestStormBearing": 56 + }, + { + "time": 1770490800, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.06, + "precipIntensityError": 0.03, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.12, + "apparentTemperature": -19.17, + "dewPoint": -15.37, + "humidity": 0.6, + "pressure": 1007.56, + "windSpeed": 10.93, + "windGust": 16.2, + "windBearing": 320, + "cloudCover": 0.31, + "uvIndex": 2.88, + "visibility": 16.09, + "ozone": 461.77, + "nearestStormDistance": 63.25, + "nearestStormBearing": 90 + }, + { + "time": 1770494400, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.05, + "precipIntensityError": 0.02, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.02, + "apparentTemperature": -19.16, + "dewPoint": -15.67, + "humidity": 0.57, + "pressure": 1008.89, + "windSpeed": 11.07, + "windGust": 16.4, + "windBearing": 320, + "cloudCover": 0.28, + "uvIndex": 2.08, + "visibility": 16.09, + "ozone": 460.11, + "nearestStormDistance": 63.25, + "nearestStormBearing": 90 + }, + { + "time": 1770498000, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.02, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -8.92, + "apparentTemperature": -19.14, + "dewPoint": -15.98, + "humidity": 0.55, + "pressure": 1009.92, + "windSpeed": 11.2, + "windGust": 16.6, + "windBearing": 320, + "cloudCover": 0.25, + "uvIndex": 1.23, + "visibility": 16.09, + "ozone": 464.16, + "nearestStormDistance": 163.12, + "nearestStormBearing": 38 + }, + { + "time": 1770501600, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.09, + "apparentTemperature": -19.43, + "dewPoint": -16.42, + "humidity": 0.54, + "pressure": 1011.26, + "windSpeed": 11.33, + "windGust": 16.13, + "windBearing": 320, + "cloudCover": 0.23, + "uvIndex": 0.43, + "visibility": 16.09, + "ozone": 482.48, + "nearestStormDistance": 129.29, + "nearestStormBearing": 99 + }, + { + "time": 1770505200, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.25, + "apparentTemperature": -19.71, + "dewPoint": -16.86, + "humidity": 0.53, + "pressure": 1013.04, + "windSpeed": 11.47, + "windGust": 15.67, + "windBearing": 320, + "cloudCover": 0.22, + "uvIndex": 0.01, + "visibility": 16.09, + "ozone": 484.32, + "nearestStormDistance": 105.41, + "nearestStormBearing": 90 + }, + { + "time": 1770508800, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.42, + "apparentTemperature": -20.0, + "dewPoint": -17.3, + "humidity": 0.52, + "pressure": 1014.7, + "windSpeed": 11.6, + "windGust": 15.2, + "windBearing": 320, + "cloudCover": 0.2, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 476.4, + "nearestStormDistance": 63.25, + "nearestStormBearing": 90 + }, + { + "time": 1770512400, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.84, + "apparentTemperature": -20.51, + "dewPoint": -17.58, + "humidity": 0.53, + "pressure": 1015.83, + "windSpeed": 11.2, + "windGust": 14.73, + "windBearing": 320, + "cloudCover": 0.2, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 488.47, + "nearestStormDistance": 63.25, + "nearestStormBearing": 90 + }, + { + "time": 1770516000, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -10.26, + "apparentTemperature": -21.02, + "dewPoint": -17.87, + "humidity": 0.53, + "pressure": 1016.42, + "windSpeed": 10.8, + "windGust": 14.27, + "windBearing": 320, + "cloudCover": 0.19, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 488.94, + "nearestStormDistance": 42.17, + "nearestStormBearing": 90 + }, + { + "time": 1770519600, + "summary": "Windy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.02, + "precipAccumulation": 0.0, + "precipType": "none", + "temperature": -10.68, + "apparentTemperature": -21.53, + "dewPoint": -18.15, + "humidity": 0.54, + "pressure": 1017.26, + "windSpeed": 10.4, + "windGust": 13.8, + "windBearing": 320, + "cloudCover": 0.19, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 476.31, + "nearestStormDistance": 63.25, + "nearestStormBearing": 90 + }, + { + "time": 1770523200, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "none", + "temperature": -11.0, + "apparentTemperature": -21.6, + "dewPoint": -18.21, + "humidity": 0.55, + "pressure": 1017.96, + "windSpeed": 9.87, + "windGust": 13.07, + "windBearing": 320, + "cloudCover": 0.19, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 472.62, + "nearestStormDistance": 84.43, + "nearestStormBearing": 56 + }, + { + "time": 1770526800, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "none", + "temperature": -11.31, + "apparentTemperature": -21.67, + "dewPoint": -18.28, + "humidity": 0.55, + "pressure": 1018.54, + "windSpeed": 9.33, + "windGust": 12.33, + "windBearing": 320, + "cloudCover": 0.18, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 473.0, + "nearestStormDistance": 104.96, + "nearestStormBearing": 45 + }, + { + "time": 1770530400, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "none", + "temperature": -11.63, + "apparentTemperature": -21.74, + "dewPoint": -18.34, + "humidity": 0.56, + "pressure": 1018.94, + "windSpeed": 8.8, + "windGust": 11.6, + "windBearing": 320, + "cloudCover": 0.18, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 471.38, + "nearestStormDistance": 128.27, + "nearestStormBearing": 36 + }, + { + "time": 1770534000, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -11.85, + "apparentTemperature": -21.99, + "dewPoint": -18.42, + "humidity": 0.57, + "pressure": 1019.57, + "windSpeed": 8.53, + "windGust": 11.43, + "windBearing": 320, + "cloudCover": 0.2, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 469.74, + "nearestStormDistance": 163.12, + "nearestStormBearing": 38 + }, + { + "time": 1770537600, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -12.08, + "apparentTemperature": -22.23, + "dewPoint": -18.51, + "humidity": 0.58, + "pressure": 1020.57, + "windSpeed": 8.27, + "windGust": 11.27, + "windBearing": 320, + "cloudCover": 0.22, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 469.32, + "nearestStormDistance": 198.1, + "nearestStormBearing": 39 + }, + { + "time": 1770541200, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -12.3, + "apparentTemperature": -22.48, + "dewPoint": -18.59, + "humidity": 0.59, + "pressure": 1020.96, + "windSpeed": 8.0, + "windGust": 11.1, + "windBearing": 320, + "cloudCover": 0.24, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 470.4, + "nearestStormDistance": 210.33, + "nearestStormBearing": 45 + }, + { + "time": 1770544800, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -12.29, + "apparentTemperature": -22.26, + "dewPoint": -18.48, + "humidity": 0.6, + "pressure": 1021.44, + "windSpeed": 7.73, + "windGust": 10.67, + "windBearing": 317, + "cloudCover": 0.26, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 467.82, + "nearestStormDistance": 223.94, + "nearestStormBearing": 49 + }, + { + "time": 1770548400, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -12.29, + "apparentTemperature": -22.05, + "dewPoint": -18.38, + "humidity": 0.61, + "pressure": 1021.88, + "windSpeed": 7.47, + "windGust": 10.23, + "windBearing": 313, + "cloudCover": 0.27, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 467.33, + "nearestStormDistance": 222.15, + "nearestStormBearing": 35 + }, + { + "time": 1770552000, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -12.28, + "apparentTemperature": -21.83, + "dewPoint": -18.27, + "humidity": 0.62, + "pressure": 1022.51, + "windSpeed": 7.2, + "windGust": 9.8, + "windBearing": 310, + "cloudCover": 0.29, + "uvIndex": 0.0, + "visibility": 16.09, + "ozone": 470.61, + "nearestStormDistance": 222.15, + "nearestStormBearing": 35 + }, + { + "time": 1770555600, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -12.06, + "apparentTemperature": -21.37, + "dewPoint": -17.87, + "humidity": 0.63, + "pressure": 1023.17, + "windSpeed": 7.07, + "windGust": 9.83, + "windBearing": 313, + "cloudCover": 0.32, + "uvIndex": 0.23, + "visibility": 16.09, + "ozone": 475.74, + "nearestStormDistance": 198.1, + "nearestStormBearing": 39 + }, + { + "time": 1770559200, + "summary": "Breezy and Mostly Clear", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.0, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -11.85, + "apparentTemperature": -20.92, + "dewPoint": -17.48, + "humidity": 0.63, + "pressure": 1023.18, + "windSpeed": 6.93, + "windGust": 9.87, + "windBearing": 317, + "cloudCover": 0.35, + "uvIndex": 1.09, + "visibility": 16.09, + "ozone": 473.89, + "nearestStormDistance": 210.33, + "nearestStormBearing": 45 + }, + { + "time": 1770562800, + "summary": "Breezy and Partly Cloudy", + "icon": "wind", + "precipIntensity": 0.0, + "precipProbability": 0.05, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -11.63, + "apparentTemperature": -20.46, + "dewPoint": -17.08, + "humidity": 0.64, + "pressure": 1023.83, + "windSpeed": 6.8, + "windGust": 9.9, + "windBearing": 320, + "cloudCover": 0.38, + "uvIndex": 2.2, + "visibility": 16.09, + "ozone": 467.51, + "nearestStormDistance": 233.17, + "nearestStormBearing": 40 + }, + { + "time": 1770566400, + "summary": "Partly Cloudy", + "icon": "partly-cloudy-day", + "precipIntensity": 0.0, + "precipProbability": 0.05, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -10.88, + "apparentTemperature": -19.39, + "dewPoint": -16.45, + "humidity": 0.64, + "pressure": 1024.02, + "windSpeed": 6.53, + "windGust": 9.77, + "windBearing": 317, + "cloudCover": 0.41, + "uvIndex": 3.21, + "visibility": 16.09, + "ozone": 453.24, + "nearestStormDistance": 233.17, + "nearestStormBearing": 40 + }, + { + "time": 1770570000, + "summary": "Partly Cloudy", + "icon": "partly-cloudy-day", + "precipIntensity": 0.0, + "precipProbability": 0.05, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -10.12, + "apparentTemperature": -18.31, + "dewPoint": -15.82, + "humidity": 0.63, + "pressure": 1023.84, + "windSpeed": 6.27, + "windGust": 9.63, + "windBearing": 313, + "cloudCover": 0.45, + "uvIndex": 3.87, + "visibility": 16.09, + "ozone": 444.43, + "nearestStormDistance": 247.0, + "nearestStormBearing": 32 + }, + { + "time": 1770573600, + "summary": "Partly Cloudy", + "icon": "partly-cloudy-day", + "precipIntensity": 0.0, + "precipProbability": 0.05, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -9.37, + "apparentTemperature": -17.24, + "dewPoint": -15.19, + "humidity": 0.63, + "pressure": 1023.45, + "windSpeed": 6.0, + "windGust": 9.5, + "windBearing": 310, + "cloudCover": 0.48, + "uvIndex": 3.98, + "visibility": 16.09, + "ozone": 441.37, + "nearestStormDistance": 280.82, + "nearestStormBearing": 45 + }, + { + "time": 1770577200, + "summary": "Partly Cloudy", + "icon": "partly-cloudy-day", + "precipIntensity": 0.0, + "precipProbability": 0.06, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -8.97, + "apparentTemperature": -16.72, + "dewPoint": -14.92, + "humidity": 0.62, + "pressure": 1021.09, + "windSpeed": 6.07, + "windGust": 9.37, + "windBearing": 310, + "cloudCover": 0.49, + "uvIndex": 3.5, + "visibility": 16.09, + "ozone": 440.69, + "nearestStormDistance": 291.96, + "nearestStormBearing": 37 + }, + { + "time": 1770580800, + "summary": "Partly Cloudy", + "icon": "partly-cloudy-day", + "precipIntensity": 0.0, + "precipProbability": 0.06, + "precipIntensityError": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperature": -8.58, + "apparentTemperature": -16.2, + "dewPoint": -14.64, + "humidity": 0.62, + "pressure": 1021.18, + "windSpeed": 6.13, + "windGust": 9.23, + "windBearing": 310, + "cloudCover": 0.51, + "uvIndex": 2.58, + "visibility": 16.09, + "ozone": 433.53, + "nearestStormDistance": 303.53, + "nearestStormBearing": 41 + } + ] + }, + "daily": { + "summary": "Snow next Friday, with high temperatures peaking at 2°C on Wednesday.", + "icon": "snow", + "data": [ + { + "time": 1770354000, + "summary": "Hazy overnight.", + "icon": "fog", + "sunriseTime": 1770379258, + "sunsetTime": 1770416384, + "moonPhase": 0.66, + "precipIntensity": 0.0, + "precipIntensityMax": 0.0, + "precipIntensityMaxTime": 1770354000, + "precipProbability": 0.33, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperatureHigh": -2.02, + "temperatureHighTime": 1770418800, + "temperatureLow": -4.82, + "temperatureLowTime": 1770462000, + "apparentTemperatureHigh": -5.66, + "apparentTemperatureHighTime": 1770411600, + "apparentTemperatureLow": -14.37, + "apparentTemperatureLowTime": 1770462000, + "dewPoint": -9.17, + "humidity": 0.71, + "pressure": 1007.52, + "windSpeed": 3.01, + "windGust": 4.09, + "windGustTime": 1770436800, + "windBearing": 281, + "cloudCover": 0.63, + "uvIndex": 3.7, + "uvIndexTime": 1770400800, + "visibility": 13.85, + "temperatureMin": -8.2, + "temperatureMinTime": 1770379200, + "temperatureMax": -1.72, + "temperatureMaxTime": 1770433200, + "apparentTemperatureMin": -13.29, + "apparentTemperatureMinTime": 1770379200, + "apparentTemperatureMax": -5.66, + "apparentTemperatureMaxTime": 1770411600 + }, + { + "time": 1770440400, + "summary": "Windy throughout the day.", + "icon": "wind", + "sunriseTime": 1770465591, + "sunsetTime": 1770502858, + "moonPhase": 0.69, + "precipIntensity": 0.0, + "precipIntensityMax": 0.0, + "precipIntensityMaxTime": 1770440400, + "precipProbability": 0.33, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperatureHigh": -5.58, + "temperatureHighTime": 1770465600, + "temperatureLow": -12.3, + "temperatureLowTime": 1770541200, + "apparentTemperatureHigh": -15.88, + "apparentTemperatureHighTime": 1770465600, + "apparentTemperatureLow": -21.7, + "apparentTemperatureLowTime": 1770519600, + "dewPoint": -13.05, + "humidity": 0.64, + "pressure": 1007.22, + "windSpeed": 9.57, + "windGust": 13.35, + "windGustTime": 1770498000, + "windBearing": 302, + "cloudCover": 0.45, + "uvIndex": 3.23, + "uvIndexTime": 1770483600, + "visibility": 11.95, + "temperatureMin": -11.0, + "temperatureMinTime": 1770523200, + "temperatureMax": -2.05, + "temperatureMaxTime": 1770440400, + "apparentTemperatureMin": -21.7, + "apparentTemperatureMinTime": 1770519600, + "apparentTemperatureMax": -7.86, + "apparentTemperatureMaxTime": 1770440400 + }, + { + "time": 1770526800, + "summary": "Breezy in the morning.", + "icon": "wind", + "sunriseTime": 1770551923, + "sunsetTime": 1770589332, + "moonPhase": 0.72, + "precipIntensity": 0.0, + "precipIntensityMax": 0.0, + "precipIntensityMaxTime": 1770526800, + "precipProbability": 0.07, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperatureHigh": -7.97, + "temperatureHighTime": 1770591600, + "temperatureLow": -10.64, + "temperatureLowTime": 1770634800, + "apparentTemperatureHigh": -14.7, + "apparentTemperatureHighTime": 1770584400, + "apparentTemperatureLow": -17.9, + "apparentTemperatureLowTime": 1770634800, + "dewPoint": -16.36, + "humidity": 0.61, + "pressure": 1022.11, + "windSpeed": 6.89, + "windGust": 9.71, + "windGustTime": 1770526800, + "windBearing": 313, + "cloudCover": 0.37, + "uvIndex": 3.98, + "uvIndexTime": 1770573600, + "visibility": 16.09, + "temperatureMin": -12.3, + "temperatureMinTime": 1770541200, + "temperatureMax": -7.86, + "temperatureMaxTime": 1770595200, + "apparentTemperatureMin": -21.66, + "apparentTemperatureMinTime": 1770541200, + "apparentTemperatureMax": -14.7, + "apparentTemperatureMaxTime": 1770584400 + }, + { + "time": 1770613200, + "summary": "Mostly clear until night.", + "icon": "clear-day", + "sunriseTime": 1770638253, + "sunsetTime": 1770675806, + "moonPhase": 0.75, + "precipIntensity": 0.0, + "precipIntensityMax": 0.0, + "precipIntensityMaxTime": 1770613200, + "precipProbability": 0.07, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperatureHigh": -4.77, + "temperatureHighTime": 1770670800, + "temperatureLow": -7.39, + "temperatureLowTime": 1770721200, + "apparentTemperatureHigh": -10.59, + "apparentTemperatureHighTime": 1770670800, + "apparentTemperatureLow": -14.19, + "apparentTemperatureLowTime": 1770714000, + "dewPoint": -13.37, + "humidity": 0.64, + "pressure": 1023.19, + "windSpeed": 5.64, + "windGust": 8.0, + "windGustTime": 1770670800, + "windBearing": 306, + "cloudCover": 0.35, + "uvIndex": 3.54, + "uvIndexTime": 1770660000, + "visibility": 16.09, + "temperatureMin": -10.96, + "temperatureMinTime": 1770638400, + "temperatureMax": -4.77, + "temperatureMaxTime": 1770670800, + "apparentTemperatureMin": -18.23, + "apparentTemperatureMinTime": 1770638400, + "apparentTemperatureMax": -10.59, + "apparentTemperatureMaxTime": 1770670800 + }, + { + "time": 1770699600, + "summary": "Mostly clear until evening.", + "icon": "clear-day", + "sunriseTime": 1770724581, + "sunsetTime": 1770762279, + "moonPhase": 0.78, + "precipIntensity": 0.0, + "precipIntensityMax": 0.0, + "precipIntensityMaxTime": 1770699600, + "precipProbability": 0.0, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperatureHigh": -1.3, + "temperatureHighTime": 1770757200, + "temperatureLow": -4.83, + "temperatureLowTime": 1770807600, + "apparentTemperatureHigh": -6.5, + "apparentTemperatureHighTime": 1770757200, + "apparentTemperatureLow": -10.85, + "apparentTemperatureLowTime": 1770807600, + "dewPoint": -10.03, + "humidity": 0.65, + "pressure": 1021.43, + "windSpeed": 4.8, + "windGust": 6.78, + "windGustTime": 1770699600, + "windBearing": 303, + "cloudCover": 0.37, + "uvIndex": 4.35, + "uvIndexTime": 1770746400, + "visibility": 15.2, + "temperatureMin": -7.39, + "temperatureMinTime": 1770721200, + "temperatureMax": -1.3, + "temperatureMaxTime": 1770757200, + "apparentTemperatureMin": -14.19, + "apparentTemperatureMinTime": 1770714000, + "apparentTemperatureMax": -6.5, + "apparentTemperatureMaxTime": 1770757200 + }, + { + "time": 1770786000, + "summary": "Hazy in the afternoon.", + "icon": "fog", + "sunriseTime": 1770810908, + "sunsetTime": 1770848753, + "moonPhase": 0.81, + "precipIntensity": 0.0, + "precipIntensityMax": 0.0, + "precipIntensityMaxTime": 1770786000, + "precipProbability": 0.08, + "precipAccumulation": 0.0, + "precipType": "snow", + "temperatureHigh": 2.11, + "temperatureHighTime": 1770836400, + "temperatureLow": -5.5, + "temperatureLowTime": 1770865200, + "apparentTemperatureHigh": -2.01, + "apparentTemperatureHighTime": 1770836400, + "apparentTemperatureLow": -8.93, + "apparentTemperatureLowTime": 1770876000, + "dewPoint": -6.87, + "humidity": 0.78, + "pressure": 1018.44, + "windSpeed": 3.33, + "windGust": 7.15, + "windGustTime": 1770854400, + "windBearing": 303, + "cloudCover": 0.5, + "uvIndex": 0.47, + "uvIndexTime": 1770832800, + "visibility": 10.62, + "temperatureMin": -5.5, + "temperatureMinTime": 1770865200, + "temperatureMax": 2.11, + "temperatureMaxTime": 1770836400, + "apparentTemperatureMin": -10.85, + "apparentTemperatureMinTime": 1770811200, + "apparentTemperatureMax": -2.01, + "apparentTemperatureMaxTime": 1770836400 + }, + { + "time": 1770872400, + "summary": "Possible snow (< 4 cm.) starting in the evening.", + "icon": "partly-cloudy-day", + "sunriseTime": 1770897234, + "sunsetTime": 1770935226, + "moonPhase": 0.84, + "precipIntensity": 0.15, + "precipIntensityMax": 1.008, + "precipIntensityMaxTime": 1770955200, + "precipProbability": 0.12, + "precipAccumulation": 0.9236, + "precipType": "snow", + "temperatureHigh": -0.19, + "temperatureHighTime": 1770919200, + "temperatureLow": -2.21, + "temperatureLowTime": 1770962400, + "apparentTemperatureHigh": 1.12, + "apparentTemperatureHighTime": 1770919200, + "apparentTemperatureLow": -7.73, + "apparentTemperatureLowTime": 1770980400, + "dewPoint": -4.45, + "humidity": 0.78, + "pressure": 1023.22, + "windSpeed": 0.95, + "windGust": 11.32, + "windGustTime": 1770886800, + "windBearing": 248, + "cloudCover": 0.47, + "uvIndex": 3.94, + "uvIndexTime": 1770919200, + "visibility": 16.09, + "temperatureMin": -5.35, + "temperatureMinTime": 1770872400, + "temperatureMax": -0.19, + "temperatureMaxTime": 1770919200, + "apparentTemperatureMin": -8.93, + "apparentTemperatureMinTime": 1770876000, + "apparentTemperatureMax": 1.12, + "apparentTemperatureMaxTime": 1770919200 + }, + { + "time": 1770958800, + "summary": "Light snow (< 10 cm.) throughout the day.", + "icon": "snow", + "sunriseTime": 1770983559, + "sunsetTime": 1771021699, + "moonPhase": 0.87, + "precipIntensity": 0.381, + "precipIntensityMax": 1.368, + "precipIntensityMaxTime": 1770962400, + "precipProbability": 0.34, + "precipAccumulation": 4.0291, + "precipType": "snow", + "temperatureHigh": -0.77, + "temperatureHighTime": 1771023600, + "temperatureLow": -0.81, + "temperatureLowTime": 1771048800, + "apparentTemperatureHigh": -3.43, + "apparentTemperatureHighTime": 1771005600, + "apparentTemperatureLow": -5.95, + "apparentTemperatureLowTime": 1771059600, + "dewPoint": -2.67, + "humidity": 0.8, + "pressure": 1015.78, + "windSpeed": 3.24, + "windGust": 12.21, + "windGustTime": 1771038000, + "windBearing": 30, + "cloudCover": 0.36, + "uvIndex": 3.8, + "uvIndexTime": 1771005600, + "visibility": 16.09, + "temperatureMin": -2.21, + "temperatureMinTime": 1770962400, + "temperatureMax": -0.64, + "temperatureMaxTime": 1771027200, + "apparentTemperatureMin": -7.91, + "apparentTemperatureMinTime": 1770984000, + "apparentTemperatureMax": -3.43, + "apparentTemperatureMaxTime": 1771005600 + } + ] + }, + "alerts": [ + { + "title": "Extreme Cold Warning", + "regions": [ + "Eastern Passaic", + "Hudson", + "Western Bergen", + "Eastern Bergen", + "Western Essex", + "Eastern Essex", + "Western Union", + "Eastern Union", + "Putnam", + "Rockland", + "Northern Westchester", + "Southern Westchester", + "New York (Manhattan)", + "Bronx", + "Richmond (Staten Is.)", + "Kings (Brooklyn)", + "Northern Queens", + "Southern Queens" + ], + "severity": "Severe", + "time": 1770402120, + "expires": 1770458400, + "description": "* WHAT...For the Wind Advisory, northwest winds 20 to 30 mph with gusts up to 50 mph expected. For the Extreme Cold Warning, dangerously cold wind chills as low as 20 below expected.\n* WHERE...Portions of northeast New Jersey and southeast New York.\n* WHEN...For the Wind Advisory, from 9 AM Saturday to midnight EST Saturday Night. For the Extreme Cold Warning, from 10 AM Saturday to 1 PM EST Sunday.\n* IMPACTS...Gusty winds will blow around unsecured objects. Tree limbs could be blown down and a few power outages may result. The cold wind chills could cause frostbite on exposed skin in as little as 30 minutes.", + "uri": "https://api.weather.gov/alerts/urn:oid:2.49.0.1.840.0.5df73ec191a300e305a2e7beb31cdbaded01fd49.004.1" + }, + { + "title": "Wind Advisory", + "regions": [ + "Eastern Passaic", + "Hudson", + "Western Bergen", + "Eastern Bergen", + "Western Essex", + "Eastern Essex", + "Western Union", + "Eastern Union", + "Putnam", + "Rockland", + "Northern Westchester", + "Southern Westchester", + "New York (Manhattan)", + "Bronx", + "Richmond (Staten Is.)", + "Kings (Brooklyn)", + "Northern Queens", + "Southern Queens" + ], + "severity": "Moderate", + "time": 1770402120, + "expires": 1770458400, + "description": "* WHAT...For the Wind Advisory, northwest winds 20 to 30 mph with gusts up to 50 mph expected. For the Extreme Cold Warning, dangerously cold wind chills as low as 20 below expected.\n* WHERE...Portions of northeast New Jersey and southeast New York.\n* WHEN...For the Wind Advisory, from 9 AM Saturday to midnight EST Saturday Night. For the Extreme Cold Warning, from 10 AM Saturday to 1 PM EST Sunday.\n* IMPACTS...Gusty winds will blow around unsecured objects. Tree limbs could be blown down and a few power outages may result. The cold wind chills could cause frostbite on exposed skin in as little as 30 minutes.", + "uri": "https://api.weather.gov/alerts/urn:oid:2.49.0.1.840.0.5df73ec191a300e305a2e7beb31cdbaded01fd49.004.2" + } + ], + "flags": { + "sources": ["ETOPO1", "hrrrsubh", "rtma_ru", "hrrr_0-18", "nbm", "nbm_fire", "dwd_mosmix", "ecmwf_ifs", "hrrr_18-48", "gfs", "gefs"], + "sourceTimes": { + "hrrr_subh": "2026-02-06 19Z", + "rtma_ru": "2026-02-06 21:15Z", + "hrrr_0-18": "2026-02-06 19Z", + "nbm": "2026-02-03 23Z", + "nbm_fire": "2026-02-06 12Z", + "dwd_mosmix": "2026-02-06 20Z", + "ecmwf_ifs": "2026-02-06 12Z", + "hrrr_18-48": "2026-02-06 18Z", + "gfs": "2026-02-06 12Z", + "gefs": "2026-02-06 12Z" + }, + "nearest-station": 10.96, + "units": "si", + "version": "V2.9.1" + } +} diff --git a/tests/mocks/weather_smhi.json b/tests/mocks/weather_smhi.json new file mode 100644 index 0000000000..c08a6e85b0 --- /dev/null +++ b/tests/mocks/weather_smhi.json @@ -0,0 +1,1907 @@ +{ + "approvedTime": "2026-02-06T21:31:33Z", + "referenceTime": "2026-02-06T21:00:00Z", + "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] } + ] + } + ] +} diff --git a/tests/mocks/weather_ukmetoffice.json b/tests/mocks/weather_ukmetoffice.json new file mode 100644 index 0000000000..1a5663e83c --- /dev/null +++ b/tests/mocks/weather_ukmetoffice.json @@ -0,0 +1,1062 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [-0.12480000000000001, 51.5081, 11.0] }, + "properties": { + "location": { "name": "London" }, + "requestPointDistance": 221.7807, + "modelRunDate": "2026-02-07T12:00Z", + "timeSeries": [ + { + "time": "2026-02-07T12:00Z", + "screenTemperature": 9.56, + "maxScreenAirTemp": 9.56, + "minScreenAirTemp": 9.11, + "screenDewPointTemperature": 8.51, + "feelsLikeTemperature": 8.74, + "windSpeed10m": 1.9, + "windDirectionFrom10m": 165, + "windGustSpeed10m": 7.72, + "max10mWindGust": 9.32, + "visibility": 8550, + "screenRelativeHumidity": 93.08, + "mslp": 99440, + "uvIndex": 1, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 15 + }, + { + "time": "2026-02-07T13:00Z", + "screenTemperature": 9.67, + "maxScreenAirTemp": 9.69, + "minScreenAirTemp": 9.56, + "screenDewPointTemperature": 8.39, + "feelsLikeTemperature": 8.76, + "windSpeed10m": 2.13, + "windDirectionFrom10m": 188, + "windGustSpeed10m": 7.31, + "max10mWindGust": 8.26, + "visibility": 7592, + "screenRelativeHumidity": 91.56, + "mslp": 99435, + "uvIndex": 1, + "significantWeatherCode": 11, + "precipitationRate": 0.06, + "totalPrecipAmount": 0.04, + "totalSnowAmount": 0, + "probOfPrecipitation": 33 + }, + { + "time": "2026-02-07T14:00Z", + "screenTemperature": 9.91, + "maxScreenAirTemp": 10.01, + "minScreenAirTemp": 9.67, + "screenDewPointTemperature": 8.62, + "feelsLikeTemperature": 8.29, + "windSpeed10m": 3.22, + "windDirectionFrom10m": 189, + "windGustSpeed10m": 8.15, + "max10mWindGust": 8.64, + "visibility": 9509, + "screenRelativeHumidity": 91.56, + "mslp": 99496, + "uvIndex": 1, + "significantWeatherCode": 14, + "precipitationRate": 1.5, + "totalPrecipAmount": 0.23, + "totalSnowAmount": 0, + "probOfPrecipitation": 62 + }, + { + "time": "2026-02-07T15:00Z", + "screenTemperature": 10.21, + "maxScreenAirTemp": 10.4, + "minScreenAirTemp": 9.91, + "screenDewPointTemperature": 8.5, + "feelsLikeTemperature": 8.19, + "windSpeed10m": 4.1, + "windDirectionFrom10m": 184, + "windGustSpeed10m": 9.49, + "max10mWindGust": 9.56, + "visibility": 9666, + "screenRelativeHumidity": 89.1, + "mslp": 99550, + "uvIndex": 1, + "significantWeatherCode": 12, + "precipitationRate": 0.24, + "totalPrecipAmount": 0.09, + "totalSnowAmount": 0, + "probOfPrecipitation": 55 + }, + { + "time": "2026-02-07T16:00Z", + "screenTemperature": 10.22, + "maxScreenAirTemp": 10.24, + "minScreenAirTemp": 10.18, + "screenDewPointTemperature": 8.24, + "feelsLikeTemperature": 8.28, + "windSpeed10m": 3.92, + "windDirectionFrom10m": 187, + "windGustSpeed10m": 8.95, + "max10mWindGust": 9.64, + "visibility": 7525, + "screenRelativeHumidity": 87.43, + "mslp": 99620, + "uvIndex": 1, + "significantWeatherCode": 12, + "precipitationRate": 0.53, + "totalPrecipAmount": 0.08, + "totalSnowAmount": 0, + "probOfPrecipitation": 59 + }, + { + "time": "2026-02-07T17:00Z", + "screenTemperature": 9.99, + "maxScreenAirTemp": 10.22, + "minScreenAirTemp": 9.98, + "screenDewPointTemperature": 8.13, + "feelsLikeTemperature": 8.22, + "windSpeed10m": 3.51, + "windDirectionFrom10m": 180, + "windGustSpeed10m": 8.31, + "max10mWindGust": 9.11, + "visibility": 11604, + "screenRelativeHumidity": 88.07, + "mslp": 99680, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 5 + }, + { + "time": "2026-02-07T18:00Z", + "screenTemperature": 9.89, + "maxScreenAirTemp": 9.99, + "minScreenAirTemp": 9.84, + "screenDewPointTemperature": 8.13, + "feelsLikeTemperature": 8.07, + "windSpeed10m": 3.54, + "windDirectionFrom10m": 181, + "windGustSpeed10m": 8.86, + "max10mWindGust": 9.03, + "visibility": 11879, + "screenRelativeHumidity": 88.72, + "mslp": 99760, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-07T19:00Z", + "screenTemperature": 9.68, + "maxScreenAirTemp": 9.89, + "minScreenAirTemp": 9.67, + "screenDewPointTemperature": 8.06, + "feelsLikeTemperature": 7.86, + "windSpeed10m": 3.45, + "windDirectionFrom10m": 183, + "windGustSpeed10m": 8.57, + "max10mWindGust": 8.86, + "visibility": 12104, + "screenRelativeHumidity": 89.57, + "mslp": 99816, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-07T20:00Z", + "screenTemperature": 9.59, + "maxScreenAirTemp": 9.68, + "minScreenAirTemp": 9.57, + "screenDewPointTemperature": 8.02, + "feelsLikeTemperature": 7.96, + "windSpeed10m": 3.08, + "windDirectionFrom10m": 179, + "windGustSpeed10m": 8.15, + "max10mWindGust": 8.88, + "visibility": 12574, + "screenRelativeHumidity": 89.91, + "mslp": 99876, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 4 + }, + { + "time": "2026-02-07T21:00Z", + "screenTemperature": 9.34, + "maxScreenAirTemp": 9.59, + "minScreenAirTemp": 9.34, + "screenDewPointTemperature": 8.01, + "feelsLikeTemperature": 7.65, + "windSpeed10m": 3.12, + "windDirectionFrom10m": 180, + "windGustSpeed10m": 7.95, + "max10mWindGust": 8.46, + "visibility": 12829, + "screenRelativeHumidity": 91.36, + "mslp": 99932, + "uvIndex": 0, + "significantWeatherCode": 2, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 3 + }, + { + "time": "2026-02-07T22:00Z", + "screenTemperature": 9.0, + "maxScreenAirTemp": 9.34, + "minScreenAirTemp": 8.98, + "screenDewPointTemperature": 7.71, + "feelsLikeTemperature": 7.27, + "windSpeed10m": 3.08, + "windDirectionFrom10m": 177, + "windGustSpeed10m": 8.34, + "max10mWindGust": 8.76, + "visibility": 12923, + "screenRelativeHumidity": 91.6, + "mslp": 99986, + "uvIndex": 0, + "significantWeatherCode": 0, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 2 + }, + { + "time": "2026-02-07T23:00Z", + "screenTemperature": 8.74, + "maxScreenAirTemp": 8.98, + "minScreenAirTemp": 8.71, + "screenDewPointTemperature": 7.57, + "feelsLikeTemperature": 7.09, + "windSpeed10m": 2.86, + "windDirectionFrom10m": 177, + "windGustSpeed10m": 7.68, + "max10mWindGust": 8.78, + "visibility": 14190, + "screenRelativeHumidity": 92.32, + "mslp": 100056, + "uvIndex": 0, + "significantWeatherCode": 0, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 2 + }, + { + "time": "2026-02-08T00:00Z", + "screenTemperature": 8.56, + "maxScreenAirTemp": 8.74, + "minScreenAirTemp": 8.56, + "screenDewPointTemperature": 7.59, + "feelsLikeTemperature": 7.12, + "windSpeed10m": 2.52, + "windDirectionFrom10m": 184, + "windGustSpeed10m": 7.13, + "max10mWindGust": 8.49, + "visibility": 13732, + "screenRelativeHumidity": 93.62, + "mslp": 100096, + "uvIndex": 0, + "significantWeatherCode": 2, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 2 + }, + { + "time": "2026-02-08T01:00Z", + "screenTemperature": 8.4, + "maxScreenAirTemp": 8.56, + "minScreenAirTemp": 8.38, + "screenDewPointTemperature": 7.27, + "feelsLikeTemperature": 7.08, + "windSpeed10m": 2.32, + "windDirectionFrom10m": 180, + "windGustSpeed10m": 6.73, + "max10mWindGust": 7.62, + "visibility": 14599, + "screenRelativeHumidity": 92.57, + "mslp": 100150, + "uvIndex": 0, + "significantWeatherCode": 2, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 2 + }, + { + "time": "2026-02-08T02:00Z", + "screenTemperature": 8.14, + "maxScreenAirTemp": 8.4, + "minScreenAirTemp": 8.13, + "screenDewPointTemperature": 7.17, + "feelsLikeTemperature": 7.11, + "windSpeed10m": 1.93, + "windDirectionFrom10m": 191, + "windGustSpeed10m": 5.96, + "max10mWindGust": 7.23, + "visibility": 12665, + "screenRelativeHumidity": 93.62, + "mslp": 100190, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 5 + }, + { + "time": "2026-02-08T03:00Z", + "screenTemperature": 7.9, + "maxScreenAirTemp": 8.14, + "minScreenAirTemp": 7.89, + "screenDewPointTemperature": 7.12, + "feelsLikeTemperature": 7.1, + "windSpeed10m": 1.63, + "windDirectionFrom10m": 195, + "windGustSpeed10m": 5.28, + "max10mWindGust": 6.22, + "visibility": 10018, + "screenRelativeHumidity": 94.84, + "mslp": 100224, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 5 + }, + { + "time": "2026-02-08T04:00Z", + "screenTemperature": 7.78, + "maxScreenAirTemp": 7.9, + "minScreenAirTemp": 7.76, + "screenDewPointTemperature": 7.07, + "feelsLikeTemperature": 6.86, + "windSpeed10m": 1.74, + "windDirectionFrom10m": 188, + "windGustSpeed10m": 5.13, + "max10mWindGust": 5.76, + "visibility": 8777, + "screenRelativeHumidity": 95.25, + "mslp": 100253, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 5 + }, + { + "time": "2026-02-08T05:00Z", + "screenTemperature": 7.67, + "maxScreenAirTemp": 7.78, + "minScreenAirTemp": 7.62, + "screenDewPointTemperature": 7.02, + "feelsLikeTemperature": 6.77, + "windSpeed10m": 1.64, + "windDirectionFrom10m": 177, + "windGustSpeed10m": 5.17, + "max10mWindGust": 5.88, + "visibility": 7296, + "screenRelativeHumidity": 95.73, + "mslp": 100280, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 5 + }, + { + "time": "2026-02-08T06:00Z", + "screenTemperature": 7.52, + "maxScreenAirTemp": 7.67, + "minScreenAirTemp": 7.47, + "screenDewPointTemperature": 6.7, + "feelsLikeTemperature": 6.68, + "windSpeed10m": 1.6, + "windDirectionFrom10m": 183, + "windGustSpeed10m": 4.97, + "max10mWindGust": 5.64, + "visibility": 7420, + "screenRelativeHumidity": 94.66, + "mslp": 100327, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 5 + }, + { + "time": "2026-02-08T07:00Z", + "screenTemperature": 7.63, + "maxScreenAirTemp": 7.64, + "minScreenAirTemp": 7.52, + "screenDewPointTemperature": 6.82, + "feelsLikeTemperature": 6.29, + "windSpeed10m": 2.18, + "windDirectionFrom10m": 182, + "windGustSpeed10m": 5.54, + "max10mWindGust": 6.01, + "visibility": 7504, + "screenRelativeHumidity": 94.7, + "mslp": 100390, + "uvIndex": 0, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 10 + }, + { + "time": "2026-02-08T08:00Z", + "screenTemperature": 7.81, + "maxScreenAirTemp": 7.81, + "minScreenAirTemp": 7.63, + "screenDewPointTemperature": 7.06, + "feelsLikeTemperature": 6.72, + "windSpeed10m": 1.93, + "windDirectionFrom10m": 190, + "windGustSpeed10m": 4.93, + "max10mWindGust": 5.86, + "visibility": 6197, + "screenRelativeHumidity": 95.08, + "mslp": 100450, + "uvIndex": 1, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 9 + }, + { + "time": "2026-02-08T09:00Z", + "screenTemperature": 8.12, + "maxScreenAirTemp": 8.13, + "minScreenAirTemp": 7.81, + "screenDewPointTemperature": 7.2, + "feelsLikeTemperature": 7.05, + "windSpeed10m": 1.95, + "windDirectionFrom10m": 180, + "windGustSpeed10m": 4.53, + "max10mWindGust": 4.92, + "visibility": 6327, + "screenRelativeHumidity": 94.03, + "mslp": 100503, + "uvIndex": 1, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 10 + }, + { + "time": "2026-02-08T10:00Z", + "screenTemperature": 8.86, + "maxScreenAirTemp": 8.86, + "minScreenAirTemp": 8.12, + "screenDewPointTemperature": 7.54, + "feelsLikeTemperature": 7.73, + "windSpeed10m": 2.17, + "windDirectionFrom10m": 176, + "windGustSpeed10m": 4.42, + "max10mWindGust": 4.54, + "visibility": 7222, + "screenRelativeHumidity": 91.55, + "mslp": 100533, + "uvIndex": 1, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 10 + }, + { + "time": "2026-02-08T11:00Z", + "screenTemperature": 9.57, + "maxScreenAirTemp": 9.57, + "minScreenAirTemp": 8.86, + "screenDewPointTemperature": 7.57, + "feelsLikeTemperature": 8.41, + "windSpeed10m": 2.37, + "windDirectionFrom10m": 181, + "windGustSpeed10m": 4.88, + "max10mWindGust": 4.88, + "visibility": 10651, + "screenRelativeHumidity": 87.5, + "mslp": 100560, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-08T12:00Z", + "screenTemperature": 10.27, + "maxScreenAirTemp": 10.28, + "minScreenAirTemp": 9.57, + "screenDewPointTemperature": 7.41, + "feelsLikeTemperature": 9.29, + "windSpeed10m": 2.28, + "windDirectionFrom10m": 185, + "windGustSpeed10m": 4.71, + "max10mWindGust": 4.71, + "visibility": 12395, + "screenRelativeHumidity": 82.51, + "mslp": 100560, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-08T13:00Z", + "screenTemperature": 10.75, + "maxScreenAirTemp": 10.76, + "minScreenAirTemp": 10.27, + "screenDewPointTemperature": 6.87, + "feelsLikeTemperature": 9.48, + "windSpeed10m": 2.77, + "windDirectionFrom10m": 184, + "windGustSpeed10m": 5.56, + "max10mWindGust": 5.56, + "visibility": 14708, + "screenRelativeHumidity": 76.97, + "mslp": 100530, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-08T14:00Z", + "screenTemperature": 10.84, + "maxScreenAirTemp": 10.88, + "minScreenAirTemp": 10.75, + "screenDewPointTemperature": 6.71, + "feelsLikeTemperature": 9.4, + "windSpeed10m": 3.1, + "windDirectionFrom10m": 186, + "windGustSpeed10m": 6.12, + "max10mWindGust": 6.29, + "visibility": 16685, + "screenRelativeHumidity": 75.74, + "mslp": 100530, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 7 + }, + { + "time": "2026-02-08T15:00Z", + "screenTemperature": 10.76, + "maxScreenAirTemp": 10.84, + "minScreenAirTemp": 10.73, + "screenDewPointTemperature": 6.67, + "feelsLikeTemperature": 9.29, + "windSpeed10m": 3.11, + "windDirectionFrom10m": 182, + "windGustSpeed10m": 6.07, + "max10mWindGust": 6.26, + "visibility": 16963, + "screenRelativeHumidity": 75.87, + "mslp": 100527, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 7 + }, + { + "time": "2026-02-08T16:00Z", + "screenTemperature": 10.36, + "maxScreenAirTemp": 10.76, + "minScreenAirTemp": 10.33, + "screenDewPointTemperature": 6.66, + "feelsLikeTemperature": 8.88, + "windSpeed10m": 3.07, + "windDirectionFrom10m": 180, + "windGustSpeed10m": 5.99, + "max10mWindGust": 6.33, + "visibility": 17519, + "screenRelativeHumidity": 77.89, + "mslp": 100530, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 7 + }, + { + "time": "2026-02-08T17:00Z", + "screenTemperature": 9.94, + "maxScreenAirTemp": 10.36, + "minScreenAirTemp": 9.93, + "screenDewPointTemperature": 6.86, + "feelsLikeTemperature": 8.52, + "windSpeed10m": 2.84, + "windDirectionFrom10m": 179, + "windGustSpeed10m": 5.58, + "max10mWindGust": 6.05, + "visibility": 16071, + "screenRelativeHumidity": 81.23, + "mslp": 100550, + "uvIndex": 0, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 10 + }, + { + "time": "2026-02-08T18:00Z", + "screenTemperature": 9.55, + "maxScreenAirTemp": 9.94, + "minScreenAirTemp": 9.54, + "screenDewPointTemperature": 6.97, + "feelsLikeTemperature": 8.1, + "windSpeed10m": 2.81, + "windDirectionFrom10m": 176, + "windGustSpeed10m": 5.68, + "max10mWindGust": 6.14, + "visibility": 15755, + "screenRelativeHumidity": 83.93, + "mslp": 100560, + "uvIndex": 0, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 12 + }, + { + "time": "2026-02-08T19:00Z", + "screenTemperature": 9.23, + "maxScreenAirTemp": 9.55, + "minScreenAirTemp": 9.22, + "screenDewPointTemperature": 7.05, + "feelsLikeTemperature": 7.71, + "windSpeed10m": 2.83, + "windDirectionFrom10m": 168, + "windGustSpeed10m": 5.67, + "max10mWindGust": 6.27, + "visibility": 14548, + "screenRelativeHumidity": 86.32, + "mslp": 100547, + "uvIndex": 0, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 18 + }, + { + "time": "2026-02-08T20:00Z", + "screenTemperature": 9.05, + "maxScreenAirTemp": 9.23, + "minScreenAirTemp": 9.04, + "screenDewPointTemperature": 7.13, + "feelsLikeTemperature": 7.66, + "windSpeed10m": 2.57, + "windDirectionFrom10m": 173, + "windGustSpeed10m": 5.24, + "max10mWindGust": 6.08, + "visibility": 13961, + "screenRelativeHumidity": 87.79, + "mslp": 100547, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 17 + }, + { + "time": "2026-02-08T21:00Z", + "screenTemperature": 8.81, + "maxScreenAirTemp": 9.05, + "minScreenAirTemp": 8.81, + "screenDewPointTemperature": 7.2, + "feelsLikeTemperature": 7.4, + "windSpeed10m": 2.56, + "windDirectionFrom10m": 163, + "windGustSpeed10m": 5.38, + "max10mWindGust": 5.73, + "visibility": 13739, + "screenRelativeHumidity": 89.7, + "mslp": 100540, + "uvIndex": 0, + "significantWeatherCode": 12, + "precipitationRate": 0.07, + "totalPrecipAmount": 0.2, + "totalSnowAmount": 0, + "probOfPrecipitation": 45 + }, + { + "time": "2026-02-08T22:00Z", + "screenTemperature": 8.74, + "maxScreenAirTemp": 8.81, + "minScreenAirTemp": 8.72, + "screenDewPointTemperature": 7.12, + "feelsLikeTemperature": 7.36, + "windSpeed10m": 2.47, + "windDirectionFrom10m": 164, + "windGustSpeed10m": 5.43, + "max10mWindGust": 5.67, + "visibility": 11395, + "screenRelativeHumidity": 89.66, + "mslp": 100530, + "uvIndex": 0, + "significantWeatherCode": 9, + "precipitationRate": 0.23, + "totalPrecipAmount": 0.18, + "totalSnowAmount": 0, + "probOfPrecipitation": 44 + }, + { + "time": "2026-02-08T23:00Z", + "screenTemperature": 8.57, + "maxScreenAirTemp": 8.74, + "minScreenAirTemp": 8.53, + "screenDewPointTemperature": 7.23, + "feelsLikeTemperature": 7.31, + "windSpeed10m": 2.28, + "windDirectionFrom10m": 149, + "windGustSpeed10m": 5.28, + "max10mWindGust": 5.87, + "visibility": 10051, + "screenRelativeHumidity": 91.35, + "mslp": 100497, + "uvIndex": 0, + "significantWeatherCode": 12, + "precipitationRate": 0.22, + "totalPrecipAmount": 0.26, + "totalSnowAmount": 0, + "probOfPrecipitation": 54 + }, + { + "time": "2026-02-09T00:00Z", + "screenTemperature": 8.52, + "maxScreenAirTemp": 8.57, + "minScreenAirTemp": 8.49, + "screenDewPointTemperature": 7.17, + "feelsLikeTemperature": 7.21, + "windSpeed10m": 2.32, + "windDirectionFrom10m": 151, + "windGustSpeed10m": 5.44, + "max10mWindGust": 5.96, + "visibility": 13108, + "screenRelativeHumidity": 91.42, + "mslp": 100475, + "uvIndex": 0, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 13 + }, + { + "time": "2026-02-09T01:00Z", + "screenTemperature": 8.39, + "maxScreenAirTemp": 8.52, + "minScreenAirTemp": 8.36, + "screenDewPointTemperature": 7.08, + "feelsLikeTemperature": 6.94, + "windSpeed10m": 2.49, + "windDirectionFrom10m": 157, + "windGustSpeed10m": 5.83, + "max10mWindGust": 6.54, + "visibility": 14678, + "screenRelativeHumidity": 91.55, + "mslp": 100430, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 12 + }, + { + "time": "2026-02-09T02:00Z", + "screenTemperature": 8.23, + "maxScreenAirTemp": 8.39, + "minScreenAirTemp": 8.18, + "screenDewPointTemperature": 6.88, + "feelsLikeTemperature": 6.86, + "windSpeed10m": 2.34, + "windDirectionFrom10m": 155, + "windGustSpeed10m": 5.35, + "max10mWindGust": 6.7, + "visibility": 13081, + "screenRelativeHumidity": 91.35, + "mslp": 100385, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 16 + }, + { + "time": "2026-02-09T03:00Z", + "screenTemperature": 8.1, + "maxScreenAirTemp": 8.23, + "minScreenAirTemp": 8.05, + "screenDewPointTemperature": 6.78, + "feelsLikeTemperature": 6.67, + "windSpeed10m": 2.37, + "windDirectionFrom10m": 150, + "windGustSpeed10m": 5.35, + "max10mWindGust": 6.67, + "visibility": 15140, + "screenRelativeHumidity": 91.56, + "mslp": 100335, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 7 + }, + { + "time": "2026-02-09T04:00Z", + "screenTemperature": 7.9, + "maxScreenAirTemp": 8.1, + "minScreenAirTemp": 7.86, + "screenDewPointTemperature": 6.58, + "feelsLikeTemperature": 6.41, + "windSpeed10m": 2.39, + "windDirectionFrom10m": 149, + "windGustSpeed10m": 5.43, + "max10mWindGust": 6.53, + "visibility": 15366, + "screenRelativeHumidity": 91.65, + "mslp": 100305, + "uvIndex": 0, + "significantWeatherCode": 8, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 10 + }, + { + "time": "2026-02-09T05:00Z", + "screenTemperature": 7.71, + "maxScreenAirTemp": 7.9, + "minScreenAirTemp": 7.65, + "screenDewPointTemperature": 6.51, + "feelsLikeTemperature": 6.28, + "windSpeed10m": 2.3, + "windDirectionFrom10m": 146, + "windGustSpeed10m": 5.3, + "max10mWindGust": 6.91, + "visibility": 14570, + "screenRelativeHumidity": 92.33, + "mslp": 100283, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-09T06:00Z", + "screenTemperature": 7.56, + "maxScreenAirTemp": 7.71, + "minScreenAirTemp": 7.54, + "screenDewPointTemperature": 6.38, + "feelsLikeTemperature": 6.11, + "windSpeed10m": 2.29, + "windDirectionFrom10m": 148, + "windGustSpeed10m": 5.34, + "max10mWindGust": 6.56, + "visibility": 13685, + "screenRelativeHumidity": 92.49, + "mslp": 100280, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-09T07:00Z", + "screenTemperature": 7.61, + "maxScreenAirTemp": 7.62, + "minScreenAirTemp": 7.56, + "screenDewPointTemperature": 6.43, + "feelsLikeTemperature": 6.17, + "windSpeed10m": 2.28, + "windDirectionFrom10m": 146, + "windGustSpeed10m": 5.26, + "max10mWindGust": 6.34, + "visibility": 13185, + "screenRelativeHumidity": 92.48, + "mslp": 100282, + "uvIndex": 0, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 7 + }, + { + "time": "2026-02-09T08:00Z", + "screenTemperature": 7.7, + "maxScreenAirTemp": 7.75, + "minScreenAirTemp": 7.61, + "screenDewPointTemperature": 6.48, + "feelsLikeTemperature": 6.25, + "windSpeed10m": 2.34, + "windDirectionFrom10m": 146, + "windGustSpeed10m": 5.57, + "max10mWindGust": 5.76, + "visibility": 13541, + "screenRelativeHumidity": 92.21, + "mslp": 100275, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-09T09:00Z", + "screenTemperature": 7.92, + "maxScreenAirTemp": 7.92, + "minScreenAirTemp": 7.7, + "screenDewPointTemperature": 6.53, + "feelsLikeTemperature": 6.42, + "windSpeed10m": 2.43, + "windDirectionFrom10m": 142, + "windGustSpeed10m": 5.54, + "max10mWindGust": 6.4, + "visibility": 13747, + "screenRelativeHumidity": 91.19, + "mslp": 100275, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-09T10:00Z", + "screenTemperature": 8.6, + "maxScreenAirTemp": 8.65, + "minScreenAirTemp": 7.92, + "screenDewPointTemperature": 6.57, + "feelsLikeTemperature": 7.09, + "windSpeed10m": 2.66, + "windDirectionFrom10m": 146, + "windGustSpeed10m": 5.71, + "max10mWindGust": 5.71, + "visibility": 14552, + "screenRelativeHumidity": 87.48, + "mslp": 100241, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-09T11:00Z", + "screenTemperature": 9.43, + "maxScreenAirTemp": 9.43, + "minScreenAirTemp": 8.6, + "screenDewPointTemperature": 6.49, + "feelsLikeTemperature": 7.83, + "windSpeed10m": 3.0, + "windDirectionFrom10m": 151, + "windGustSpeed10m": 6.25, + "max10mWindGust": 6.25, + "visibility": 19055, + "screenRelativeHumidity": 82.28, + "mslp": 100209, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "totalPrecipAmount": 0.0, + "totalSnowAmount": 0, + "probOfPrecipitation": 6 + }, + { + "time": "2026-02-09T12:00Z", + "screenTemperature": 10.25, + "screenDewPointTemperature": 6.37, + "feelsLikeTemperature": 8.61, + "windSpeed10m": 3.28, + "windDirectionFrom10m": 155, + "windGustSpeed10m": 6.87, + "visibility": 20517, + "screenRelativeHumidity": 77.18, + "mslp": 100150, + "uvIndex": 1, + "significantWeatherCode": 7, + "precipitationRate": 0.0, + "probOfPrecipitation": 6 + } + ] + } + } + ], + "parameters": [ + { + "totalSnowAmount": { "type": "Parameter", "description": "Total Snow Amount Over Previous Hour", "unit": { "label": "millimetres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "mm" } } }, + "screenTemperature": { "type": "Parameter", "description": "Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "visibility": { "type": "Parameter", "description": "Visibility", "unit": { "label": "metres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m" } } }, + "windDirectionFrom10m": { "type": "Parameter", "description": "10m Wind From Direction", "unit": { "label": "degrees", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "deg" } } }, + "precipitationRate": { "type": "Parameter", "description": "Precipitation Rate", "unit": { "label": "millimetres per hour", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "mm/h" } } }, + "maxScreenAirTemp": { "type": "Parameter", "description": "Maximum Screen Air Temperature Over Previous Hour", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "feelsLikeTemperature": { "type": "Parameter", "description": "Feels Like Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "screenDewPointTemperature": { "type": "Parameter", "description": "Screen Dew Point Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "screenRelativeHumidity": { "type": "Parameter", "description": "Screen Relative Humidity", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "windSpeed10m": { "type": "Parameter", "description": "10m Wind Speed", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } }, + "probOfPrecipitation": { "type": "Parameter", "description": "Probability of Precipitation", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "max10mWindGust": { "type": "Parameter", "description": "Maximum 10m Wind Gust Speed Over Previous Hour", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } }, + "significantWeatherCode": { "type": "Parameter", "description": "Significant Weather Code", "unit": { "label": "dimensionless", "symbol": { "value": "https://datahub.metoffice.gov.uk/", "type": "1" } } }, + "minScreenAirTemp": { "type": "Parameter", "description": "Minimum Screen Air Temperature Over Previous Hour", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "totalPrecipAmount": { "type": "Parameter", "description": "Total Precipitation Amount Over Previous Hour", "unit": { "label": "millimetres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "mm" } } }, + "mslp": { "type": "Parameter", "description": "Mean Sea Level Pressure", "unit": { "label": "pascals", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Pa" } } }, + "windGustSpeed10m": { "type": "Parameter", "description": "10m Wind Gust Speed", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } }, + "uvIndex": { "type": "Parameter", "description": "UV Index", "unit": { "label": "dimensionless", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "1" } } } + } + ] +} diff --git a/tests/mocks/weather_ukmetoffice_daily.json b/tests/mocks/weather_ukmetoffice_daily.json new file mode 100644 index 0000000000..e774a0f575 --- /dev/null +++ b/tests/mocks/weather_ukmetoffice_daily.json @@ -0,0 +1,419 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [-0.12480000000000001, 51.5081, 11.0] }, + "properties": { + "location": { "name": "London" }, + "requestPointDistance": 221.7807, + "modelRunDate": "2026-02-07T12:00Z", + "timeSeries": [ + { + "time": "2026-02-06T00:00Z", + "midday10MWindSpeed": 0.82, + "midnight10MWindSpeed": 1.59, + "midday10MWindDirection": 121, + "midnight10MWindDirection": 175, + "midday10MWindGust": 3.09, + "midnight10MWindGust": 7.72, + "middayVisibility": 4000, + "midnightVisibility": 12560, + "middayRelativeHumidity": 92.93, + "midnightRelativeHumidity": 89.85, + "middayMslp": 98480, + "midnightMslp": 99260, + "nightSignificantWeatherCode": 2, + "dayMaxScreenTemperature": 11.37, + "nightMinScreenTemperature": 7.26, + "dayUpperBoundMaxTemp": 12.53, + "nightUpperBoundMinTemp": 8.77, + "dayLowerBoundMaxTemp": 9.86, + "nightLowerBoundMinTemp": 6.62, + "nightMinFeelsLikeTemp": 5.98, + "dayUpperBoundMaxFeelsLikeTemp": 11.58, + "nightUpperBoundMinFeelsLikeTemp": 6.83, + "dayLowerBoundMaxFeelsLikeTemp": 8.89, + "nightLowerBoundMinFeelsLikeTemp": 5.23, + "nightProbabilityOfPrecipitation": 85, + "nightProbabilityOfSnow": 0, + "nightProbabilityOfHeavySnow": 0, + "nightProbabilityOfRain": 85, + "nightProbabilityOfHeavyRain": 80, + "nightProbabilityOfHail": 16, + "nightProbabilityOfSferics": 8 + }, + { + "time": "2026-02-07T00:00Z", + "midday10MWindSpeed": 1.9, + "midnight10MWindSpeed": 2.52, + "midday10MWindDirection": 165, + "midnight10MWindDirection": 184, + "midday10MWindGust": 7.72, + "midnight10MWindGust": 7.13, + "middayVisibility": 8550, + "midnightVisibility": 13732, + "middayRelativeHumidity": 93.08, + "midnightRelativeHumidity": 93.62, + "middayMslp": 99440, + "midnightMslp": 100100, + "maxUvIndex": 1, + "daySignificantWeatherCode": 12, + "nightSignificantWeatherCode": 7, + "dayMaxScreenTemperature": 10.5, + "nightMinScreenTemperature": 7.52, + "dayUpperBoundMaxTemp": 11.72, + "nightUpperBoundMinTemp": 9.39, + "dayLowerBoundMaxTemp": 9.78, + "nightLowerBoundMinTemp": 5.83, + "dayMaxFeelsLikeTemp": 8.76, + "nightMinFeelsLikeTemp": 6.29, + "dayUpperBoundMaxFeelsLikeTemp": 9.47, + "nightUpperBoundMinFeelsLikeTemp": 8.28, + "dayLowerBoundMaxFeelsLikeTemp": 8.06, + "nightLowerBoundMinFeelsLikeTemp": 5.22, + "dayProbabilityOfPrecipitation": 91, + "nightProbabilityOfPrecipitation": 10, + "dayProbabilityOfSnow": 0, + "nightProbabilityOfSnow": 0, + "dayProbabilityOfHeavySnow": 0, + "nightProbabilityOfHeavySnow": 0, + "dayProbabilityOfRain": 91, + "nightProbabilityOfRain": 10, + "dayProbabilityOfHeavyRain": 86, + "nightProbabilityOfHeavyRain": 2, + "dayProbabilityOfHail": 17, + "nightProbabilityOfHail": 0, + "dayProbabilityOfSferics": 11, + "nightProbabilityOfSferics": 0 + }, + { + "time": "2026-02-08T00:00Z", + "midday10MWindSpeed": 2.28, + "midnight10MWindSpeed": 2.32, + "midday10MWindDirection": 185, + "midnight10MWindDirection": 151, + "midday10MWindGust": 4.71, + "midnight10MWindGust": 5.44, + "middayVisibility": 12395, + "midnightVisibility": 13108, + "middayRelativeHumidity": 82.51, + "midnightRelativeHumidity": 91.42, + "middayMslp": 100559, + "midnightMslp": 100474, + "maxUvIndex": 1, + "daySignificantWeatherCode": 7, + "nightSignificantWeatherCode": 7, + "dayMaxScreenTemperature": 11.07, + "nightMinScreenTemperature": 7.56, + "dayUpperBoundMaxTemp": 11.84, + "nightUpperBoundMinTemp": 8.59, + "dayLowerBoundMaxTemp": 9.76, + "nightLowerBoundMinTemp": 5.18, + "dayMaxFeelsLikeTemp": 9.48, + "nightMinFeelsLikeTemp": 6.11, + "dayUpperBoundMaxFeelsLikeTemp": 10.97, + "nightUpperBoundMinFeelsLikeTemp": 7.32, + "dayLowerBoundMaxFeelsLikeTemp": 8.13, + "nightLowerBoundMinFeelsLikeTemp": 5.38, + "dayProbabilityOfPrecipitation": 10, + "nightProbabilityOfPrecipitation": 54, + "dayProbabilityOfSnow": 0, + "nightProbabilityOfSnow": 0, + "dayProbabilityOfHeavySnow": 0, + "nightProbabilityOfHeavySnow": 0, + "dayProbabilityOfRain": 10, + "nightProbabilityOfRain": 54, + "dayProbabilityOfHeavyRain": 2, + "nightProbabilityOfHeavyRain": 32, + "dayProbabilityOfHail": 0, + "nightProbabilityOfHail": 4, + "dayProbabilityOfSferics": 0, + "nightProbabilityOfSferics": 6 + }, + { + "time": "2026-02-09T00:00Z", + "midday10MWindSpeed": 3.28, + "midnight10MWindSpeed": 3.42, + "midday10MWindDirection": 155, + "midnight10MWindDirection": 121, + "midday10MWindGust": 6.87, + "midnight10MWindGust": 7.02, + "middayVisibility": 20517, + "midnightVisibility": 18708, + "middayRelativeHumidity": 77.18, + "midnightRelativeHumidity": 86.28, + "middayMslp": 100150, + "midnightMslp": 99580, + "maxUvIndex": 1, + "daySignificantWeatherCode": 7, + "nightSignificantWeatherCode": 7, + "dayMaxScreenTemperature": 10.89, + "nightMinScreenTemperature": 6.93, + "dayUpperBoundMaxTemp": 11.87, + "nightUpperBoundMinTemp": 8.61, + "dayLowerBoundMaxTemp": 8.55, + "nightLowerBoundMinTemp": 4.78, + "dayMaxFeelsLikeTemp": 9.06, + "nightMinFeelsLikeTemp": 5.13, + "dayUpperBoundMaxFeelsLikeTemp": 9.87, + "nightUpperBoundMinFeelsLikeTemp": 6.29, + "dayLowerBoundMaxFeelsLikeTemp": 6.57, + "nightLowerBoundMinFeelsLikeTemp": 3.3, + "dayProbabilityOfPrecipitation": 6, + "nightProbabilityOfPrecipitation": 18, + "dayProbabilityOfSnow": 0, + "nightProbabilityOfSnow": 0, + "dayProbabilityOfHeavySnow": 0, + "nightProbabilityOfHeavySnow": 0, + "dayProbabilityOfRain": 6, + "nightProbabilityOfRain": 18, + "dayProbabilityOfHeavyRain": 1, + "nightProbabilityOfHeavyRain": 7, + "dayProbabilityOfHail": 0, + "nightProbabilityOfHail": 1, + "dayProbabilityOfSferics": 0, + "nightProbabilityOfSferics": 0 + }, + { + "time": "2026-02-10T00:00Z", + "midday10MWindSpeed": 3.09, + "midnight10MWindSpeed": 3.12, + "midday10MWindDirection": 150, + "midnight10MWindDirection": 191, + "midday10MWindGust": 6.52, + "midnight10MWindGust": 6.18, + "middayVisibility": 17148, + "midnightVisibility": 12750, + "middayRelativeHumidity": 86.68, + "midnightRelativeHumidity": 93.78, + "middayMslp": 98991, + "midnightMslp": 98238, + "maxUvIndex": 1, + "daySignificantWeatherCode": 8, + "nightSignificantWeatherCode": 12, + "dayMaxScreenTemperature": 10.47, + "nightMinScreenTemperature": 8.75, + "dayUpperBoundMaxTemp": 13.15, + "nightUpperBoundMinTemp": 10.63, + "dayLowerBoundMaxTemp": 7.91, + "nightLowerBoundMinTemp": 6.14, + "dayMaxFeelsLikeTemp": 8.44, + "nightMinFeelsLikeTemp": 7.65, + "dayUpperBoundMaxFeelsLikeTemp": 11.11, + "nightUpperBoundMinFeelsLikeTemp": 8.73, + "dayLowerBoundMaxFeelsLikeTemp": 6.87, + "nightLowerBoundMinFeelsLikeTemp": 5.59, + "dayProbabilityOfPrecipitation": 49, + "nightProbabilityOfPrecipitation": 54, + "dayProbabilityOfSnow": 0, + "nightProbabilityOfSnow": 0, + "dayProbabilityOfHeavySnow": 0, + "nightProbabilityOfHeavySnow": 0, + "dayProbabilityOfRain": 49, + "nightProbabilityOfRain": 54, + "dayProbabilityOfHeavyRain": 26, + "nightProbabilityOfHeavyRain": 32, + "dayProbabilityOfHail": 1, + "nightProbabilityOfHail": 2, + "dayProbabilityOfSferics": 1, + "nightProbabilityOfSferics": 2 + }, + { + "time": "2026-02-11T00:00Z", + "midday10MWindSpeed": 4.2, + "midnight10MWindSpeed": 3.4, + "midday10MWindDirection": 228, + "midnight10MWindDirection": 241, + "midday10MWindGust": 9.23, + "midnight10MWindGust": 6.88, + "middayVisibility": 20709, + "midnightVisibility": 18608, + "middayRelativeHumidity": 82.88, + "midnightRelativeHumidity": 89.7, + "middayMslp": 98098, + "midnightMslp": 97870, + "maxUvIndex": 1, + "daySignificantWeatherCode": 12, + "nightSignificantWeatherCode": 12, + "dayMaxScreenTemperature": 11.71, + "nightMinScreenTemperature": 7.6, + "dayUpperBoundMaxTemp": 13.23, + "nightUpperBoundMinTemp": 9.77, + "dayLowerBoundMaxTemp": 7.85, + "nightLowerBoundMinTemp": 4.71, + "dayMaxFeelsLikeTemp": 9.43, + "nightMinFeelsLikeTemp": 5.5, + "dayUpperBoundMaxFeelsLikeTemp": 11.39, + "nightUpperBoundMinFeelsLikeTemp": 7.6, + "dayLowerBoundMaxFeelsLikeTemp": 8.0, + "nightLowerBoundMinFeelsLikeTemp": 4.33, + "dayProbabilityOfPrecipitation": 50, + "nightProbabilityOfPrecipitation": 46, + "dayProbabilityOfSnow": 0, + "nightProbabilityOfSnow": 0, + "dayProbabilityOfHeavySnow": 0, + "nightProbabilityOfHeavySnow": 0, + "dayProbabilityOfRain": 50, + "nightProbabilityOfRain": 46, + "dayProbabilityOfHeavyRain": 28, + "nightProbabilityOfHeavyRain": 25, + "dayProbabilityOfHail": 2, + "nightProbabilityOfHail": 1, + "dayProbabilityOfSferics": 5, + "nightProbabilityOfSferics": 4 + }, + { + "time": "2026-02-12T00:00Z", + "midday10MWindSpeed": 3.99, + "midnight10MWindSpeed": 3.62, + "midday10MWindDirection": 297, + "midnight10MWindDirection": 321, + "midday10MWindGust": 8.71, + "midnight10MWindGust": 7.52, + "middayVisibility": 21894, + "midnightVisibility": 24612, + "middayRelativeHumidity": 80.41, + "midnightRelativeHumidity": 83.6, + "middayMslp": 98255, + "midnightMslp": 98981, + "maxUvIndex": 1, + "daySignificantWeatherCode": 8, + "nightSignificantWeatherCode": 7, + "dayMaxScreenTemperature": 9.92, + "nightMinScreenTemperature": 3.15, + "dayUpperBoundMaxTemp": 12.14, + "nightUpperBoundMinTemp": 9.05, + "dayLowerBoundMaxTemp": 5.26, + "nightLowerBoundMinTemp": 0.41, + "dayMaxFeelsLikeTemp": 6.69, + "nightMinFeelsLikeTemp": -0.03, + "dayUpperBoundMaxFeelsLikeTemp": 10.16, + "nightUpperBoundMinFeelsLikeTemp": 7.3, + "dayLowerBoundMaxFeelsLikeTemp": 4.45, + "nightLowerBoundMinFeelsLikeTemp": -3.64, + "dayProbabilityOfPrecipitation": 21, + "nightProbabilityOfPrecipitation": 22, + "dayProbabilityOfSnow": 0, + "nightProbabilityOfSnow": 2, + "dayProbabilityOfHeavySnow": 0, + "nightProbabilityOfHeavySnow": 1, + "dayProbabilityOfRain": 21, + "nightProbabilityOfRain": 22, + "dayProbabilityOfHeavyRain": 9, + "nightProbabilityOfHeavyRain": 10, + "dayProbabilityOfHail": 1, + "nightProbabilityOfHail": 1, + "dayProbabilityOfSferics": 2, + "nightProbabilityOfSferics": 2 + }, + { + "time": "2026-02-13T00:00Z", + "midday10MWindSpeed": 4.14, + "midnight10MWindSpeed": 2.83, + "midday10MWindDirection": 322, + "midnight10MWindDirection": 307, + "midday10MWindGust": 9.4, + "midnight10MWindGust": 5.92, + "middayVisibility": 34312, + "midnightVisibility": 34597, + "middayRelativeHumidity": 66.26, + "midnightRelativeHumidity": 77.93, + "middayMslp": 99718, + "midnightMslp": 100243, + "maxUvIndex": 1, + "daySignificantWeatherCode": 1, + "nightSignificantWeatherCode": 0, + "dayMaxScreenTemperature": 6.79, + "nightMinScreenTemperature": 0.85, + "dayUpperBoundMaxTemp": 11.07, + "nightUpperBoundMinTemp": 7.3, + "dayLowerBoundMaxTemp": 2.84, + "nightLowerBoundMinTemp": -1.75, + "dayMaxFeelsLikeTemp": 2.21, + "nightMinFeelsLikeTemp": -2.05, + "dayUpperBoundMaxFeelsLikeTemp": 9.57, + "nightUpperBoundMinFeelsLikeTemp": 6.72, + "dayLowerBoundMaxFeelsLikeTemp": -0.29, + "nightLowerBoundMinFeelsLikeTemp": -3.77, + "dayProbabilityOfPrecipitation": 11, + "nightProbabilityOfPrecipitation": 6, + "dayProbabilityOfSnow": 2, + "nightProbabilityOfSnow": 1, + "dayProbabilityOfHeavySnow": 1, + "nightProbabilityOfHeavySnow": 0, + "dayProbabilityOfRain": 9, + "nightProbabilityOfRain": 6, + "dayProbabilityOfHeavyRain": 4, + "nightProbabilityOfHeavyRain": 3, + "dayProbabilityOfHail": 1, + "nightProbabilityOfHail": 0, + "dayProbabilityOfSferics": 1, + "nightProbabilityOfSferics": 0 + } + ] + } + } + ], + "parameters": [ + { + "daySignificantWeatherCode": { "type": "Parameter", "description": "Day Significant Weather Code", "unit": { "label": "dimensionless", "symbol": { "value": "https://datahub.metoffice.gov.uk/", "type": "1" } } }, + "midnightRelativeHumidity": { "type": "Parameter", "description": "Relative Humidity at Local Midnight", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "nightProbabilityOfHeavyRain": { "type": "Parameter", "description": "Probability of Heavy Rain During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "midnight10MWindSpeed": { "type": "Parameter", "description": "10m Wind Speed at Local Midnight", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } }, + "nightUpperBoundMinFeelsLikeTemp": { + "type": "Parameter", + "description": "Upper Bound on Night Minimum Feels Like Air Temperature", + "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } + }, + "nightUpperBoundMinTemp": { "type": "Parameter", "description": "Upper Bound on Night Minimum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "midnightVisibility": { "type": "Parameter", "description": "Visibility at Local Midnight", "unit": { "label": "metres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m" } } }, + "dayUpperBoundMaxFeelsLikeTemp": { + "type": "Parameter", + "description": "Upper Bound on Day Maximum Feels Like Air Temperature", + "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } + }, + "nightProbabilityOfRain": { "type": "Parameter", "description": "Probability of Rain During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "midday10MWindDirection": { "type": "Parameter", "description": "10m Wind Direction at Local Midday", "unit": { "label": "degrees", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "deg" } } }, + "nightLowerBoundMinFeelsLikeTemp": { + "type": "Parameter", + "description": "Lower Bound on Night Minimum Feels Like Air Temperature", + "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } + }, + "nightProbabilityOfHail": { "type": "Parameter", "description": "Probability of Hail During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "middayMslp": { "type": "Parameter", "description": "Mean Sea Level Pressure at Local Midday", "unit": { "label": "pascals", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Pa" } } }, + "dayProbabilityOfHeavySnow": { "type": "Parameter", "description": "Probability of Heavy Snow During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "nightProbabilityOfPrecipitation": { "type": "Parameter", "description": "Probability of Precipitation During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "dayProbabilityOfHail": { "type": "Parameter", "description": "Probability of Hail During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "dayProbabilityOfRain": { "type": "Parameter", "description": "Probability of Rain During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "midday10MWindSpeed": { "type": "Parameter", "description": "10m Wind Speed at Local Midday", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } }, + "midday10MWindGust": { "type": "Parameter", "description": "10m Wind Gust Speed at Local Midday", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } }, + "middayVisibility": { "type": "Parameter", "description": "Visibility at Local Midday", "unit": { "label": "metres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m" } } }, + "midnight10MWindGust": { "type": "Parameter", "description": "10m Wind Gust Speed at Local Midnight", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } }, + "midnightMslp": { "type": "Parameter", "description": "Mean Sea Level Pressure at Local Midnight", "unit": { "label": "pascals", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Pa" } } }, + "dayProbabilityOfSferics": { "type": "Parameter", "description": "Probability of Sferics During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "nightSignificantWeatherCode": { "type": "Parameter", "description": "Night Significant Weather Code", "unit": { "label": "dimensionless", "symbol": { "value": "https://datahub.metoffice.gov.uk/", "type": "1" } } }, + "dayProbabilityOfPrecipitation": { "type": "Parameter", "description": "Probability of Precipitation During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "dayProbabilityOfHeavyRain": { "type": "Parameter", "description": "Probability of Heavy Rain During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "dayMaxScreenTemperature": { "type": "Parameter", "description": "Day Maximum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "nightMinScreenTemperature": { "type": "Parameter", "description": "Night Minimum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "midnight10MWindDirection": { "type": "Parameter", "description": "10m Wind Direction at Local Midnight", "unit": { "label": "degrees", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "deg" } } }, + "maxUvIndex": { "type": "Parameter", "description": "Day Maximum UV Index", "unit": { "label": "dimensionless", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "1" } } }, + "dayProbabilityOfSnow": { "type": "Parameter", "description": "Probability of Snow During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "nightProbabilityOfSnow": { "type": "Parameter", "description": "Probability of Snow During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "dayLowerBoundMaxTemp": { "type": "Parameter", "description": "Lower Bound on Day Maximum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "nightProbabilityOfHeavySnow": { "type": "Parameter", "description": "Probability of Heavy Snow During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "dayLowerBoundMaxFeelsLikeTemp": { + "type": "Parameter", + "description": "Lower Bound on Day Maximum Feels Like Air Temperature", + "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } + }, + "dayUpperBoundMaxTemp": { "type": "Parameter", "description": "Upper Bound on Day Maximum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "dayMaxFeelsLikeTemp": { "type": "Parameter", "description": "Day Maximum Feels Like Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "middayRelativeHumidity": { "type": "Parameter", "description": "Relative Humidity at Local Midday", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }, + "nightLowerBoundMinTemp": { "type": "Parameter", "description": "Lower Bound on Night Minimum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "nightMinFeelsLikeTemp": { "type": "Parameter", "description": "Night Minimum Feels Like Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } }, + "nightProbabilityOfSferics": { "type": "Parameter", "description": "Probability of Sferics During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } } + } + ] +} diff --git a/tests/mocks/weather_weatherbit.json b/tests/mocks/weather_weatherbit.json new file mode 100644 index 0000000000..bc8dfb530e --- /dev/null +++ b/tests/mocks/weather_weatherbit.json @@ -0,0 +1,45 @@ +{ + "count": 1, + "data": [ + { + "app_temp": -0.6, + "aqi": 44, + "city_name": "New York City", + "clouds": 100, + "country_code": "US", + "datetime": "2026-02-06:21", + "dewpt": -9, + "dhi": 62, + "dni": 555, + "elev_angle": 12.55, + "ghi": 175, + "gust": 3.1, + "h_angle": 60, + "lat": 40.7128, + "lon": -74.006, + "ob_time": "2026-02-06 21:25", + "pod": "d", + "precip": 0, + "pres": 1004, + "rh": 47, + "slp": 1004, + "snow": 0, + "solar_rad": 35, + "sources": ["KJRB", "radar", "satellite"], + "state_code": "NY", + "station": "KJRB", + "sunrise": "11:59", + "sunset": "22:21", + "temp": 1, + "timezone": "America/New_York", + "ts": 1770413100, + "uv": 0, + "vis": 16, + "weather": { "code": 804, "description": "Overcast clouds", "icon": "c04d" }, + "wind_cdir": "SSW", + "wind_cdir_full": "south-southwest", + "wind_dir": 210, + "wind_spd": 1.5 + } + ] +} diff --git a/tests/mocks/weather_weatherbit_forecast.json b/tests/mocks/weather_weatherbit_forecast.json new file mode 100644 index 0000000000..b5239b8436 --- /dev/null +++ b/tests/mocks/weather_weatherbit_forecast.json @@ -0,0 +1,290 @@ +{ + "city_name": "New York City", + "country_code": "US", + "data": [ + { + "app_max_temp": -2.7, + "app_min_temp": -9.8, + "clouds": 76, + "clouds_hi": 8, + "clouds_low": 40, + "clouds_mid": 90, + "datetime": "2026-02-06", + "dewpt": -7.6, + "high_temp": 0.8, + "low_temp": -6.5, + "max_dhi": null, + "max_temp": 0.5, + "min_temp": -6.3, + "moon_phase": 0.68, + "moon_phase_lunation": 0.65, + "moonrise_ts": 1770432076, + "moonset_ts": 1770388275, + "ozone": 405, + "pop": 50, + "precip": 0.25, + "pres": 1005, + "rh": 66, + "slp": 1008, + "snow": 3.75, + "snow_depth": 216.91895, + "sunrise_ts": 1770379197, + "sunset_ts": 1770416511, + "temp": -2, + "ts": 1770372060, + "uv": 1, + "valid_date": "2026-02-06", + "vis": 21.7, + "weather": { "code": 600, "description": "Light snow", "icon": "s01d" }, + "wind_cdir": "SSW", + "wind_cdir_full": "south-southwest", + "wind_dir": 192, + "wind_gust_spd": 3.4, + "wind_spd": 2.4 + }, + { + "app_max_temp": -4.9, + "app_min_temp": -22.5, + "clouds": 76, + "clouds_hi": 0, + "clouds_low": 87, + "clouds_mid": 57, + "datetime": "2026-02-07", + "dewpt": -13.7, + "high_temp": -5.9, + "low_temp": -13.9, + "max_dhi": null, + "max_temp": -0.2, + "min_temp": -12.2, + "moon_phase": 0.59, + "moon_phase_lunation": 0.68, + "moonrise_ts": 1770522306, + "moonset_ts": 1770476147, + "ozone": 452, + "pop": 0, + "precip": 0, + "pres": 1006, + "rh": 61, + "slp": 1009, + "snow": 0, + "snow_depth": 201.76189, + "sunrise_ts": 1770465530, + "sunset_ts": 1770502984, + "temp": -7.5, + "ts": 1770440460, + "uv": 1, + "valid_date": "2026-02-07", + "vis": 17.8, + "weather": { "code": 804, "description": "Overcast clouds", "icon": "c04d" }, + "wind_cdir": "NW", + "wind_cdir_full": "northwest", + "wind_dir": 307, + "wind_gust_spd": 13.2, + "wind_spd": 9.6 + }, + { + "app_max_temp": -16.5, + "app_min_temp": -23.8, + "clouds": 9, + "clouds_hi": 0, + "clouds_low": 17, + "clouds_mid": 0, + "datetime": "2026-02-08", + "dewpt": -18.1, + "high_temp": -7.5, + "low_temp": -12.4, + "max_dhi": null, + "max_temp": -7.5, + "min_temp": -13.9, + "moon_phase": 0.49, + "moon_phase_lunation": 0.71, + "moonrise_ts": 1770612516, + "moonset_ts": 1770564257, + "ozone": 453, + "pop": 0, + "precip": 0, + "pres": 1021, + "rh": 54, + "slp": 1024, + "snow": 0, + "snow_depth": 190.89763, + "sunrise_ts": 1770551862, + "sunset_ts": 1770589457, + "temp": -10.7, + "ts": 1770526860, + "uv": 3, + "valid_date": "2026-02-08", + "vis": 24, + "weather": { "code": 801, "description": "Few clouds", "icon": "c02d" }, + "wind_cdir": "NW", + "wind_cdir_full": "northwest", + "wind_dir": 321, + "wind_gust_spd": 11.3, + "wind_spd": 8.2 + }, + { + "app_max_temp": -7.5, + "app_min_temp": -18.4, + "clouds": 38, + "clouds_hi": 23, + "clouds_low": 36, + "clouds_mid": 53, + "datetime": "2026-02-09", + "dewpt": -13.7, + "high_temp": -1.6, + "low_temp": -7.4, + "max_dhi": null, + "max_temp": -1.6, + "min_temp": -12.4, + "moon_phase": 0.4, + "moon_phase_lunation": 0.75, + "moonrise_ts": 1770616323, + "moonset_ts": 1770652706, + "ozone": 379, + "pop": 0, + "precip": 0, + "pres": 1021, + "rh": 59, + "slp": 1024, + "snow": 0, + "snow_depth": 174.14348, + "sunrise_ts": 1770638193, + "sunset_ts": 1770675930, + "temp": -7, + "ts": 1770613260, + "uv": 2, + "valid_date": "2026-02-09", + "vis": 23.5, + "weather": { "code": 802, "description": "Scattered clouds", "icon": "c02d" }, + "wind_cdir": "WNW", + "wind_cdir_full": "west-northwest", + "wind_dir": 301, + "wind_gust_spd": 5.9, + "wind_spd": 4.3 + }, + { + "app_max_temp": -3.1, + "app_min_temp": -11.5, + "clouds": 36, + "clouds_hi": 45, + "clouds_low": 39, + "clouds_mid": 25, + "datetime": "2026-02-10", + "dewpt": -8.5, + "high_temp": 1.5, + "low_temp": -3, + "max_dhi": null, + "max_temp": 1.5, + "min_temp": -7.4, + "moon_phase": 0.3, + "moon_phase_lunation": 0.78, + "moonrise_ts": 1770706492, + "moonset_ts": 1770741592, + "ozone": 348, + "pop": 0, + "precip": 0, + "pres": 1018, + "rh": 65, + "slp": 1021, + "snow": 0, + "snow_depth": 150.55084, + "sunrise_ts": 1770724522, + "sunset_ts": 1770762403, + "temp": -2.9, + "ts": 1770699660, + "uv": 3, + "valid_date": "2026-02-10", + "vis": 23, + "weather": { "code": 802, "description": "Scattered clouds", "icon": "c02d" }, + "wind_cdir": "WNW", + "wind_cdir_full": "west-northwest", + "wind_dir": 290, + "wind_gust_spd": 3.6, + "wind_spd": 3.5 + }, + { + "app_max_temp": -1.4, + "app_min_temp": -5.8, + "clouds": 73, + "clouds_hi": 97, + "clouds_low": 55, + "clouds_mid": 81, + "datetime": "2026-02-11", + "dewpt": -4.2, + "high_temp": 3.8, + "low_temp": -3.4, + "max_dhi": null, + "max_temp": 3.8, + "min_temp": -3, + "moon_phase": 0.22, + "moon_phase_lunation": 0.81, + "moonrise_ts": 1770796533, + "moonset_ts": 1770830974, + "ozone": 327, + "pop": 80, + "precip": 6.33, + "pres": 1012, + "rh": 72, + "slp": 1014, + "snow": 8.82, + "snow_depth": 103.88888, + "sunrise_ts": 1770810850, + "sunset_ts": 1770848875, + "temp": 0.3, + "ts": 1770786060, + "uv": 2, + "valid_date": "2026-02-11", + "vis": 16.7, + "weather": { "code": 500, "description": "Light rain", "icon": "r01d" }, + "wind_cdir": "WNW", + "wind_cdir_full": "west-northwest", + "wind_dir": 302, + "wind_gust_spd": 4.2, + "wind_spd": 4.2 + }, + { + "app_max_temp": -5.3, + "app_min_temp": -10.9, + "clouds": 40, + "clouds_hi": 0, + "clouds_low": 40, + "clouds_mid": 0, + "datetime": "2026-02-12", + "dewpt": -5.2, + "high_temp": 0, + "low_temp": -6.3, + "max_dhi": null, + "max_temp": 0, + "min_temp": -4.6, + "moon_phase": 0.14, + "moon_phase_lunation": 0.85, + "moonrise_ts": 1770886312, + "moonset_ts": 1770920833, + "ozone": 378, + "pop": 20, + "precip": 0.125, + "pres": 1010, + "rh": 79, + "slp": 1013, + "snow": 0.625, + "snow_depth": 49.526215, + "sunrise_ts": 1770897177, + "sunset_ts": 1770935347, + "temp": -2, + "ts": 1770872460, + "uv": 4, + "valid_date": "2026-02-12", + "vis": 24, + "weather": { "code": 610, "description": "Mix snow/rain", "icon": "s04d" }, + "wind_cdir": "WNW", + "wind_cdir_full": "west-northwest", + "wind_dir": 299, + "wind_gust_spd": 12, + "wind_spd": 5.3 + } + ], + "lat": 40.7128, + "lon": -74.006, + "state_code": "NY", + "timezone": "America/New_York" +} diff --git a/tests/mocks/weather_weatherbit_hourly.json b/tests/mocks/weather_weatherbit_hourly.json new file mode 100644 index 0000000000..d277750081 --- /dev/null +++ b/tests/mocks/weather_weatherbit_hourly.json @@ -0,0 +1 @@ +{ "error": "Your API key does not allow access to this endpoint." } diff --git a/tests/mocks/weather_weatherflow.json b/tests/mocks/weather_weatherflow.json new file mode 100644 index 0000000000..38e4fbdbed --- /dev/null +++ b/tests/mocks/weather_weatherflow.json @@ -0,0 +1,4875 @@ +{ + "current_conditions": { + "air_density": 1.22, + "air_temperature": 16.0, + "brightness": 22546, + "conditions": "Clear", + "delta_t": 8.0, + "dew_point": -2.0, + "feels_like": 16.0, + "icon": "clear-day", + "is_precip_local_day_rain_check": true, + "is_precip_local_yesterday_rain_check": true, + "lightning_strike_count_last_1hr": 0, + "lightning_strike_count_last_3hr": 0, + "lightning_strike_last_distance": 25, + "lightning_strike_last_distance_msg": "23 - 27 km", + "lightning_strike_last_epoch": 1765159221, + "precip_accum_local_day": 0, + "precip_accum_local_yesterday": 1.75, + "precip_minutes_local_day": 0, + "precip_minutes_local_yesterday": 141, + "precip_probability": 0, + "pressure_trend": "falling", + "relative_humidity": 28, + "sea_level_pressure": 1013.6, + "solar_radiation": 188, + "station_pressure": 1013.0, + "time": 1770414299, + "uv": 1, + "wet_bulb_globe_temperature": 10.0, + "wet_bulb_temperature": 8.0, + "wind_avg": 15.0, + "wind_direction": 269, + "wind_direction_cardinal": "W", + "wind_gust": 20.0 + }, + "forecast": { + "daily": [ + { + "air_temp_high": 15.0, + "air_temp_low": 4.0, + "conditions": "Clear", + "day_num": 6, + "day_start_local": 1770354000, + "icon": "clear-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "sunrise": 1770379765, + "sunset": 1770419180 + }, + { + "air_temp_high": 14.0, + "air_temp_low": 10.0, + "conditions": "Clear", + "day_num": 7, + "day_start_local": 1770440400, + "icon": "clear-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "sunrise": 1770466123, + "sunset": 1770505628 + }, + { + "air_temp_high": 16.0, + "air_temp_low": 10.0, + "conditions": "Clear", + "day_num": 8, + "day_start_local": 1770526800, + "icon": "clear-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "sunrise": 1770552481, + "sunset": 1770592076 + }, + { + "air_temp_high": 18.0, + "air_temp_low": 9.0, + "conditions": "Clear", + "day_num": 9, + "day_start_local": 1770613200, + "icon": "clear-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "sunrise": 1770638837, + "sunset": 1770678523 + }, + { + "air_temp_high": 20.0, + "air_temp_low": 10.0, + "conditions": "Partly Cloudy", + "day_num": 10, + "day_start_local": 1770699600, + "icon": "partly-cloudy-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "sunrise": 1770725192, + "sunset": 1770764970 + }, + { + "air_temp_high": 21.0, + "air_temp_low": 13.0, + "conditions": "Partly Cloudy", + "day_num": 11, + "day_start_local": 1770786000, + "icon": "partly-cloudy-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "sunrise": 1770811546, + "sunset": 1770851417 + }, + { + "air_temp_high": 20.0, + "air_temp_low": 14.0, + "conditions": "Partly Cloudy", + "day_num": 12, + "day_start_local": 1770872400, + "icon": "partly-cloudy-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "sunrise": 1770897898, + "sunset": 1770937863 + }, + { + "air_temp_high": 20.0, + "air_temp_low": 14.0, + "conditions": "Partly Cloudy", + "day_num": 13, + "day_start_local": 1770958800, + "icon": "partly-cloudy-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "sunrise": 1770984250, + "sunset": 1771024309 + }, + { + "air_temp_high": 19.0, + "air_temp_low": 14.0, + "conditions": "Rain Possible", + "day_num": 14, + "day_start_local": 1771045200, + "icon": "possibly-rainy-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 20, + "precip_type": "rain", + "sunrise": 1771070600, + "sunset": 1771110755 + }, + { + "air_temp_high": 19.0, + "air_temp_low": 14.0, + "conditions": "Partly Cloudy", + "day_num": 15, + "day_start_local": 1771131600, + "icon": "partly-cloudy-day", + "month_num": 2, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "sunrise": 1771156949, + "sunset": 1771197200 + } + ], + "hourly": [ + { + "air_temperature": 15.0, + "conditions": "Clear", + "feels_like": 15.0, + "icon": "clear-day", + "local_day": 6, + "local_hour": 17, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 42, + "sea_level_pressure": 1013.6, + "station_pressure": 1013.2, + "time": 1770415200, + "uv": 2.0, + "wind_avg": 27.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 40.0 + }, + { + "air_temperature": 15.0, + "conditions": "Clear", + "feels_like": 15.0, + "icon": "clear-day", + "local_day": 6, + "local_hour": 18, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 45, + "sea_level_pressure": 1014.4, + "station_pressure": 1014.0, + "time": 1770418800, + "uv": 0.0, + "wind_avg": 32.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 44.0 + }, + { + "air_temperature": 14.0, + "conditions": "Clear", + "feels_like": 14.0, + "icon": "clear-night", + "local_day": 6, + "local_hour": 19, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 52, + "sea_level_pressure": 1015.0, + "station_pressure": 1014.6, + "time": 1770422400, + "uv": 0.0, + "wind_avg": 33.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 48.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-night", + "local_day": 6, + "local_hour": 20, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 61, + "sea_level_pressure": 1015.3, + "station_pressure": 1014.9, + "time": 1770426000, + "uv": 0.0, + "wind_avg": 35.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 48.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 6, + "local_hour": 21, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1015.2, + "station_pressure": 1014.8, + "time": 1770429600, + "uv": 0.0, + "wind_avg": 33.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 50.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 6, + "local_hour": 22, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 76, + "sea_level_pressure": 1015.2, + "station_pressure": 1014.8, + "time": 1770433200, + "uv": 0.0, + "wind_avg": 32.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 48.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 6, + "local_hour": 23, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1015.0, + "station_pressure": 1014.6, + "time": 1770436800, + "uv": 0.0, + "wind_avg": 30.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 47.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 0, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 88, + "sea_level_pressure": 1015.0, + "station_pressure": 1014.6, + "time": 1770440400, + "uv": 0.0, + "wind_avg": 29.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 45.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 88, + "sea_level_pressure": 1015.1, + "station_pressure": 1014.7, + "time": 1770444000, + "uv": 0.0, + "wind_avg": 27.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 44.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 2, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 86, + "sea_level_pressure": 1014.9, + "station_pressure": 1014.5, + "time": 1770447600, + "uv": 0.0, + "wind_avg": 27.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 44.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 3, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 86, + "sea_level_pressure": 1015.0, + "station_pressure": 1014.6, + "time": 1770451200, + "uv": 0.0, + "wind_avg": 26.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 44.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 4, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 85, + "sea_level_pressure": 1015.1, + "station_pressure": 1014.7, + "time": 1770454800, + "uv": 0.0, + "wind_avg": 26.0, + "wind_direction": 290, + "wind_direction_cardinal": "WNW", + "wind_gust": 42.0 + }, + { + "air_temperature": 11.0, + "conditions": "Clear", + "feels_like": 11.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 5, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1015.6, + "station_pressure": 1015.2, + "time": 1770458400, + "uv": 0.0, + "wind_avg": 24.0, + "wind_direction": 290, + "wind_direction_cardinal": "WNW", + "wind_gust": 41.0 + }, + { + "air_temperature": 11.0, + "conditions": "Clear", + "feels_like": 11.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 6, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1016.4, + "station_pressure": 1016.0, + "time": 1770462000, + "uv": 0.0, + "wind_avg": 24.0, + "wind_direction": 300, + "wind_direction_cardinal": "WNW", + "wind_gust": 39.0 + }, + { + "air_temperature": 10.0, + "conditions": "Clear", + "feels_like": 10.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1017.2, + "station_pressure": 1016.8, + "time": 1770465600, + "uv": 0.0, + "wind_avg": 24.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 39.0 + }, + { + "air_temperature": 11.0, + "conditions": "Clear", + "feels_like": 11.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 8, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 82, + "sea_level_pressure": 1018.5, + "station_pressure": 1018.1, + "time": 1770469200, + "uv": 1.0, + "wind_avg": 26.0, + "wind_direction": 320, + "wind_direction_cardinal": "NW", + "wind_gust": 39.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 9, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1019.8, + "station_pressure": 1019.4, + "time": 1770472800, + "uv": 2.0, + "wind_avg": 27.0, + "wind_direction": 330, + "wind_direction_cardinal": "NNW", + "wind_gust": 39.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 10, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 67, + "sea_level_pressure": 1020.4, + "station_pressure": 1020.0, + "time": 1770476400, + "uv": 4.0, + "wind_avg": 29.0, + "wind_direction": 340, + "wind_direction_cardinal": "NNW", + "wind_gust": 39.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 11, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 64, + "sea_level_pressure": 1020.8, + "station_pressure": 1020.4, + "time": 1770480000, + "uv": 5.0, + "wind_avg": 29.0, + "wind_direction": 340, + "wind_direction_cardinal": "NNW", + "wind_gust": 39.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 12, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 61, + "sea_level_pressure": 1020.7, + "station_pressure": 1020.3, + "time": 1770483600, + "uv": 6.0, + "wind_avg": 29.0, + "wind_direction": 350, + "wind_direction_cardinal": "N", + "wind_gust": 38.0 + }, + { + "air_temperature": 14.0, + "conditions": "Clear", + "feels_like": 14.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 13, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 59, + "sea_level_pressure": 1020.0, + "station_pressure": 1019.6, + "time": 1770487200, + "uv": 7.0, + "wind_avg": 27.0, + "wind_direction": 350, + "wind_direction_cardinal": "N", + "wind_gust": 39.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 14, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 63, + "sea_level_pressure": 1019.8, + "station_pressure": 1019.4, + "time": 1770490800, + "uv": 7.0, + "wind_avg": 27.0, + "wind_direction": 360, + "wind_direction_cardinal": "N", + "wind_gust": 38.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 15, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 61, + "sea_level_pressure": 1019.9, + "station_pressure": 1019.5, + "time": 1770494400, + "uv": 6.0, + "wind_avg": 27.0, + "wind_direction": 0, + "wind_direction_cardinal": "N", + "wind_gust": 38.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 16, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 61, + "sea_level_pressure": 1020.4, + "station_pressure": 1020.0, + "time": 1770498000, + "uv": 4.0, + "wind_avg": 27.0, + "wind_direction": 10, + "wind_direction_cardinal": "N", + "wind_gust": 36.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 17, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 63, + "sea_level_pressure": 1021.1, + "station_pressure": 1020.7, + "time": 1770501600, + "uv": 2.0, + "wind_avg": 27.0, + "wind_direction": 10, + "wind_direction_cardinal": "N", + "wind_gust": 36.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-day", + "local_day": 7, + "local_hour": 18, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 65, + "sea_level_pressure": 1021.6, + "station_pressure": 1021.2, + "time": 1770505200, + "uv": 1.0, + "wind_avg": 26.0, + "wind_direction": 10, + "wind_direction_cardinal": "N", + "wind_gust": 36.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 19, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 66, + "sea_level_pressure": 1022.3, + "station_pressure": 1021.9, + "time": 1770508800, + "uv": 0.0, + "wind_avg": 23.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 34.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 20, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1022.9, + "station_pressure": 1022.5, + "time": 1770512400, + "uv": 0.0, + "wind_avg": 23.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 32.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 21, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 65, + "sea_level_pressure": 1023.4, + "station_pressure": 1023.0, + "time": 1770516000, + "uv": 0.0, + "wind_avg": 22.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 32.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 22, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1023.7, + "station_pressure": 1023.3, + "time": 1770519600, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 31.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 7, + "local_hour": 23, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 67, + "sea_level_pressure": 1024.0, + "station_pressure": 1023.6, + "time": 1770523200, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 28.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 0, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 66, + "sea_level_pressure": 1024.1, + "station_pressure": 1023.7, + "time": 1770526800, + "uv": 0.0, + "wind_avg": 17.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 28.0 + }, + { + "air_temperature": 11.0, + "conditions": "Clear", + "feels_like": 11.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 67, + "sea_level_pressure": 1024.1, + "station_pressure": 1023.7, + "time": 1770530400, + "uv": 0.0, + "wind_avg": 16.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 26.0 + }, + { + "air_temperature": 11.0, + "conditions": "Clear", + "feels_like": 11.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 2, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 66, + "sea_level_pressure": 1024.2, + "station_pressure": 1023.8, + "time": 1770534000, + "uv": 0.0, + "wind_avg": 15.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 26.0 + }, + { + "air_temperature": 11.0, + "conditions": "Clear", + "feels_like": 11.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 3, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 67, + "sea_level_pressure": 1024.2, + "station_pressure": 1023.8, + "time": 1770537600, + "uv": 0.0, + "wind_avg": 15.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 25.0 + }, + { + "air_temperature": 10.0, + "conditions": "Clear", + "feels_like": 10.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 4, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1024.3, + "station_pressure": 1023.9, + "time": 1770541200, + "uv": 0.0, + "wind_avg": 14.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 25.0 + }, + { + "air_temperature": 10.0, + "conditions": "Clear", + "feels_like": 10.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 5, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 70, + "sea_level_pressure": 1024.7, + "station_pressure": 1024.3, + "time": 1770544800, + "uv": 0.0, + "wind_avg": 14.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 24.0 + }, + { + "air_temperature": 10.0, + "conditions": "Clear", + "feels_like": 8.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 6, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 72, + "sea_level_pressure": 1025.1, + "station_pressure": 1024.7, + "time": 1770548400, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 23.0 + }, + { + "air_temperature": 10.0, + "conditions": "Clear", + "feels_like": 8.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1025.4, + "station_pressure": 1025.0, + "time": 1770552000, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 20, + "wind_direction_cardinal": "NNE", + "wind_gust": 22.0 + }, + { + "air_temperature": 11.0, + "conditions": "Clear", + "feels_like": 11.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 8, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 74, + "sea_level_pressure": 1025.9, + "station_pressure": 1025.5, + "time": 1770555600, + "uv": 4.0, + "wind_avg": 13.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 22.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 9, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 67, + "sea_level_pressure": 1026.4, + "station_pressure": 1026.0, + "time": 1770559200, + "uv": 4.0, + "wind_avg": 14.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 23.0 + }, + { + "air_temperature": 14.0, + "conditions": "Clear", + "feels_like": 14.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 10, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 61, + "sea_level_pressure": 1026.9, + "station_pressure": 1026.5, + "time": 1770562800, + "uv": 4.0, + "wind_avg": 14.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 23.0 + }, + { + "air_temperature": 15.0, + "conditions": "Clear", + "feels_like": 15.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 11, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 62, + "sea_level_pressure": 1026.4, + "station_pressure": 1026.0, + "time": 1770566400, + "uv": 6.0, + "wind_avg": 15.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 22.0 + }, + { + "air_temperature": 15.0, + "conditions": "Clear", + "feels_like": 15.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 12, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 61, + "sea_level_pressure": 1026.0, + "station_pressure": 1025.6, + "time": 1770570000, + "uv": 6.0, + "wind_avg": 15.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 22.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 13, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 60, + "sea_level_pressure": 1025.5, + "station_pressure": 1025.1, + "time": 1770573600, + "uv": 6.0, + "wind_avg": 16.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 21.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 14, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 63, + "sea_level_pressure": 1025.3, + "station_pressure": 1024.9, + "time": 1770577200, + "uv": 5.0, + "wind_avg": 15.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 21.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 15, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 62, + "sea_level_pressure": 1025.1, + "station_pressure": 1024.7, + "time": 1770580800, + "uv": 5.0, + "wind_avg": 15.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 20.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-day", + "local_day": 8, + "local_hour": 16, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 63, + "sea_level_pressure": 1025.0, + "station_pressure": 1024.6, + "time": 1770584400, + "uv": 5.0, + "wind_avg": 14.0, + "wind_direction": 30, + "wind_direction_cardinal": "NNE", + "wind_gust": 19.0 + }, + { + "air_temperature": 15.0, + "conditions": "Clear", + "feels_like": 15.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 17, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1025.3, + "station_pressure": 1024.9, + "time": 1770588000, + "uv": 1.0, + "wind_avg": 12.0, + "wind_direction": 40, + "wind_direction_cardinal": "NE", + "wind_gust": 18.0 + }, + { + "air_temperature": 14.0, + "conditions": "Clear", + "feels_like": 14.0, + "icon": "clear-day", + "local_day": 8, + "local_hour": 18, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1025.7, + "station_pressure": 1025.3, + "time": 1770591600, + "uv": 1.0, + "wind_avg": 10.0, + "wind_direction": 40, + "wind_direction_cardinal": "NE", + "wind_gust": 16.0 + }, + { + "air_temperature": 14.0, + "conditions": "Clear", + "feels_like": 14.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 19, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 74, + "sea_level_pressure": 1026.1, + "station_pressure": 1025.7, + "time": 1770595200, + "uv": 1.0, + "wind_avg": 7.0, + "wind_direction": 40, + "wind_direction_cardinal": "NE", + "wind_gust": 14.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 20, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 78, + "sea_level_pressure": 1026.1, + "station_pressure": 1025.7, + "time": 1770598800, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 60, + "wind_direction_cardinal": "ENE", + "wind_gust": 13.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 21, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 80, + "sea_level_pressure": 1026.1, + "station_pressure": 1025.7, + "time": 1770602400, + "uv": 0.0, + "wind_avg": 6.0, + "wind_direction": 60, + "wind_direction_cardinal": "ENE", + "wind_gust": 12.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 22, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1026.2, + "station_pressure": 1025.8, + "time": 1770606000, + "uv": 0.0, + "wind_avg": 6.0, + "wind_direction": 60, + "wind_direction_cardinal": "ENE", + "wind_gust": 11.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 8, + "local_hour": 23, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 79, + "sea_level_pressure": 1026.0, + "station_pressure": 1025.6, + "time": 1770609600, + "uv": 0.0, + "wind_avg": 5.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 11.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 9, + "local_hour": 0, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 80, + "sea_level_pressure": 1025.9, + "station_pressure": 1025.5, + "time": 1770613200, + "uv": 0.0, + "wind_avg": 5.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 11.0 + }, + { + "air_temperature": 12.0, + "conditions": "Clear", + "feels_like": 12.0, + "icon": "clear-night", + "local_day": 9, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 82, + "sea_level_pressure": 1025.8, + "station_pressure": 1025.4, + "time": 1770616800, + "uv": 0.0, + "wind_avg": 4.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 11.0 + }, + { + "air_temperature": 11.0, + "conditions": "Clear", + "feels_like": 11.0, + "icon": "clear-night", + "local_day": 9, + "local_hour": 2, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 80, + "sea_level_pressure": 1025.3, + "station_pressure": 1024.9, + "time": 1770620400, + "uv": 0.0, + "wind_avg": 5.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 12.0 + }, + { + "air_temperature": 10.0, + "conditions": "Partly Cloudy", + "feels_like": 10.0, + "icon": "partly-cloudy-night", + "local_day": 9, + "local_hour": 3, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 84, + "sea_level_pressure": 1024.8, + "station_pressure": 1024.4, + "time": 1770624000, + "uv": 0.0, + "wind_avg": 5.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 12.0 + }, + { + "air_temperature": 10.0, + "conditions": "Partly Cloudy", + "feels_like": 9.0, + "icon": "partly-cloudy-night", + "local_day": 9, + "local_hour": 4, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 87, + "sea_level_pressure": 1024.3, + "station_pressure": 1023.9, + "time": 1770627600, + "uv": 0.0, + "wind_avg": 6.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 13.0 + }, + { + "air_temperature": 9.0, + "conditions": "Partly Cloudy", + "feels_like": 9.0, + "icon": "partly-cloudy-night", + "local_day": 9, + "local_hour": 5, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 90, + "sea_level_pressure": 1024.7, + "station_pressure": 1024.3, + "time": 1770631200, + "uv": 0.0, + "wind_avg": 6.0, + "wind_direction": 290, + "wind_direction_cardinal": "WNW", + "wind_gust": 14.0 + }, + { + "air_temperature": 9.0, + "conditions": "Partly Cloudy", + "feels_like": 8.0, + "icon": "partly-cloudy-night", + "local_day": 9, + "local_hour": 6, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 92, + "sea_level_pressure": 1025.0, + "station_pressure": 1024.6, + "time": 1770634800, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 290, + "wind_direction_cardinal": "WNW", + "wind_gust": 14.0 + }, + { + "air_temperature": 10.0, + "conditions": "Partly Cloudy", + "feels_like": 9.0, + "icon": "partly-cloudy-night", + "local_day": 9, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 89, + "sea_level_pressure": 1025.3, + "station_pressure": 1024.9, + "time": 1770638400, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 290, + "wind_direction_cardinal": "WNW", + "wind_gust": 15.0 + }, + { + "air_temperature": 11.0, + "conditions": "Partly Cloudy", + "feels_like": 11.0, + "icon": "partly-cloudy-day", + "local_day": 9, + "local_hour": 8, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 90, + "sea_level_pressure": 1025.8, + "station_pressure": 1025.4, + "time": 1770642000, + "uv": 2.0, + "wind_avg": 8.0, + "wind_direction": 300, + "wind_direction_cardinal": "WNW", + "wind_gust": 15.0 + }, + { + "air_temperature": 13.0, + "conditions": "Partly Cloudy", + "feels_like": 13.0, + "icon": "partly-cloudy-day", + "local_day": 9, + "local_hour": 9, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 79, + "sea_level_pressure": 1026.3, + "station_pressure": 1025.9, + "time": 1770645600, + "uv": 2.0, + "wind_avg": 8.0, + "wind_direction": 300, + "wind_direction_cardinal": "WNW", + "wind_gust": 16.0 + }, + { + "air_temperature": 15.0, + "conditions": "Clear", + "feels_like": 15.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 10, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1026.8, + "station_pressure": 1026.4, + "time": 1770649200, + "uv": 2.0, + "wind_avg": 9.0, + "wind_direction": 300, + "wind_direction_cardinal": "WNW", + "wind_gust": 16.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 11, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 61, + "sea_level_pressure": 1026.2, + "station_pressure": 1025.8, + "time": 1770652800, + "uv": 4.0, + "wind_avg": 10.0, + "wind_direction": 330, + "wind_direction_cardinal": "NNW", + "wind_gust": 16.0 + }, + { + "air_temperature": 17.0, + "conditions": "Clear", + "feels_like": 17.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 12, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 59, + "sea_level_pressure": 1025.5, + "station_pressure": 1025.1, + "time": 1770656400, + "uv": 4.0, + "wind_avg": 10.0, + "wind_direction": 330, + "wind_direction_cardinal": "NNW", + "wind_gust": 17.0 + }, + { + "air_temperature": 17.0, + "conditions": "Clear", + "feels_like": 17.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 13, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 57, + "sea_level_pressure": 1024.8, + "station_pressure": 1024.4, + "time": 1770660000, + "uv": 4.0, + "wind_avg": 12.0, + "wind_direction": 330, + "wind_direction_cardinal": "NNW", + "wind_gust": 17.0 + }, + { + "air_temperature": 18.0, + "conditions": "Clear", + "feels_like": 18.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 14, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 57, + "sea_level_pressure": 1024.1, + "station_pressure": 1023.7, + "time": 1770663600, + "uv": 5.0, + "wind_avg": 12.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 18.0 + }, + { + "air_temperature": 18.0, + "conditions": "Clear", + "feels_like": 18.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 15, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 56, + "sea_level_pressure": 1023.4, + "station_pressure": 1023.0, + "time": 1770667200, + "uv": 5.0, + "wind_avg": 12.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 18.0 + }, + { + "air_temperature": 18.0, + "conditions": "Clear", + "feels_like": 18.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 16, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 56, + "sea_level_pressure": 1022.7, + "station_pressure": 1022.3, + "time": 1770670800, + "uv": 5.0, + "wind_avg": 12.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 19.0 + }, + { + "air_temperature": 17.0, + "conditions": "Clear", + "feels_like": 17.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 17, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 66, + "sea_level_pressure": 1022.9, + "station_pressure": 1022.5, + "time": 1770674400, + "uv": 3.0, + "wind_avg": 11.0, + "wind_direction": 160, + "wind_direction_cardinal": "SSE", + "wind_gust": 18.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-day", + "local_day": 9, + "local_hour": 18, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 69, + "sea_level_pressure": 1023.1, + "station_pressure": 1022.7, + "time": 1770678000, + "uv": 3.0, + "wind_avg": 10.0, + "wind_direction": 160, + "wind_direction_cardinal": "SSE", + "wind_gust": 16.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-night", + "local_day": 9, + "local_hour": 19, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1023.3, + "station_pressure": 1022.9, + "time": 1770681600, + "uv": 3.0, + "wind_avg": 9.0, + "wind_direction": 160, + "wind_direction_cardinal": "SSE", + "wind_gust": 15.0 + }, + { + "air_temperature": 15.0, + "conditions": "Clear", + "feels_like": 15.0, + "icon": "clear-night", + "local_day": 9, + "local_hour": 20, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 74, + "sea_level_pressure": 1023.4, + "station_pressure": 1023.0, + "time": 1770685200, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 240, + "wind_direction_cardinal": "WSW", + "wind_gust": 16.0 + }, + { + "air_temperature": 15.0, + "conditions": "Clear", + "feels_like": 15.0, + "icon": "clear-night", + "local_day": 9, + "local_hour": 21, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 76, + "sea_level_pressure": 1023.5, + "station_pressure": 1023.1, + "time": 1770688800, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 240, + "wind_direction_cardinal": "WSW", + "wind_gust": 17.0 + }, + { + "air_temperature": 14.0, + "conditions": "Clear", + "feels_like": 14.0, + "icon": "clear-night", + "local_day": 9, + "local_hour": 22, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 79, + "sea_level_pressure": 1023.6, + "station_pressure": 1023.2, + "time": 1770692400, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 240, + "wind_direction_cardinal": "WSW", + "wind_gust": 17.0 + }, + { + "air_temperature": 14.0, + "conditions": "Clear", + "feels_like": 14.0, + "icon": "clear-night", + "local_day": 9, + "local_hour": 23, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1023.4, + "station_pressure": 1023.0, + "time": 1770696000, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 18.0 + }, + { + "air_temperature": 13.0, + "conditions": "Clear", + "feels_like": 13.0, + "icon": "clear-night", + "local_day": 10, + "local_hour": 0, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1023.2, + "station_pressure": 1022.8, + "time": 1770699600, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 18.0 + }, + { + "air_temperature": 13.0, + "conditions": "Partly Cloudy", + "feels_like": 13.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 76, + "sea_level_pressure": 1023.0, + "station_pressure": 1022.6, + "time": 1770703200, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 19.0 + }, + { + "air_temperature": 12.0, + "conditions": "Partly Cloudy", + "feels_like": 12.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 2, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 74, + "sea_level_pressure": 1022.9, + "station_pressure": 1022.5, + "time": 1770706800, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 18.0 + }, + { + "air_temperature": 12.0, + "conditions": "Partly Cloudy", + "feels_like": 12.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 3, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 76, + "sea_level_pressure": 1022.9, + "station_pressure": 1022.5, + "time": 1770710400, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 17.0 + }, + { + "air_temperature": 11.0, + "conditions": "Partly Cloudy", + "feels_like": 11.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 4, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 79, + "sea_level_pressure": 1022.8, + "station_pressure": 1022.4, + "time": 1770714000, + "uv": 0.0, + "wind_avg": 9.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 16.0 + }, + { + "air_temperature": 11.0, + "conditions": "Partly Cloudy", + "feels_like": 11.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 5, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 82, + "sea_level_pressure": 1023.2, + "station_pressure": 1022.8, + "time": 1770717600, + "uv": 0.0, + "wind_avg": 8.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 15.0 + }, + { + "air_temperature": 10.0, + "conditions": "Partly Cloudy", + "feels_like": 10.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 6, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 85, + "sea_level_pressure": 1023.5, + "station_pressure": 1023.1, + "time": 1770721200, + "uv": 0.0, + "wind_avg": 8.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 15.0 + }, + { + "air_temperature": 11.0, + "conditions": "Partly Cloudy", + "feels_like": 11.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1023.9, + "station_pressure": 1023.5, + "time": 1770724800, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 15.0 + }, + { + "air_temperature": 12.0, + "conditions": "Partly Cloudy", + "feels_like": 12.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 8, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 89, + "sea_level_pressure": 1024.2, + "station_pressure": 1023.8, + "time": 1770728400, + "uv": 2.0, + "wind_avg": 7.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 15.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 9, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 79, + "sea_level_pressure": 1024.5, + "station_pressure": 1024.1, + "time": 1770732000, + "uv": 2.0, + "wind_avg": 7.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 15.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 10, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1024.8, + "station_pressure": 1024.4, + "time": 1770735600, + "uv": 2.0, + "wind_avg": 7.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 15.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 11, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 67, + "sea_level_pressure": 1024.1, + "station_pressure": 1023.7, + "time": 1770739200, + "uv": 4.0, + "wind_avg": 8.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 14.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 12, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 63, + "sea_level_pressure": 1023.3, + "station_pressure": 1022.9, + "time": 1770742800, + "uv": 4.0, + "wind_avg": 8.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 14.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 13, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 60, + "sea_level_pressure": 1022.5, + "station_pressure": 1022.1, + "time": 1770746400, + "uv": 4.0, + "wind_avg": 9.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 14.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 14, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 61, + "sea_level_pressure": 1021.9, + "station_pressure": 1021.5, + "time": 1770750000, + "uv": 5.0, + "wind_avg": 9.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 14.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 15, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 59, + "sea_level_pressure": 1021.3, + "station_pressure": 1020.9, + "time": 1770753600, + "uv": 5.0, + "wind_avg": 10.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 15.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 16, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 59, + "sea_level_pressure": 1020.6, + "station_pressure": 1020.2, + "time": 1770757200, + "uv": 5.0, + "wind_avg": 10.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 15.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 17, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1021.1, + "station_pressure": 1020.7, + "time": 1770760800, + "uv": 3.0, + "wind_avg": 9.0, + "wind_direction": 140, + "wind_direction_cardinal": "SE", + "wind_gust": 15.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 10, + "local_hour": 18, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1021.5, + "station_pressure": 1021.1, + "time": 1770764400, + "uv": 3.0, + "wind_avg": 8.0, + "wind_direction": 140, + "wind_direction_cardinal": "SE", + "wind_gust": 14.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 19, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 77, + "sea_level_pressure": 1022.0, + "station_pressure": 1021.6, + "time": 1770768000, + "uv": 3.0, + "wind_avg": 7.0, + "wind_direction": 140, + "wind_direction_cardinal": "SE", + "wind_gust": 14.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 20, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 78, + "sea_level_pressure": 1022.2, + "station_pressure": 1021.8, + "time": 1770771600, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 200, + "wind_direction_cardinal": "SSW", + "wind_gust": 14.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 10, + "local_hour": 21, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 79, + "sea_level_pressure": 1022.4, + "station_pressure": 1022.0, + "time": 1770775200, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 200, + "wind_direction_cardinal": "SSW", + "wind_gust": 14.0 + }, + { + "air_temperature": 16.0, + "conditions": "Cloudy", + "feels_like": 16.0, + "icon": "cloudy", + "local_day": 10, + "local_hour": 22, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 80, + "sea_level_pressure": 1022.6, + "station_pressure": 1022.2, + "time": 1770778800, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 200, + "wind_direction_cardinal": "SSW", + "wind_gust": 15.0 + }, + { + "air_temperature": 16.0, + "conditions": "Cloudy", + "feels_like": 16.0, + "icon": "cloudy", + "local_day": 10, + "local_hour": 23, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 78, + "sea_level_pressure": 1022.4, + "station_pressure": 1022.0, + "time": 1770782400, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 15.0 + }, + { + "air_temperature": 15.0, + "conditions": "Cloudy", + "feels_like": 15.0, + "icon": "cloudy", + "local_day": 11, + "local_hour": 0, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 81, + "sea_level_pressure": 1022.3, + "station_pressure": 1021.9, + "time": 1770786000, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 15.0 + }, + { + "air_temperature": 15.0, + "conditions": "Cloudy", + "feels_like": 15.0, + "icon": "cloudy", + "local_day": 11, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1022.1, + "station_pressure": 1021.7, + "time": 1770789600, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 16.0 + }, + { + "air_temperature": 14.0, + "conditions": "Cloudy", + "feels_like": 14.0, + "icon": "cloudy", + "local_day": 11, + "local_hour": 2, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 85, + "sea_level_pressure": 1021.8, + "station_pressure": 1021.4, + "time": 1770793200, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 16.0 + }, + { + "air_temperature": 14.0, + "conditions": "Cloudy", + "feels_like": 14.0, + "icon": "cloudy", + "local_day": 11, + "local_hour": 3, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 87, + "sea_level_pressure": 1021.6, + "station_pressure": 1021.2, + "time": 1770796800, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 15.0 + }, + { + "air_temperature": 14.0, + "conditions": "Cloudy", + "feels_like": 14.0, + "icon": "cloudy", + "local_day": 11, + "local_hour": 4, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 89, + "sea_level_pressure": 1021.4, + "station_pressure": 1021.0, + "time": 1770800400, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 15.0 + }, + { + "air_temperature": 13.0, + "conditions": "Partly Cloudy", + "feels_like": 13.0, + "icon": "partly-cloudy-night", + "local_day": 11, + "local_hour": 5, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 91, + "sea_level_pressure": 1021.4, + "station_pressure": 1021.0, + "time": 1770804000, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 16.0 + }, + { + "air_temperature": 13.0, + "conditions": "Partly Cloudy", + "feels_like": 13.0, + "icon": "partly-cloudy-night", + "local_day": 11, + "local_hour": 6, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 92, + "sea_level_pressure": 1021.5, + "station_pressure": 1021.1, + "time": 1770807600, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 16.0 + }, + { + "air_temperature": 13.0, + "conditions": "Partly Cloudy", + "feels_like": 13.0, + "icon": "partly-cloudy-night", + "local_day": 11, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 91, + "sea_level_pressure": 1021.5, + "station_pressure": 1021.1, + "time": 1770811200, + "uv": 0.0, + "wind_avg": 7.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 17.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-day", + "local_day": 11, + "local_hour": 8, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 91, + "sea_level_pressure": 1021.7, + "station_pressure": 1021.3, + "time": 1770814800, + "uv": 2.0, + "wind_avg": 8.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 17.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-day", + "local_day": 11, + "local_hour": 9, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1022.0, + "station_pressure": 1021.6, + "time": 1770818400, + "uv": 2.0, + "wind_avg": 8.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 17.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-day", + "local_day": 11, + "local_hour": 10, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 76, + "sea_level_pressure": 1022.2, + "station_pressure": 1021.8, + "time": 1770822000, + "uv": 2.0, + "wind_avg": 9.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 17.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 11, + "local_hour": 11, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1021.3, + "station_pressure": 1020.9, + "time": 1770825600, + "uv": 4.0, + "wind_avg": 10.0, + "wind_direction": 240, + "wind_direction_cardinal": "WSW", + "wind_gust": 18.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 11, + "local_hour": 12, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1020.4, + "station_pressure": 1020.0, + "time": 1770829200, + "uv": 4.0, + "wind_avg": 10.0, + "wind_direction": 240, + "wind_direction_cardinal": "WSW", + "wind_gust": 18.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 11, + "local_hour": 13, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 65, + "sea_level_pressure": 1019.5, + "station_pressure": 1019.1, + "time": 1770832800, + "uv": 4.0, + "wind_avg": 12.0, + "wind_direction": 240, + "wind_direction_cardinal": "WSW", + "wind_gust": 19.0 + }, + { + "air_temperature": 21.0, + "conditions": "Partly Cloudy", + "feels_like": 21.0, + "icon": "partly-cloudy-day", + "local_day": 11, + "local_hour": 14, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 66, + "sea_level_pressure": 1019.1, + "station_pressure": 1018.7, + "time": 1770836400, + "uv": 5.0, + "wind_avg": 12.0, + "wind_direction": 170, + "wind_direction_cardinal": "S", + "wind_gust": 19.0 + }, + { + "air_temperature": 21.0, + "conditions": "Clear", + "feels_like": 21.0, + "icon": "clear-day", + "local_day": 11, + "local_hour": 15, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 65, + "sea_level_pressure": 1018.6, + "station_pressure": 1018.2, + "time": 1770840000, + "uv": 5.0, + "wind_avg": 13.0, + "wind_direction": 170, + "wind_direction_cardinal": "S", + "wind_gust": 19.0 + }, + { + "air_temperature": 21.0, + "conditions": "Clear", + "feels_like": 21.0, + "icon": "clear-day", + "local_day": 11, + "local_hour": 16, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 66, + "sea_level_pressure": 1018.1, + "station_pressure": 1017.7, + "time": 1770843600, + "uv": 5.0, + "wind_avg": 13.0, + "wind_direction": 170, + "wind_direction_cardinal": "S", + "wind_gust": 19.0 + }, + { + "air_temperature": 20.0, + "conditions": "Clear", + "feels_like": 20.0, + "icon": "clear-day", + "local_day": 11, + "local_hour": 17, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 69, + "sea_level_pressure": 1018.4, + "station_pressure": 1018.0, + "time": 1770847200, + "uv": 3.0, + "wind_avg": 13.0, + "wind_direction": 170, + "wind_direction_cardinal": "S", + "wind_gust": 20.0 + }, + { + "air_temperature": 20.0, + "conditions": "Clear", + "feels_like": 20.0, + "icon": "clear-day", + "local_day": 11, + "local_hour": 18, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 72, + "sea_level_pressure": 1018.7, + "station_pressure": 1018.3, + "time": 1770850800, + "uv": 3.0, + "wind_avg": 12.0, + "wind_direction": 170, + "wind_direction_cardinal": "S", + "wind_gust": 20.0 + }, + { + "air_temperature": 19.0, + "conditions": "Clear", + "feels_like": 19.0, + "icon": "clear-night", + "local_day": 11, + "local_hour": 19, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 76, + "sea_level_pressure": 1019.0, + "station_pressure": 1018.6, + "time": 1770854400, + "uv": 3.0, + "wind_avg": 12.0, + "wind_direction": 170, + "wind_direction_cardinal": "S", + "wind_gust": 20.0 + }, + { + "air_temperature": 18.0, + "conditions": "Clear", + "feels_like": 18.0, + "icon": "clear-night", + "local_day": 11, + "local_hour": 20, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 77, + "sea_level_pressure": 1019.1, + "station_pressure": 1018.7, + "time": 1770858000, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 20.0 + }, + { + "air_temperature": 18.0, + "conditions": "Clear", + "feels_like": 18.0, + "icon": "clear-night", + "local_day": 11, + "local_hour": 21, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 80, + "sea_level_pressure": 1019.3, + "station_pressure": 1018.9, + "time": 1770861600, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 21.0 + }, + { + "air_temperature": 17.0, + "conditions": "Clear", + "feels_like": 17.0, + "icon": "clear-night", + "local_day": 11, + "local_hour": 22, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1019.4, + "station_pressure": 1019.0, + "time": 1770865200, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 21.0 + }, + { + "air_temperature": 17.0, + "conditions": "Clear", + "feels_like": 17.0, + "icon": "clear-night", + "local_day": 11, + "local_hour": 23, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1019.0, + "station_pressure": 1018.6, + "time": 1770868800, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 21.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-night", + "local_day": 12, + "local_hour": 0, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 85, + "sea_level_pressure": 1018.5, + "station_pressure": 1018.1, + "time": 1770872400, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 22.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-night", + "local_day": 12, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 87, + "sea_level_pressure": 1018.1, + "station_pressure": 1017.7, + "time": 1770876000, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 22.0 + }, + { + "air_temperature": 16.0, + "conditions": "Clear", + "feels_like": 16.0, + "icon": "clear-night", + "local_day": 12, + "local_hour": 2, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 88, + "sea_level_pressure": 1017.9, + "station_pressure": 1017.5, + "time": 1770879600, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 22.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 3, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 90, + "sea_level_pressure": 1017.7, + "station_pressure": 1017.3, + "time": 1770883200, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 22.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 4, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 92, + "sea_level_pressure": 1017.5, + "station_pressure": 1017.1, + "time": 1770886800, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 23.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 5, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 97, + "sea_level_pressure": 1017.9, + "station_pressure": 1017.5, + "time": 1770890400, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 23.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 6, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 99, + "sea_level_pressure": 1018.2, + "station_pressure": 1017.8, + "time": 1770894000, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 22.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 98, + "sea_level_pressure": 1018.5, + "station_pressure": 1018.1, + "time": 1770897600, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 22.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 8, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 100, + "sea_level_pressure": 1018.6, + "station_pressure": 1018.2, + "time": 1770901200, + "uv": 2.0, + "wind_avg": 13.0, + "wind_direction": 290, + "wind_direction_cardinal": "WNW", + "wind_gust": 22.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 9, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 93, + "sea_level_pressure": 1018.7, + "station_pressure": 1018.3, + "time": 1770904800, + "uv": 2.0, + "wind_avg": 14.0, + "wind_direction": 290, + "wind_direction_cardinal": "WNW", + "wind_gust": 22.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 10, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 85, + "sea_level_pressure": 1018.8, + "station_pressure": 1018.4, + "time": 1770908400, + "uv": 2.0, + "wind_avg": 14.0, + "wind_direction": 290, + "wind_direction_cardinal": "WNW", + "wind_gust": 22.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 11, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 81, + "sea_level_pressure": 1018.1, + "station_pressure": 1017.7, + "time": 1770912000, + "uv": 4.0, + "wind_avg": 15.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 22.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 12, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 77, + "sea_level_pressure": 1017.5, + "station_pressure": 1017.1, + "time": 1770915600, + "uv": 4.0, + "wind_avg": 15.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 22.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 13, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 75, + "sea_level_pressure": 1016.8, + "station_pressure": 1016.4, + "time": 1770919200, + "uv": 4.0, + "wind_avg": 16.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 22.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 14, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1016.4, + "station_pressure": 1016.0, + "time": 1770922800, + "uv": 1.0, + "wind_avg": 16.0, + "wind_direction": 350, + "wind_direction_cardinal": "N", + "wind_gust": 22.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 15, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1016.1, + "station_pressure": 1015.7, + "time": 1770926400, + "uv": 1.0, + "wind_avg": 15.0, + "wind_direction": 350, + "wind_direction_cardinal": "N", + "wind_gust": 22.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 16, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 75, + "sea_level_pressure": 1015.7, + "station_pressure": 1015.3, + "time": 1770930000, + "uv": 1.0, + "wind_avg": 15.0, + "wind_direction": 350, + "wind_direction_cardinal": "N", + "wind_gust": 22.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 17, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 77, + "sea_level_pressure": 1016.2, + "station_pressure": 1015.8, + "time": 1770933600, + "uv": 1.0, + "wind_avg": 14.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 21.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 12, + "local_hour": 18, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 79, + "sea_level_pressure": 1016.7, + "station_pressure": 1016.3, + "time": 1770937200, + "uv": 1.0, + "wind_avg": 13.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 21.0 + }, + { + "air_temperature": 18.0, + "conditions": "Clear", + "feels_like": 18.0, + "icon": "clear-night", + "local_day": 12, + "local_hour": 19, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 82, + "sea_level_pressure": 1017.2, + "station_pressure": 1016.8, + "time": 1770940800, + "uv": 1.0, + "wind_avg": 12.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 20.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 20, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 81, + "sea_level_pressure": 1017.4, + "station_pressure": 1017.0, + "time": 1770944400, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 21.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 21, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 84, + "sea_level_pressure": 1017.6, + "station_pressure": 1017.2, + "time": 1770948000, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 21.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 22, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 86, + "sea_level_pressure": 1017.8, + "station_pressure": 1017.4, + "time": 1770951600, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 260, + "wind_direction_cardinal": "W", + "wind_gust": 21.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 12, + "local_hour": 23, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 86, + "sea_level_pressure": 1017.6, + "station_pressure": 1017.2, + "time": 1770955200, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 21.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 0, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 88, + "sea_level_pressure": 1017.5, + "station_pressure": 1017.1, + "time": 1770958800, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 22.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 90, + "sea_level_pressure": 1017.3, + "station_pressure": 1016.9, + "time": 1770962400, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 280, + "wind_direction_cardinal": "W", + "wind_gust": 22.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 2, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 89, + "sea_level_pressure": 1017.2, + "station_pressure": 1016.8, + "time": 1770966000, + "uv": 0.0, + "wind_avg": 12.0, + "wind_direction": 300, + "wind_direction_cardinal": "WNW", + "wind_gust": 23.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 3, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 90, + "sea_level_pressure": 1017.1, + "station_pressure": 1016.7, + "time": 1770969600, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 300, + "wind_direction_cardinal": "WNW", + "wind_gust": 23.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 4, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 91, + "sea_level_pressure": 1017.0, + "station_pressure": 1016.6, + "time": 1770973200, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 300, + "wind_direction_cardinal": "WNW", + "wind_gust": 23.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 5, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 91, + "sea_level_pressure": 1017.5, + "station_pressure": 1017.1, + "time": 1770976800, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 23.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 6, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 94, + "sea_level_pressure": 1017.9, + "station_pressure": 1017.5, + "time": 1770980400, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 24.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 93, + "sea_level_pressure": 1018.3, + "station_pressure": 1017.9, + "time": 1770984000, + "uv": 0.0, + "wind_avg": 13.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 24.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 8, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 94, + "sea_level_pressure": 1018.6, + "station_pressure": 1018.2, + "time": 1770987600, + "uv": 2.0, + "wind_avg": 14.0, + "wind_direction": 340, + "wind_direction_cardinal": "NNW", + "wind_gust": 24.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 9, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 86, + "sea_level_pressure": 1019.0, + "station_pressure": 1018.6, + "time": 1770991200, + "uv": 2.0, + "wind_avg": 15.0, + "wind_direction": 340, + "wind_direction_cardinal": "NNW", + "wind_gust": 24.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 10, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 79, + "sea_level_pressure": 1019.4, + "station_pressure": 1019.0, + "time": 1770994800, + "uv": 2.0, + "wind_avg": 16.0, + "wind_direction": 340, + "wind_direction_cardinal": "NNW", + "wind_gust": 24.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 11, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 75, + "sea_level_pressure": 1018.9, + "station_pressure": 1018.5, + "time": 1770998400, + "uv": 4.0, + "wind_avg": 17.0, + "wind_direction": 50, + "wind_direction_cardinal": "NE", + "wind_gust": 25.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 12, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 72, + "sea_level_pressure": 1018.5, + "station_pressure": 1018.1, + "time": 1771002000, + "uv": 4.0, + "wind_avg": 17.0, + "wind_direction": 50, + "wind_direction_cardinal": "NE", + "wind_gust": 26.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 13, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1018.1, + "station_pressure": 1017.7, + "time": 1771005600, + "uv": 4.0, + "wind_avg": 18.0, + "wind_direction": 50, + "wind_direction_cardinal": "NE", + "wind_gust": 26.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 14, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1017.6, + "station_pressure": 1017.2, + "time": 1771009200, + "uv": 5.0, + "wind_avg": 18.0, + "wind_direction": 90, + "wind_direction_cardinal": "E", + "wind_gust": 26.0 + }, + { + "air_temperature": 20.0, + "conditions": "Partly Cloudy", + "feels_like": 20.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 15, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1017.1, + "station_pressure": 1016.7, + "time": 1771012800, + "uv": 5.0, + "wind_avg": 18.0, + "wind_direction": 90, + "wind_direction_cardinal": "E", + "wind_gust": 27.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 16, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1016.6, + "station_pressure": 1016.2, + "time": 1771016400, + "uv": 5.0, + "wind_avg": 19.0, + "wind_direction": 90, + "wind_direction_cardinal": "E", + "wind_gust": 27.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 17, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 75, + "sea_level_pressure": 1016.9, + "station_pressure": 1016.5, + "time": 1771020000, + "uv": 3.0, + "wind_avg": 18.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 26.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 13, + "local_hour": 18, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 78, + "sea_level_pressure": 1017.2, + "station_pressure": 1016.8, + "time": 1771023600, + "uv": 3.0, + "wind_avg": 17.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 26.0 + }, + { + "air_temperature": 18.0, + "conditions": "Clear", + "feels_like": 18.0, + "icon": "clear-night", + "local_day": 13, + "local_hour": 19, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 80, + "sea_level_pressure": 1017.5, + "station_pressure": 1017.1, + "time": 1771027200, + "uv": 3.0, + "wind_avg": 16.0, + "wind_direction": 110, + "wind_direction_cardinal": "ESE", + "wind_gust": 25.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 20, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 81, + "sea_level_pressure": 1017.6, + "station_pressure": 1017.2, + "time": 1771030800, + "uv": 0.0, + "wind_avg": 16.0, + "wind_direction": 100, + "wind_direction_cardinal": "E", + "wind_gust": 26.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 21, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1017.6, + "station_pressure": 1017.2, + "time": 1771034400, + "uv": 0.0, + "wind_avg": 16.0, + "wind_direction": 100, + "wind_direction_cardinal": "E", + "wind_gust": 26.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 22, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 85, + "sea_level_pressure": 1017.7, + "station_pressure": 1017.3, + "time": 1771038000, + "uv": 0.0, + "wind_avg": 16.0, + "wind_direction": 100, + "wind_direction_cardinal": "E", + "wind_gust": 27.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 13, + "local_hour": 23, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 84, + "sea_level_pressure": 1017.2, + "station_pressure": 1016.8, + "time": 1771041600, + "uv": 0.0, + "wind_avg": 17.0, + "wind_direction": 340, + "wind_direction_cardinal": "NNW", + "wind_gust": 27.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 0, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 86, + "sea_level_pressure": 1016.8, + "station_pressure": 1016.4, + "time": 1771045200, + "uv": 0.0, + "wind_avg": 17.0, + "wind_direction": 340, + "wind_direction_cardinal": "NNW", + "wind_gust": 27.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 88, + "sea_level_pressure": 1016.4, + "station_pressure": 1016.0, + "time": 1771048800, + "uv": 0.0, + "wind_avg": 18.0, + "wind_direction": 340, + "wind_direction_cardinal": "NNW", + "wind_gust": 28.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 2, + "precip": 0.09, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 87, + "sea_level_pressure": 1015.9, + "station_pressure": 1015.5, + "time": 1771052400, + "uv": 0.0, + "wind_avg": 18.0, + "wind_direction": 320, + "wind_direction_cardinal": "NW", + "wind_gust": 28.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 3, + "precip": 0.17, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 90, + "sea_level_pressure": 1015.5, + "station_pressure": 1015.1, + "time": 1771056000, + "uv": 0.0, + "wind_avg": 18.0, + "wind_direction": 320, + "wind_direction_cardinal": "NW", + "wind_gust": 28.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 4, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 91, + "sea_level_pressure": 1015.0, + "station_pressure": 1014.6, + "time": 1771059600, + "uv": 0.0, + "wind_avg": 18.0, + "wind_direction": 320, + "wind_direction_cardinal": "NW", + "wind_gust": 29.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 5, + "precip": 0.17, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 92, + "sea_level_pressure": 1015.4, + "station_pressure": 1015.0, + "time": 1771063200, + "uv": 0.0, + "wind_avg": 18.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 29.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 6, + "precip": 0.09, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 95, + "sea_level_pressure": 1015.8, + "station_pressure": 1015.4, + "time": 1771066800, + "uv": 0.0, + "wind_avg": 18.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 30.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 94, + "sea_level_pressure": 1016.2, + "station_pressure": 1015.8, + "time": 1771070400, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 310, + "wind_direction_cardinal": "NW", + "wind_gust": 30.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 8, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 0, + "precip_type": "rain", + "relative_humidity": 90, + "sea_level_pressure": 1016.4, + "station_pressure": 1016.0, + "time": 1771074000, + "uv": 2.0, + "wind_avg": 19.0, + "wind_direction": 320, + "wind_direction_cardinal": "NW", + "wind_gust": 30.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 9, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 83, + "sea_level_pressure": 1016.6, + "station_pressure": 1016.2, + "time": 1771077600, + "uv": 2.0, + "wind_avg": 20.0, + "wind_direction": 320, + "wind_direction_cardinal": "NW", + "wind_gust": 31.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 10, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 77, + "sea_level_pressure": 1016.8, + "station_pressure": 1016.4, + "time": 1771081200, + "uv": 2.0, + "wind_avg": 21.0, + "wind_direction": 320, + "wind_direction_cardinal": "NW", + "wind_gust": 31.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 11, + "precip": 0.09, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1016.1, + "station_pressure": 1015.7, + "time": 1771084800, + "uv": 4.0, + "wind_avg": 21.0, + "wind_direction": 210, + "wind_direction_cardinal": "SSW", + "wind_gust": 32.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 12, + "precip": 0.17, + "precip_icon": "chance-rain", + "precip_probability": 5, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1015.4, + "station_pressure": 1015.0, + "time": 1771088400, + "uv": 4.0, + "wind_avg": 22.0, + "wind_direction": 210, + "wind_direction_cardinal": "SSW", + "wind_gust": 32.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 13, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 69, + "sea_level_pressure": 1014.7, + "station_pressure": 1014.3, + "time": 1771092000, + "uv": 4.0, + "wind_avg": 22.0, + "wind_direction": 210, + "wind_direction_cardinal": "SSW", + "wind_gust": 33.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 14, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 67, + "sea_level_pressure": 1014.4, + "station_pressure": 1014.0, + "time": 1771095600, + "uv": 3.0, + "wind_avg": 22.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 33.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 15, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 67, + "sea_level_pressure": 1014.2, + "station_pressure": 1013.8, + "time": 1771099200, + "uv": 3.0, + "wind_avg": 22.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 32.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 16, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1013.9, + "station_pressure": 1013.5, + "time": 1771102800, + "uv": 3.0, + "wind_avg": 21.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 32.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 17, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 69, + "sea_level_pressure": 1013.7, + "station_pressure": 1013.3, + "time": 1771106400, + "uv": 3.0, + "wind_avg": 21.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 32.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 14, + "local_hour": 18, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1013.4, + "station_pressure": 1013.0, + "time": 1771110000, + "uv": 3.0, + "wind_avg": 21.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 32.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 19, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 15, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1013.2, + "station_pressure": 1012.8, + "time": 1771113600, + "uv": 3.0, + "wind_avg": 21.0, + "wind_direction": 180, + "wind_direction_cardinal": "S", + "wind_gust": 32.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 20, + "precip": 0.21, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 72, + "sea_level_pressure": 1013.3, + "station_pressure": 1012.9, + "time": 1771117200, + "uv": 0.0, + "wind_avg": 21.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 32.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 21, + "precip": 0.17, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1013.4, + "station_pressure": 1013.0, + "time": 1771120800, + "uv": 0.0, + "wind_avg": 20.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 32.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 22, + "precip": 0.13, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 75, + "sea_level_pressure": 1013.6, + "station_pressure": 1013.2, + "time": 1771124400, + "uv": 0.0, + "wind_avg": 20.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 32.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 14, + "local_hour": 23, + "precip": 0.09, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 78, + "sea_level_pressure": 1013.7, + "station_pressure": 1013.3, + "time": 1771128000, + "uv": 0.0, + "wind_avg": 20.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 0, + "precip": 0.04, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 80, + "sea_level_pressure": 1013.8, + "station_pressure": 1013.4, + "time": 1771131600, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 1, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 82, + "sea_level_pressure": 1014.0, + "station_pressure": 1013.6, + "time": 1771135200, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 2, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 86, + "sea_level_pressure": 1014.1, + "station_pressure": 1013.7, + "time": 1771138800, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 3, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 88, + "sea_level_pressure": 1014.2, + "station_pressure": 1013.8, + "time": 1771142400, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 4, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 91, + "sea_level_pressure": 1014.3, + "station_pressure": 1013.9, + "time": 1771146000, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 5, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 92, + "sea_level_pressure": 1014.4, + "station_pressure": 1014.0, + "time": 1771149600, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 6, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 92, + "sea_level_pressure": 1014.5, + "station_pressure": 1014.1, + "time": 1771153200, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 14.0, + "conditions": "Partly Cloudy", + "feels_like": 14.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 7, + "precip": 0, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 90, + "sea_level_pressure": 1014.6, + "station_pressure": 1014.2, + "time": 1771156800, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 230, + "wind_direction_cardinal": "SW", + "wind_gust": 31.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 8, + "precip": 0.04, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 93, + "sea_level_pressure": 1014.4, + "station_pressure": 1014.0, + "time": 1771160400, + "uv": 4.0, + "wind_avg": 19.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 31.0 + }, + { + "air_temperature": 15.0, + "conditions": "Partly Cloudy", + "feels_like": 15.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 9, + "precip": 0.09, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 88, + "sea_level_pressure": 1014.2, + "station_pressure": 1013.8, + "time": 1771164000, + "uv": 4.0, + "wind_avg": 19.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 31.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 10, + "precip": 0.13, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 82, + "sea_level_pressure": 1014.0, + "station_pressure": 1013.6, + "time": 1771167600, + "uv": 4.0, + "wind_avg": 20.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 31.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 11, + "precip": 0.17, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 76, + "sea_level_pressure": 1013.8, + "station_pressure": 1013.4, + "time": 1771171200, + "uv": 4.0, + "wind_avg": 20.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 31.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 12, + "precip": 0.21, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1013.5, + "station_pressure": 1013.1, + "time": 1771174800, + "uv": 4.0, + "wind_avg": 21.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 31.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 13, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 70, + "sea_level_pressure": 1013.3, + "station_pressure": 1012.9, + "time": 1771178400, + "uv": 4.0, + "wind_avg": 21.0, + "wind_direction": 250, + "wind_direction_cardinal": "WSW", + "wind_gust": 30.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 14, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1013.4, + "station_pressure": 1013.0, + "time": 1771182000, + "uv": 3.0, + "wind_avg": 21.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 30.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 15, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 68, + "sea_level_pressure": 1013.5, + "station_pressure": 1013.1, + "time": 1771185600, + "uv": 3.0, + "wind_avg": 21.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 30.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 16, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 69, + "sea_level_pressure": 1013.6, + "station_pressure": 1013.2, + "time": 1771189200, + "uv": 3.0, + "wind_avg": 20.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 30.0 + }, + { + "air_temperature": 19.0, + "conditions": "Partly Cloudy", + "feels_like": 19.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 17, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 71, + "sea_level_pressure": 1013.7, + "station_pressure": 1013.3, + "time": 1771192800, + "uv": 3.0, + "wind_avg": 20.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 30.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-day", + "local_day": 15, + "local_hour": 18, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 73, + "sea_level_pressure": 1013.8, + "station_pressure": 1013.4, + "time": 1771196400, + "uv": 3.0, + "wind_avg": 20.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 30.0 + }, + { + "air_temperature": 18.0, + "conditions": "Partly Cloudy", + "feels_like": 18.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 19, + "precip": 0.25, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 75, + "sea_level_pressure": 1013.8, + "station_pressure": 1013.4, + "time": 1771200000, + "uv": 3.0, + "wind_avg": 19.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 30.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 20, + "precip": 0.21, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 74, + "sea_level_pressure": 1014.0, + "station_pressure": 1013.6, + "time": 1771203600, + "uv": 0.0, + "wind_avg": 19.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 29.0 + }, + { + "air_temperature": 17.0, + "conditions": "Partly Cloudy", + "feels_like": 17.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 21, + "precip": 0.17, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 76, + "sea_level_pressure": 1014.2, + "station_pressure": 1013.8, + "time": 1771207200, + "uv": 0.0, + "wind_avg": 18.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 29.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 22, + "precip": 0.13, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 78, + "sea_level_pressure": 1014.4, + "station_pressure": 1014.0, + "time": 1771210800, + "uv": 0.0, + "wind_avg": 18.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 29.0 + }, + { + "air_temperature": 16.0, + "conditions": "Partly Cloudy", + "feels_like": 16.0, + "icon": "partly-cloudy-night", + "local_day": 15, + "local_hour": 23, + "precip": 0.09, + "precip_icon": "chance-rain", + "precip_probability": 10, + "precip_type": "rain", + "relative_humidity": 81, + "sea_level_pressure": 1014.6, + "station_pressure": 1014.2, + "time": 1771214400, + "uv": 0.0, + "wind_avg": 17.0, + "wind_direction": 270, + "wind_direction_cardinal": "W", + "wind_gust": 29.0 + } + ] + }, + "latitude": 29.05592, + "location_name": "OG Pergola", + "longitude": -80.90748, + "source_id_conditions": 5, + "station": { "agl": 1.8288, "elevation": 3.0345869064331055, "is_station_online": true, "state": 1, "station_id": 151283 }, + "status": { "status_code": 0, "status_message": "SUCCESS" }, + "timezone": "America/New_York", + "timezone_offset_minutes": -300, + "units": { "units_air_density": "kg/m3", "units_brightness": "lux", "units_distance": "km", "units_other": "metric", "units_precip": "mm", "units_pressure": "mb", "units_solar_radiation": "w/m2", "units_temp": "c", "units_wind": "kph" } +} diff --git a/tests/mocks/weather_weathergov_current.json b/tests/mocks/weather_weathergov_current.json new file mode 100644 index 0000000000..770bba1ff8 --- /dev/null +++ b/tests/mocks/weather_weathergov_current.json @@ -0,0 +1,151 @@ +{ + "@context": [ + "https://geojson.org/geojson-ld/geojson-context.jsonld", + { + "@version": "1.1", + "wx": "https://api.weather.gov/ontology#", + "s": "https://schema.org/", + "geo": "http://www.opengis.net/ont/geosparql#", + "unit": "http://codes.wmo.int/common/unit/", + "@vocab": "https://api.weather.gov/ontology#", + "geometry": { + "@id": "s:GeoCoordinates", + "@type": "geo:wktLiteral" + }, + "city": "s:addressLocality", + "state": "s:addressRegion", + "distance": { + "@id": "s:Distance", + "@type": "s:QuantitativeValue" + }, + "bearing": { + "@type": "s:QuantitativeValue" + }, + "value": { + "@id": "s:value" + }, + "unitCode": { + "@id": "s:unitCode", + "@type": "@id" + }, + "forecastOffice": { + "@type": "@id" + }, + "forecastGridData": { + "@type": "@id" + }, + "publicZone": { + "@type": "@id" + }, + "county": { + "@type": "@id" + } + } + ], + "id": "https://api.weather.gov/stations/KDCA/observations/2026-02-06T21:30:00+00:00", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.03, 38.85] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KDCA/observations/2026-02-06T21:30:00+00:00", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 20 + }, + "station": "https://api.weather.gov/stations/KDCA", + "stationId": "KDCA", + "stationName": "Washington/Reagan National Airport, DC", + "timestamp": "2026-02-06T21:30:00+00:00", + "rawMessage": "", + "textDescription": "Light Snow", + "icon": "https://api.weather.gov/icons/land/day/snow?size=medium", + "presentWeather": [ + { + "intensity": "light", + "modifier": null, + "weather": "snow", + "rawString": "-SN" + } + ], + "temperature": { + "unitCode": "wmoUnit:degC", + "value": -1, + "qualityControl": "V" + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -7, + "qualityControl": "V" + }, + "windDirection": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 0, + "qualityControl": "V" + }, + "windSpeed": { + "unitCode": "wmoUnit:km_h-1", + "value": 0, + "qualityControl": "V" + }, + "windGust": { + "unitCode": "wmoUnit:km_h-1", + "value": null, + "qualityControl": "Z" + }, + "barometricPressure": { + "unitCode": "wmoUnit:Pa", + "value": 100372.55, + "qualityControl": "V" + }, + "seaLevelPressure": { + "unitCode": "wmoUnit:Pa", + "value": null, + "qualityControl": "Z" + }, + "visibility": { + "unitCode": "wmoUnit:m", + "value": 9656.06, + "qualityControl": "C" + }, + "maxTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "minTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "precipitationLast3Hours": { + "unitCode": "wmoUnit:mm", + "value": null, + "qualityControl": "Z" + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 63.771213893297, + "qualityControl": "V" + }, + "windChill": { + "unitCode": "wmoUnit:degC", + "value": null, + "qualityControl": "V" + }, + "heatIndex": { + "unitCode": "wmoUnit:degC", + "value": null, + "qualityControl": "V" + }, + "cloudLayers": [ + { + "base": { + "unitCode": "wmoUnit:m", + "value": 944.88 + }, + "amount": "OVC" + } + ] + } +} diff --git a/tests/mocks/weather_weathergov_forecast.json b/tests/mocks/weather_weathergov_forecast.json new file mode 100644 index 0000000000..258d86532b --- /dev/null +++ b/tests/mocks/weather_weathergov_forecast.json @@ -0,0 +1,304 @@ +{ + "@context": [ + "https://geojson.org/geojson-ld/geojson-context.jsonld", + { + "@version": "1.1", + "wx": "https://api.weather.gov/ontology#", + "geo": "http://www.opengis.net/ont/geosparql#", + "unit": "http://codes.wmo.int/common/unit/", + "@vocab": "https://api.weather.gov/ontology#" + } + ], + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-77.0445, 38.8569], + [-77.0408, 38.8788], + [-77.0689, 38.8818], + [-77.0727, 38.8598], + [-77.0445, 38.8569] + ] + ] + }, + "properties": { + "units": "si", + "forecastGenerator": "BaselineForecastGenerator", + "generatedAt": "2026-02-06T21:45:05+00:00", + "updateTime": "2026-02-06T20:53:00+00:00", + "validTimes": "2026-02-06T14:00:00+00:00/P7DT14H", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 7.9248 + }, + "periods": [ + { + "number": 1, + "name": "This Afternoon", + "startTime": "2026-02-06T16:00:00-05:00", + "endTime": "2026-02-06T18:00:00-05:00", + "isDaytime": true, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 71 + }, + "windSpeed": "4 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/snow,70?size=medium", + "shortForecast": "Light Snow Likely", + "detailedForecast": "Snow likely. Cloudy, with a high near 1. South wind around 4 km/h. Chance of precipitation is 70%. New snow accumulation of less than one cm possible." + }, + { + "number": 2, + "name": "Tonight", + "startTime": "2026-02-06T18:00:00-05:00", + "endTime": "2026-02-07T06:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 45 + }, + "windSpeed": "2 to 35 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/night/snow,50/wind_bkn?size=medium", + "shortForecast": "Chance Light Snow then Mostly Cloudy", + "detailedForecast": "A chance of snow before 10pm. Mostly cloudy. Low around -11, with temperatures rising to around -7 overnight. West wind 2 to 35 km/h, with gusts as high as 63 km/h. Chance of precipitation is 50%. New snow accumulation of less than two cm possible." + }, + { + "number": 3, + "name": "Saturday", + "startTime": "2026-02-07T06:00:00-05:00", + "endTime": "2026-02-07T18:00:00-05:00", + "isDaytime": true, + "temperature": -7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "37 to 48 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=medium", + "shortForecast": "Mostly Sunny", + "detailedForecast": "Mostly sunny, with a high near -7. Wind chill values as low as -21. Northwest wind 37 to 48 km/h, with gusts as high as 94 km/h." + }, + { + "number": 4, + "name": "Saturday Night", + "startTime": "2026-02-07T18:00:00-05:00", + "endTime": "2026-02-08T06:00:00-05:00", + "isDaytime": false, + "temperature": -12, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "22 to 43 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/wind_few?size=medium", + "shortForecast": "Mostly Clear", + "detailedForecast": "Mostly clear, with a low around -12. Wind chill values as low as -21. Northwest wind 22 to 43 km/h, with gusts as high as 76 km/h." + }, + { + "number": 5, + "name": "Sunday", + "startTime": "2026-02-08T06:00:00-05:00", + "endTime": "2026-02-08T18:00:00-05:00", + "isDaytime": true, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "windSpeed": "13 to 22 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=medium", + "shortForecast": "Mostly Sunny", + "detailedForecast": "Mostly sunny, with a high near -4. Northwest wind 13 to 22 km/h, with gusts as high as 43 km/h." + }, + { + "number": 6, + "name": "Sunday Night", + "startTime": "2026-02-08T18:00:00-05:00", + "endTime": "2026-02-09T06:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "windSpeed": "4 to 9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=medium", + "shortForecast": "Partly Cloudy", + "detailedForecast": "Partly cloudy, with a low around -11." + }, + { + "number": 7, + "name": "Monday", + "startTime": "2026-02-09T06:00:00-05:00", + "endTime": "2026-02-09T18:00:00-05:00", + "isDaytime": true, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "7 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=medium", + "shortForecast": "Partly Sunny", + "detailedForecast": "Partly sunny, with a high near 0." + }, + { + "number": 8, + "name": "Monday Night", + "startTime": "2026-02-09T18:00:00-05:00", + "endTime": "2026-02-10T06:00:00-05:00", + "isDaytime": false, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "2 km/h", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=medium", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "Mostly cloudy, with a low around -6." + }, + { + "number": 9, + "name": "Tuesday", + "startTime": "2026-02-10T06:00:00-05:00", + "endTime": "2026-02-10T18:00:00-05:00", + "isDaytime": true, + "temperature": 7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "windSpeed": "6 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=medium", + "shortForecast": "Mostly Sunny", + "detailedForecast": "Mostly sunny, with a high near 7." + }, + { + "number": 10, + "name": "Tuesday Night", + "startTime": "2026-02-10T18:00:00-05:00", + "endTime": "2026-02-11T06:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 18 + }, + "windSpeed": "4 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/bkn/rain,20?size=medium", + "shortForecast": "Mostly Cloudy then Slight Chance Light Rain", + "detailedForecast": "A slight chance of rain after 1am. Mostly cloudy, with a low around -1." + }, + { + "number": 11, + "name": "Wednesday", + "startTime": "2026-02-11T06:00:00-05:00", + "endTime": "2026-02-11T18:00:00-05:00", + "isDaytime": true, + "temperature": 8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "windSpeed": "4 to 11 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain. Mostly cloudy, with a high near 8. Chance of precipitation is 50%." + }, + { + "number": 12, + "name": "Wednesday Night", + "startTime": "2026-02-11T18:00:00-05:00", + "endTime": "2026-02-12T06:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,50/rain,30?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain. Mostly cloudy, with a low around -1. Chance of precipitation is 50%." + }, + { + "number": 13, + "name": "Thursday", + "startTime": "2026-02-12T06:00:00-05:00", + "endTime": "2026-02-12T18:00:00-05:00", + "isDaytime": true, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "windSpeed": "11 to 17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,30/rain,20?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain before 1pm. Mostly cloudy, with a high near 4. Chance of precipitation is 30%." + }, + { + "number": 14, + "name": "Thursday Night", + "startTime": "2026-02-12T18:00:00-05:00", + "endTime": "2026-02-13T06:00:00-05:00", + "isDaytime": false, + "temperature": -3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "windSpeed": "13 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=medium", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "A slight chance of snow after 7pm. Mostly cloudy, with a low around -3." + } + ] + } +} diff --git a/tests/mocks/weather_weathergov_hourly.json b/tests/mocks/weather_weathergov_hourly.json new file mode 100644 index 0000000000..e4fc3bb862 --- /dev/null +++ b/tests/mocks/weather_weathergov_hourly.json @@ -0,0 +1,4250 @@ +{ + "@context": [ + "https://geojson.org/geojson-ld/geojson-context.jsonld", + { + "@version": "1.1", + "wx": "https://api.weather.gov/ontology#", + "geo": "http://www.opengis.net/ont/geosparql#", + "unit": "http://codes.wmo.int/common/unit/", + "@vocab": "https://api.weather.gov/ontology#" + } + ], + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [-77.0445, 38.8569], + [-77.0408, 38.8788], + [-77.0689, 38.8818], + [-77.0727, 38.8598], + [-77.0445, 38.8569] + ] + ] + }, + "properties": { + "units": "si", + "forecastGenerator": "HourlyForecastGenerator", + "generatedAt": "2026-02-06T21:45:06+00:00", + "updateTime": "2026-02-06T20:53:00+00:00", + "validTimes": "2026-02-06T14:00:00+00:00/P7DT14H", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 7.9248 + }, + "periods": [ + { + "number": 1, + "name": "", + "startTime": "2026-02-06T16:00:00-05:00", + "endTime": "2026-02-06T17:00:00-05:00", + "isDaytime": true, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 71 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.888888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 72 + }, + "windSpeed": "4 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/snow,70?size=small", + "shortForecast": "Light Snow Likely", + "detailedForecast": "" + }, + { + "number": 2, + "name": "", + "startTime": "2026-02-06T17:00:00-05:00", + "endTime": "2026-02-06T18:00:00-05:00", + "isDaytime": true, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 57 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.3333333333333335 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "4 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/snow,60?size=small", + "shortForecast": "Light Snow Likely", + "detailedForecast": "" + }, + { + "number": 3, + "name": "", + "startTime": "2026-02-06T18:00:00-05:00", + "endTime": "2026-02-06T19:00:00-05:00", + "isDaytime": false, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 45 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.888888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "2 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/snow,50?size=small", + "shortForecast": "Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 4, + "name": "", + "startTime": "2026-02-06T19:00:00-05:00", + "endTime": "2026-02-06T20:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 37 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -4.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "4 km/h", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/snow,40?size=small", + "shortForecast": "Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 5, + "name": "", + "startTime": "2026-02-06T20:00:00-05:00", + "endTime": "2026-02-06T21:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 30 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.888888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 81 + }, + "windSpeed": "4 km/h", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/night/snow,30?size=small", + "shortForecast": "Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 6, + "name": "", + "startTime": "2026-02-06T21:00:00-05:00", + "endTime": "2026-02-06T22:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 17 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.888888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 81 + }, + "windSpeed": "4 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 7, + "name": "", + "startTime": "2026-02-06T22:00:00-05:00", + "endTime": "2026-02-06T23:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 13 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.888888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 81 + }, + "windSpeed": "6 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 8, + "name": "", + "startTime": "2026-02-06T23:00:00-05:00", + "endTime": "2026-02-07T00:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 5 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -4.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "7 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 9, + "name": "", + "startTime": "2026-02-07T00:00:00-05:00", + "endTime": "2026-02-07T01:00:00-05:00", + "isDaytime": false, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 7 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -5 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "9 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 10, + "name": "", + "startTime": "2026-02-07T01:00:00-05:00", + "endTime": "2026-02-07T02:00:00-05:00", + "isDaytime": false, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 6 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -5.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 11, + "name": "", + "startTime": "2026-02-07T02:00:00-05:00", + "endTime": "2026-02-07T03:00:00-05:00", + "isDaytime": false, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -6.666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "19 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 12, + "name": "", + "startTime": "2026-02-07T03:00:00-05:00", + "endTime": "2026-02-07T04:00:00-05:00", + "isDaytime": false, + "temperature": -3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -7.777777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 68 + }, + "windSpeed": "24 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 13, + "name": "", + "startTime": "2026-02-07T04:00:00-05:00", + "endTime": "2026-02-07T05:00:00-05:00", + "isDaytime": false, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 68 + }, + "windSpeed": "31 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 14, + "name": "", + "startTime": "2026-02-07T05:00:00-05:00", + "endTime": "2026-02-07T06:00:00-05:00", + "isDaytime": false, + "temperature": -7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 71 + }, + "windSpeed": "35 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/wind_sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 15, + "name": "", + "startTime": "2026-02-07T06:00:00-05:00", + "endTime": "2026-02-07T07:00:00-05:00", + "isDaytime": true, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.333333333333334 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 64 + }, + "windSpeed": "37 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 16, + "name": "", + "startTime": "2026-02-07T07:00:00-05:00", + "endTime": "2026-02-07T08:00:00-05:00", + "isDaytime": true, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "39 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 17, + "name": "", + "startTime": "2026-02-07T08:00:00-05:00", + "endTime": "2026-02-07T09:00:00-05:00", + "isDaytime": true, + "temperature": -10, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -16.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "43 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 18, + "name": "", + "startTime": "2026-02-07T09:00:00-05:00", + "endTime": "2026-02-07T10:00:00-05:00", + "isDaytime": true, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.22222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 53 + }, + "windSpeed": "44 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 19, + "name": "", + "startTime": "2026-02-07T10:00:00-05:00", + "endTime": "2026-02-07T11:00:00-05:00", + "isDaytime": true, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 48 + }, + "windSpeed": "48 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 20, + "name": "", + "startTime": "2026-02-07T11:00:00-05:00", + "endTime": "2026-02-07T12:00:00-05:00", + "isDaytime": true, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 48 + }, + "windSpeed": "48 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 21, + "name": "", + "startTime": "2026-02-07T12:00:00-05:00", + "endTime": "2026-02-07T13:00:00-05:00", + "isDaytime": true, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 44 + }, + "windSpeed": "48 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 22, + "name": "", + "startTime": "2026-02-07T13:00:00-05:00", + "endTime": "2026-02-07T14:00:00-05:00", + "isDaytime": true, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 46 + }, + "windSpeed": "48 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 23, + "name": "", + "startTime": "2026-02-07T14:00:00-05:00", + "endTime": "2026-02-07T15:00:00-05:00", + "isDaytime": true, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 42 + }, + "windSpeed": "46 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 24, + "name": "", + "startTime": "2026-02-07T15:00:00-05:00", + "endTime": "2026-02-07T16:00:00-05:00", + "isDaytime": true, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 42 + }, + "windSpeed": "43 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 25, + "name": "", + "startTime": "2026-02-07T16:00:00-05:00", + "endTime": "2026-02-07T17:00:00-05:00", + "isDaytime": true, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.77777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 44 + }, + "windSpeed": "41 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 26, + "name": "", + "startTime": "2026-02-07T17:00:00-05:00", + "endTime": "2026-02-07T18:00:00-05:00", + "isDaytime": true, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 42 + }, + "windSpeed": "41 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 27, + "name": "", + "startTime": "2026-02-07T18:00:00-05:00", + "endTime": "2026-02-07T19:00:00-05:00", + "isDaytime": false, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 46 + }, + "windSpeed": "43 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 28, + "name": "", + "startTime": "2026-02-07T19:00:00-05:00", + "endTime": "2026-02-07T20:00:00-05:00", + "isDaytime": false, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 44 + }, + "windSpeed": "43 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 29, + "name": "", + "startTime": "2026-02-07T20:00:00-05:00", + "endTime": "2026-02-07T21:00:00-05:00", + "isDaytime": false, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.22222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 51 + }, + "windSpeed": "39 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 30, + "name": "", + "startTime": "2026-02-07T21:00:00-05:00", + "endTime": "2026-02-07T22:00:00-05:00", + "isDaytime": false, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.77777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "windSpeed": "37 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 31, + "name": "", + "startTime": "2026-02-07T22:00:00-05:00", + "endTime": "2026-02-07T23:00:00-05:00", + "isDaytime": false, + "temperature": -10, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.77777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 53 + }, + "windSpeed": "33 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 32, + "name": "", + "startTime": "2026-02-07T23:00:00-05:00", + "endTime": "2026-02-08T00:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.77777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 55 + }, + "windSpeed": "31 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 33, + "name": "", + "startTime": "2026-02-08T00:00:00-05:00", + "endTime": "2026-02-08T01:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 53 + }, + "windSpeed": "28 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 34, + "name": "", + "startTime": "2026-02-08T01:00:00-05:00", + "endTime": "2026-02-08T02:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 55 + }, + "windSpeed": "28 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 35, + "name": "", + "startTime": "2026-02-08T02:00:00-05:00", + "endTime": "2026-02-08T03:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 55 + }, + "windSpeed": "26 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 36, + "name": "", + "startTime": "2026-02-08T03:00:00-05:00", + "endTime": "2026-02-08T04:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.77777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 58 + }, + "windSpeed": "24 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 37, + "name": "", + "startTime": "2026-02-08T04:00:00-05:00", + "endTime": "2026-02-08T05:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.77777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 58 + }, + "windSpeed": "24 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 38, + "name": "", + "startTime": "2026-02-08T05:00:00-05:00", + "endTime": "2026-02-08T06:00:00-05:00", + "isDaytime": false, + "temperature": -12, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.77777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 60 + }, + "windSpeed": "22 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 39, + "name": "", + "startTime": "2026-02-08T06:00:00-05:00", + "endTime": "2026-02-08T07:00:00-05:00", + "isDaytime": true, + "temperature": -12, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 57 + }, + "windSpeed": "22 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 40, + "name": "", + "startTime": "2026-02-08T07:00:00-05:00", + "endTime": "2026-02-08T08:00:00-05:00", + "isDaytime": true, + "temperature": -12, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -18.333333333333332 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 57 + }, + "windSpeed": "20 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 41, + "name": "", + "startTime": "2026-02-08T08:00:00-05:00", + "endTime": "2026-02-08T09:00:00-05:00", + "isDaytime": true, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.77777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 55 + }, + "windSpeed": "20 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 42, + "name": "", + "startTime": "2026-02-08T09:00:00-05:00", + "endTime": "2026-02-08T10:00:00-05:00", + "isDaytime": true, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -17.22222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 53 + }, + "windSpeed": "19 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 43, + "name": "", + "startTime": "2026-02-08T10:00:00-05:00", + "endTime": "2026-02-08T11:00:00-05:00", + "isDaytime": true, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -16.666666666666668 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 51 + }, + "windSpeed": "19 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 44, + "name": "", + "startTime": "2026-02-08T11:00:00-05:00", + "endTime": "2026-02-08T12:00:00-05:00", + "isDaytime": true, + "temperature": -7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -16.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "windSpeed": "19 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 45, + "name": "", + "startTime": "2026-02-08T12:00:00-05:00", + "endTime": "2026-02-08T13:00:00-05:00", + "isDaytime": true, + "temperature": -7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "windSpeed": "19 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 46, + "name": "", + "startTime": "2026-02-08T13:00:00-05:00", + "endTime": "2026-02-08T14:00:00-05:00", + "isDaytime": true, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 47 + }, + "windSpeed": "19 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 47, + "name": "", + "startTime": "2026-02-08T14:00:00-05:00", + "endTime": "2026-02-08T15:00:00-05:00", + "isDaytime": true, + "temperature": -5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 47 + }, + "windSpeed": "19 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 48, + "name": "", + "startTime": "2026-02-08T15:00:00-05:00", + "endTime": "2026-02-08T16:00:00-05:00", + "isDaytime": true, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 45 + }, + "windSpeed": "17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 49, + "name": "", + "startTime": "2026-02-08T16:00:00-05:00", + "endTime": "2026-02-08T17:00:00-05:00", + "isDaytime": true, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 47 + }, + "windSpeed": "15 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 50, + "name": "", + "startTime": "2026-02-08T17:00:00-05:00", + "endTime": "2026-02-08T18:00:00-05:00", + "isDaytime": true, + "temperature": -5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.333333333333334 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 52 + }, + "windSpeed": "13 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 51, + "name": "", + "startTime": "2026-02-08T18:00:00-05:00", + "endTime": "2026-02-08T19:00:00-05:00", + "isDaytime": false, + "temperature": -5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.333333333333334 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 52 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 52, + "name": "", + "startTime": "2026-02-08T19:00:00-05:00", + "endTime": "2026-02-08T20:00:00-05:00", + "isDaytime": false, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.333333333333334 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 54 + }, + "windSpeed": "7 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 53, + "name": "", + "startTime": "2026-02-08T20:00:00-05:00", + "endTime": "2026-02-08T21:00:00-05:00", + "isDaytime": false, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.333333333333334 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 56 + }, + "windSpeed": "7 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 54, + "name": "", + "startTime": "2026-02-08T21:00:00-05:00", + "endTime": "2026-02-08T22:00:00-05:00", + "isDaytime": false, + "temperature": -7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 59 + }, + "windSpeed": "7 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 55, + "name": "", + "startTime": "2026-02-08T22:00:00-05:00", + "endTime": "2026-02-08T23:00:00-05:00", + "isDaytime": false, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "7 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 56, + "name": "", + "startTime": "2026-02-08T23:00:00-05:00", + "endTime": "2026-02-09T00:00:00-05:00", + "isDaytime": false, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "7 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 57, + "name": "", + "startTime": "2026-02-09T00:00:00-05:00", + "endTime": "2026-02-09T01:00:00-05:00", + "isDaytime": false, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "6 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 58, + "name": "", + "startTime": "2026-02-09T01:00:00-05:00", + "endTime": "2026-02-09T02:00:00-05:00", + "isDaytime": false, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "6 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 59, + "name": "", + "startTime": "2026-02-09T02:00:00-05:00", + "endTime": "2026-02-09T03:00:00-05:00", + "isDaytime": false, + "temperature": -9, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 64 + }, + "windSpeed": "6 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 60, + "name": "", + "startTime": "2026-02-09T03:00:00-05:00", + "endTime": "2026-02-09T04:00:00-05:00", + "isDaytime": false, + "temperature": -10, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 67 + }, + "windSpeed": "6 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 61, + "name": "", + "startTime": "2026-02-09T04:00:00-05:00", + "endTime": "2026-02-09T05:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "4 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 62, + "name": "", + "startTime": "2026-02-09T05:00:00-05:00", + "endTime": "2026-02-09T06:00:00-05:00", + "isDaytime": false, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "4 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 63, + "name": "", + "startTime": "2026-02-09T06:00:00-05:00", + "endTime": "2026-02-09T07:00:00-05:00", + "isDaytime": true, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "4 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 64, + "name": "", + "startTime": "2026-02-09T07:00:00-05:00", + "endTime": "2026-02-09T08:00:00-05:00", + "isDaytime": true, + "temperature": -11, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "4 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 65, + "name": "", + "startTime": "2026-02-09T08:00:00-05:00", + "endTime": "2026-02-09T09:00:00-05:00", + "isDaytime": true, + "temperature": -10, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -15 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 67 + }, + "windSpeed": "4 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 66, + "name": "", + "startTime": "2026-02-09T09:00:00-05:00", + "endTime": "2026-02-09T10:00:00-05:00", + "isDaytime": true, + "temperature": -8, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 59 + }, + "windSpeed": "4 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 67, + "name": "", + "startTime": "2026-02-09T10:00:00-05:00", + "endTime": "2026-02-09T11:00:00-05:00", + "isDaytime": true, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -13.333333333333334 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 56 + }, + "windSpeed": "4 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 68, + "name": "", + "startTime": "2026-02-09T11:00:00-05:00", + "endTime": "2026-02-09T12:00:00-05:00", + "isDaytime": true, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -12.777777777777779 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 52 + }, + "windSpeed": "6 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 69, + "name": "", + "startTime": "2026-02-09T12:00:00-05:00", + "endTime": "2026-02-09T13:00:00-05:00", + "isDaytime": true, + "temperature": -3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -11.666666666666666 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "windSpeed": "7 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 70, + "name": "", + "startTime": "2026-02-09T13:00:00-05:00", + "endTime": "2026-02-09T14:00:00-05:00", + "isDaytime": true, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 48 + }, + "windSpeed": "7 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 71, + "name": "", + "startTime": "2026-02-09T14:00:00-05:00", + "endTime": "2026-02-09T15:00:00-05:00", + "isDaytime": true, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -10.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "windSpeed": "7 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 72, + "name": "", + "startTime": "2026-02-09T15:00:00-05:00", + "endTime": "2026-02-09T16:00:00-05:00", + "isDaytime": true, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -10 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "windSpeed": "6 km/h", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 73, + "name": "", + "startTime": "2026-02-09T16:00:00-05:00", + "endTime": "2026-02-09T17:00:00-05:00", + "isDaytime": true, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -10 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 47 + }, + "windSpeed": "6 km/h", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 74, + "name": "", + "startTime": "2026-02-09T17:00:00-05:00", + "endTime": "2026-02-09T18:00:00-05:00", + "isDaytime": true, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -10 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "windSpeed": "4 km/h", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 75, + "name": "", + "startTime": "2026-02-09T18:00:00-05:00", + "endTime": "2026-02-09T19:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -9.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 53 + }, + "windSpeed": "2 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 76, + "name": "", + "startTime": "2026-02-09T19:00:00-05:00", + "endTime": "2026-02-09T20:00:00-05:00", + "isDaytime": false, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -9.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 58 + }, + "windSpeed": "2 km/h", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 77, + "name": "", + "startTime": "2026-02-09T20:00:00-05:00", + "endTime": "2026-02-09T21:00:00-05:00", + "isDaytime": false, + "temperature": -3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -9.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 60 + }, + "windSpeed": "2 km/h", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 78, + "name": "", + "startTime": "2026-02-09T21:00:00-05:00", + "endTime": "2026-02-09T22:00:00-05:00", + "isDaytime": false, + "temperature": -3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 65 + }, + "windSpeed": "2 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 79, + "name": "", + "startTime": "2026-02-09T22:00:00-05:00", + "endTime": "2026-02-09T23:00:00-05:00", + "isDaytime": false, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 68 + }, + "windSpeed": "2 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 80, + "name": "", + "startTime": "2026-02-09T23:00:00-05:00", + "endTime": "2026-02-10T00:00:00-05:00", + "isDaytime": false, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 71 + }, + "windSpeed": "2 km/h", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 81, + "name": "", + "startTime": "2026-02-10T00:00:00-05:00", + "endTime": "2026-02-10T01:00:00-05:00", + "isDaytime": false, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 71 + }, + "windSpeed": "2 km/h", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 82, + "name": "", + "startTime": "2026-02-10T01:00:00-05:00", + "endTime": "2026-02-10T02:00:00-05:00", + "isDaytime": false, + "temperature": -5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 74 + }, + "windSpeed": "2 km/h", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 83, + "name": "", + "startTime": "2026-02-10T02:00:00-05:00", + "endTime": "2026-02-10T03:00:00-05:00", + "isDaytime": false, + "temperature": -5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 74 + }, + "windSpeed": "2 km/h", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 84, + "name": "", + "startTime": "2026-02-10T03:00:00-05:00", + "endTime": "2026-02-10T04:00:00-05:00", + "isDaytime": false, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 77 + }, + "windSpeed": "2 km/h", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 85, + "name": "", + "startTime": "2026-02-10T04:00:00-05:00", + "endTime": "2026-02-10T05:00:00-05:00", + "isDaytime": false, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 77 + }, + "windSpeed": "2 km/h", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 86, + "name": "", + "startTime": "2026-02-10T05:00:00-05:00", + "endTime": "2026-02-10T06:00:00-05:00", + "isDaytime": false, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 77 + }, + "windSpeed": "2 km/h", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 87, + "name": "", + "startTime": "2026-02-10T06:00:00-05:00", + "endTime": "2026-02-10T07:00:00-05:00", + "isDaytime": true, + "temperature": -6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 77 + }, + "windSpeed": "2 km/h", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 88, + "name": "", + "startTime": "2026-02-10T07:00:00-05:00", + "endTime": "2026-02-10T08:00:00-05:00", + "isDaytime": true, + "temperature": -5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -8.333333333333334 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 77 + }, + "windSpeed": "2 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 89, + "name": "", + "startTime": "2026-02-10T08:00:00-05:00", + "endTime": "2026-02-10T09:00:00-05:00", + "isDaytime": true, + "temperature": -4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -7.777777777777778 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 74 + }, + "windSpeed": "2 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 90, + "name": "", + "startTime": "2026-02-10T09:00:00-05:00", + "endTime": "2026-02-10T10:00:00-05:00", + "isDaytime": true, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -6.666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "2 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 91, + "name": "", + "startTime": "2026-02-10T10:00:00-05:00", + "endTime": "2026-02-10T11:00:00-05:00", + "isDaytime": true, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -5.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 63 + }, + "windSpeed": "4 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 92, + "name": "", + "startTime": "2026-02-10T11:00:00-05:00", + "endTime": "2026-02-10T12:00:00-05:00", + "isDaytime": true, + "temperature": 2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -4.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "4 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 93, + "name": "", + "startTime": "2026-02-10T12:00:00-05:00", + "endTime": "2026-02-10T13:00:00-05:00", + "isDaytime": true, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.888888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 57 + }, + "windSpeed": "6 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 94, + "name": "", + "startTime": "2026-02-10T13:00:00-05:00", + "endTime": "2026-02-10T14:00:00-05:00", + "isDaytime": true, + "temperature": 5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.3333333333333335 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 55 + }, + "windSpeed": "6 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 95, + "name": "", + "startTime": "2026-02-10T14:00:00-05:00", + "endTime": "2026-02-10T15:00:00-05:00", + "isDaytime": true, + "temperature": 6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 55 + }, + "windSpeed": "6 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 96, + "name": "", + "startTime": "2026-02-10T15:00:00-05:00", + "endTime": "2026-02-10T16:00:00-05:00", + "isDaytime": true, + "temperature": 6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 55 + }, + "windSpeed": "6 km/h", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/day/few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 97, + "name": "", + "startTime": "2026-02-10T16:00:00-05:00", + "endTime": "2026-02-10T17:00:00-05:00", + "isDaytime": true, + "temperature": 6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 55 + }, + "windSpeed": "4 km/h", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/day/few?size=small", + "shortForecast": "Sunny", + "detailedForecast": "" + }, + { + "number": 98, + "name": "", + "startTime": "2026-02-10T17:00:00-05:00", + "endTime": "2026-02-10T18:00:00-05:00", + "isDaytime": true, + "temperature": 6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 57 + }, + "windSpeed": "4 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 99, + "name": "", + "startTime": "2026-02-10T18:00:00-05:00", + "endTime": "2026-02-10T19:00:00-05:00", + "isDaytime": false, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 59 + }, + "windSpeed": "4 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 100, + "name": "", + "startTime": "2026-02-10T19:00:00-05:00", + "endTime": "2026-02-10T20:00:00-05:00", + "isDaytime": false, + "temperature": 3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 6 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 67 + }, + "windSpeed": "4 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 101, + "name": "", + "startTime": "2026-02-10T20:00:00-05:00", + "endTime": "2026-02-10T21:00:00-05:00", + "isDaytime": false, + "temperature": 2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 6 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "2 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 102, + "name": "", + "startTime": "2026-02-10T21:00:00-05:00", + "endTime": "2026-02-10T22:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 6 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "4 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 103, + "name": "", + "startTime": "2026-02-10T22:00:00-05:00", + "endTime": "2026-02-10T23:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 6 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "4 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 104, + "name": "", + "startTime": "2026-02-10T23:00:00-05:00", + "endTime": "2026-02-11T00:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 6 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "4 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 105, + "name": "", + "startTime": "2026-02-11T00:00:00-05:00", + "endTime": "2026-02-11T01:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 6 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "2 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 106, + "name": "", + "startTime": "2026-02-11T01:00:00-05:00", + "endTime": "2026-02-11T02:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 18 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "4 km/h", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 107, + "name": "", + "startTime": "2026-02-11T02:00:00-05:00", + "endTime": "2026-02-11T03:00:00-05:00", + "isDaytime": false, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 18 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 81 + }, + "windSpeed": "4 km/h", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 108, + "name": "", + "startTime": "2026-02-11T03:00:00-05:00", + "endTime": "2026-02-11T04:00:00-05:00", + "isDaytime": false, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 18 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "4 km/h", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 109, + "name": "", + "startTime": "2026-02-11T04:00:00-05:00", + "endTime": "2026-02-11T05:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 18 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "4 km/h", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 110, + "name": "", + "startTime": "2026-02-11T05:00:00-05:00", + "endTime": "2026-02-11T06:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 18 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "4 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 111, + "name": "", + "startTime": "2026-02-11T06:00:00-05:00", + "endTime": "2026-02-11T07:00:00-05:00", + "isDaytime": true, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 18 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "4 km/h", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 112, + "name": "", + "startTime": "2026-02-11T07:00:00-05:00", + "endTime": "2026-02-11T08:00:00-05:00", + "isDaytime": true, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -1.6666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "4 km/h", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 113, + "name": "", + "startTime": "2026-02-11T08:00:00-05:00", + "endTime": "2026-02-11T09:00:00-05:00", + "isDaytime": true, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -1.1111111111111112 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "6 km/h", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 114, + "name": "", + "startTime": "2026-02-11T09:00:00-05:00", + "endTime": "2026-02-11T10:00:00-05:00", + "isDaytime": true, + "temperature": 2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 0 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "6 km/h", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 115, + "name": "", + "startTime": "2026-02-11T10:00:00-05:00", + "endTime": "2026-02-11T11:00:00-05:00", + "isDaytime": true, + "temperature": 3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 0.5555555555555556 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 82 + }, + "windSpeed": "7 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 116, + "name": "", + "startTime": "2026-02-11T11:00:00-05:00", + "endTime": "2026-02-11T12:00:00-05:00", + "isDaytime": true, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1.1111111111111112 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 79 + }, + "windSpeed": "7 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 117, + "name": "", + "startTime": "2026-02-11T12:00:00-05:00", + "endTime": "2026-02-11T13:00:00-05:00", + "isDaytime": true, + "temperature": 5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 49 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1.1111111111111112 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 76 + }, + "windSpeed": "9 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 118, + "name": "", + "startTime": "2026-02-11T13:00:00-05:00", + "endTime": "2026-02-11T14:00:00-05:00", + "isDaytime": true, + "temperature": 6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1.1111111111111112 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "9 km/h", + "windDirection": "W", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 119, + "name": "", + "startTime": "2026-02-11T14:00:00-05:00", + "endTime": "2026-02-11T15:00:00-05:00", + "isDaytime": true, + "temperature": 7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1.1111111111111112 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 68 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 120, + "name": "", + "startTime": "2026-02-11T15:00:00-05:00", + "endTime": "2026-02-11T16:00:00-05:00", + "isDaytime": true, + "temperature": 7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1.6666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 121, + "name": "", + "startTime": "2026-02-11T16:00:00-05:00", + "endTime": "2026-02-11T17:00:00-05:00", + "isDaytime": true, + "temperature": 7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1.6666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 122, + "name": "", + "startTime": "2026-02-11T17:00:00-05:00", + "endTime": "2026-02-11T18:00:00-05:00", + "isDaytime": true, + "temperature": 7, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1.6666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 123, + "name": "", + "startTime": "2026-02-11T18:00:00-05:00", + "endTime": "2026-02-11T19:00:00-05:00", + "isDaytime": false, + "temperature": 6, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1.1111111111111112 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 73 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,50?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 124, + "name": "", + "startTime": "2026-02-11T19:00:00-05:00", + "endTime": "2026-02-11T20:00:00-05:00", + "isDaytime": false, + "temperature": 5, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 0.5555555555555556 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 73 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 125, + "name": "", + "startTime": "2026-02-11T20:00:00-05:00", + "endTime": "2026-02-11T21:00:00-05:00", + "isDaytime": false, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 0 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 73 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 126, + "name": "", + "startTime": "2026-02-11T21:00:00-05:00", + "endTime": "2026-02-11T22:00:00-05:00", + "isDaytime": false, + "temperature": 3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -0.5555555555555556 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 76 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 127, + "name": "", + "startTime": "2026-02-11T22:00:00-05:00", + "endTime": "2026-02-11T23:00:00-05:00", + "isDaytime": false, + "temperature": 3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -1.1111111111111112 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 128, + "name": "", + "startTime": "2026-02-11T23:00:00-05:00", + "endTime": "2026-02-12T00:00:00-05:00", + "isDaytime": false, + "temperature": 2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -1.6666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 129, + "name": "", + "startTime": "2026-02-12T00:00:00-05:00", + "endTime": "2026-02-12T01:00:00-05:00", + "isDaytime": false, + "temperature": 2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -1.6666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 130, + "name": "", + "startTime": "2026-02-12T01:00:00-05:00", + "endTime": "2026-02-12T02:00:00-05:00", + "isDaytime": false, + "temperature": 2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 131, + "name": "", + "startTime": "2026-02-12T02:00:00-05:00", + "endTime": "2026-02-12T03:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.2222222222222223 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 132, + "name": "", + "startTime": "2026-02-12T03:00:00-05:00", + "endTime": "2026-02-12T04:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 133, + "name": "", + "startTime": "2026-02-12T04:00:00-05:00", + "endTime": "2026-02-12T05:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 134, + "name": "", + "startTime": "2026-02-12T05:00:00-05:00", + "endTime": "2026-02-12T06:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -2.7777777777777777 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 135, + "name": "", + "startTime": "2026-02-12T06:00:00-05:00", + "endTime": "2026-02-12T07:00:00-05:00", + "isDaytime": true, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.3333333333333335 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,30?size=small", + "shortForecast": "Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 136, + "name": "", + "startTime": "2026-02-12T07:00:00-05:00", + "endTime": "2026-02-12T08:00:00-05:00", + "isDaytime": true, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.3333333333333335 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 78 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 137, + "name": "", + "startTime": "2026-02-12T08:00:00-05:00", + "endTime": "2026-02-12T09:00:00-05:00", + "isDaytime": true, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.3333333333333335 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "13 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 138, + "name": "", + "startTime": "2026-02-12T09:00:00-05:00", + "endTime": "2026-02-12T10:00:00-05:00", + "isDaytime": true, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.3333333333333335 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 72 + }, + "windSpeed": "15 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 139, + "name": "", + "startTime": "2026-02-12T10:00:00-05:00", + "endTime": "2026-02-12T11:00:00-05:00", + "isDaytime": true, + "temperature": 2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.3333333333333335 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 67 + }, + "windSpeed": "17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 140, + "name": "", + "startTime": "2026-02-12T11:00:00-05:00", + "endTime": "2026-02-12T12:00:00-05:00", + "isDaytime": true, + "temperature": 3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.3333333333333335 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 64 + }, + "windSpeed": "17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 141, + "name": "", + "startTime": "2026-02-12T12:00:00-05:00", + "endTime": "2026-02-12T13:00:00-05:00", + "isDaytime": true, + "temperature": 3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.888888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 59 + }, + "windSpeed": "17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small", + "shortForecast": "Slight Chance Light Rain", + "detailedForecast": "" + }, + { + "number": 142, + "name": "", + "startTime": "2026-02-12T13:00:00-05:00", + "endTime": "2026-02-12T14:00:00-05:00", + "isDaytime": true, + "temperature": 3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 14 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -3.888888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 59 + }, + "windSpeed": "17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 143, + "name": "", + "startTime": "2026-02-12T14:00:00-05:00", + "endTime": "2026-02-12T15:00:00-05:00", + "isDaytime": true, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 14 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -4.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 54 + }, + "windSpeed": "17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 144, + "name": "", + "startTime": "2026-02-12T15:00:00-05:00", + "endTime": "2026-02-12T16:00:00-05:00", + "isDaytime": true, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 14 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -4.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 52 + }, + "windSpeed": "17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 145, + "name": "", + "startTime": "2026-02-12T16:00:00-05:00", + "endTime": "2026-02-12T17:00:00-05:00", + "isDaytime": true, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 14 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -5 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 50 + }, + "windSpeed": "17 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 146, + "name": "", + "startTime": "2026-02-12T17:00:00-05:00", + "endTime": "2026-02-12T18:00:00-05:00", + "isDaytime": true, + "temperature": 4, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 14 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -5 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 52 + }, + "windSpeed": "15 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 147, + "name": "", + "startTime": "2026-02-12T18:00:00-05:00", + "endTime": "2026-02-12T19:00:00-05:00", + "isDaytime": false, + "temperature": 3, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 14 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -5.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 54 + }, + "windSpeed": "13 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 148, + "name": "", + "startTime": "2026-02-12T19:00:00-05:00", + "endTime": "2026-02-12T20:00:00-05:00", + "isDaytime": false, + "temperature": 2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 16 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -5.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 59 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 149, + "name": "", + "startTime": "2026-02-12T20:00:00-05:00", + "endTime": "2026-02-12T21:00:00-05:00", + "isDaytime": false, + "temperature": 1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 16 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -5.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 150, + "name": "", + "startTime": "2026-02-12T21:00:00-05:00", + "endTime": "2026-02-12T22:00:00-05:00", + "isDaytime": false, + "temperature": 0, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 16 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -6.111111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 63 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 151, + "name": "", + "startTime": "2026-02-12T22:00:00-05:00", + "endTime": "2026-02-12T23:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 16 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -6.111111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 66 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 152, + "name": "", + "startTime": "2026-02-12T23:00:00-05:00", + "endTime": "2026-02-13T00:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 16 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -6.111111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 153, + "name": "", + "startTime": "2026-02-13T00:00:00-05:00", + "endTime": "2026-02-13T01:00:00-05:00", + "isDaytime": false, + "temperature": -1, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 16 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -6.666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 66 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 154, + "name": "", + "startTime": "2026-02-13T01:00:00-05:00", + "endTime": "2026-02-13T02:00:00-05:00", + "isDaytime": false, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -6.666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "9 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 155, + "name": "", + "startTime": "2026-02-13T02:00:00-05:00", + "endTime": "2026-02-13T03:00:00-05:00", + "isDaytime": false, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -6.666666666666667 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 71 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + }, + { + "number": 156, + "name": "", + "startTime": "2026-02-13T03:00:00-05:00", + "endTime": "2026-02-13T04:00:00-05:00", + "isDaytime": false, + "temperature": -2, + "temperatureUnit": "C", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": -7.222222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 68 + }, + "windSpeed": "11 km/h", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small", + "shortForecast": "Slight Chance Light Snow", + "detailedForecast": "" + } + ] + } +} diff --git a/tests/mocks/weather_weathergov_points.json b/tests/mocks/weather_weathergov_points.json new file mode 100644 index 0000000000..d13794899f --- /dev/null +++ b/tests/mocks/weather_weathergov_points.json @@ -0,0 +1,89 @@ +{ + "@context": [ + "https://geojson.org/geojson-ld/geojson-context.jsonld", + { + "@version": "1.1", + "wx": "https://api.weather.gov/ontology#", + "s": "https://schema.org/", + "geo": "http://www.opengis.net/ont/geosparql#", + "unit": "http://codes.wmo.int/common/unit/", + "@vocab": "https://api.weather.gov/ontology#", + "geometry": { + "@id": "s:GeoCoordinates", + "@type": "geo:wktLiteral" + }, + "city": "s:addressLocality", + "state": "s:addressRegion", + "distance": { + "@id": "s:Distance", + "@type": "s:QuantitativeValue" + }, + "bearing": { + "@type": "s:QuantitativeValue" + }, + "value": { + "@id": "s:value" + }, + "unitCode": { + "@id": "s:unitCode", + "@type": "@id" + }, + "forecastOffice": { + "@type": "@id" + }, + "forecastGridData": { + "@type": "@id" + }, + "publicZone": { + "@type": "@id" + }, + "county": { + "@type": "@id" + } + } + ], + "id": "https://api.weather.gov/points/38.8894,-77.0352", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.0352, 38.8894] + }, + "properties": { + "@id": "https://api.weather.gov/points/38.8894,-77.0352", + "@type": "wx:Point", + "cwa": "LWX", + "type": "land", + "forecastOffice": "https://api.weather.gov/offices/LWX", + "gridId": "LWX", + "gridX": 97, + "gridY": 71, + "forecast": "https://api.weather.gov/gridpoints/LWX/97,71/forecast", + "forecastHourly": "https://api.weather.gov/gridpoints/LWX/97,71/forecast/hourly", + "forecastGridData": "https://api.weather.gov/gridpoints/LWX/97,71", + "observationStations": "https://api.weather.gov/gridpoints/LWX/97,71/stations", + "relativeLocation": { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.017229, 38.904103] + }, + "properties": { + "city": "Washington", + "state": "DC", + "distance": { + "unitCode": "wmoUnit:m", + "value": 2256.4628420106 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 223 + } + } + }, + "forecastZone": "https://api.weather.gov/zones/forecast/DCZ001", + "county": "https://api.weather.gov/zones/county/DCC001", + "fireWeatherZone": "https://api.weather.gov/zones/fire/DCZ001", + "timeZone": "America/New_York", + "radarStation": "KLWX" + } +} diff --git a/tests/mocks/weather_weathergov_stations.json b/tests/mocks/weather_weathergov_stations.json new file mode 100644 index 0000000000..742524a693 --- /dev/null +++ b/tests/mocks/weather_weathergov_stations.json @@ -0,0 +1,1793 @@ +{ + "@context": [ + "https://geojson.org/geojson-ld/geojson-context.jsonld", + { + "@version": "1.1", + "wx": "https://api.weather.gov/ontology#", + "s": "https://schema.org/", + "geo": "http://www.opengis.net/ont/geosparql#", + "unit": "http://codes.wmo.int/common/unit/", + "@vocab": "https://api.weather.gov/ontology#", + "geometry": { + "@id": "s:GeoCoordinates", + "@type": "geo:wktLiteral" + }, + "city": "s:addressLocality", + "state": "s:addressRegion", + "distance": { + "@id": "s:Distance", + "@type": "s:QuantitativeValue" + }, + "bearing": { + "@type": "s:QuantitativeValue" + }, + "value": { + "@id": "s:value" + }, + "unitCode": { + "@id": "s:unitCode", + "@type": "@id" + }, + "forecastOffice": { + "@type": "@id" + }, + "forecastGridData": { + "@type": "@id" + }, + "publicZone": { + "@type": "@id" + }, + "county": { + "@type": "@id" + }, + "observationStations": { + "@container": "@list", + "@type": "@id" + } + } + ], + "type": "FeatureCollection", + "features": [ + { + "id": "https://api.weather.gov/stations/KDCA", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.03417, 38.84833] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KDCA", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 3.9624 + }, + "stationIdentifier": "KDCA", + "name": "Washington/Reagan National Airport, DC", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 3043.6748842539 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 140 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ054", + "county": "https://api.weather.gov/zones/county/VAC013", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ054" + } + }, + { + "id": "https://api.weather.gov/stations/KCGS", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.9223, 38.9806] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KCGS", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 14.9352 + }, + "stationIdentifier": "KCGS", + "name": "College Park Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 16980.874107362 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 43 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ013", + "county": "https://api.weather.gov/zones/county/MDC033", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ013" + } + }, + { + "id": "https://api.weather.gov/stations/KADW", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.85, 38.81667] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KADW", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 85.9536 + }, + "stationIdentifier": "KADW", + "name": "Camp Springs / Andrews Air Force Base", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 18837.139622535 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 108 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ013", + "county": "https://api.weather.gov/zones/county/MDC033", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ013" + } + }, + { + "id": "https://api.weather.gov/stations/KDAA", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.18333, 38.71667] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KDAA", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 21.0312 + }, + "stationIdentifier": "KDAA", + "name": "Fort Belvoir", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 20211.268967046 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 212 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ053", + "county": "https://api.weather.gov/zones/county/VAC059", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ053" + } + }, + { + "id": "https://api.weather.gov/stations/KFME", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.76667, 39.08333] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KFME", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 46.0248 + }, + "stationIdentifier": "KFME", + "name": "Fort Meade / Tipton", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 34568.722953871 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 46 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ014", + "county": "https://api.weather.gov/zones/county/MDC003", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ014" + } + }, + { + "id": "https://api.weather.gov/stations/KIAD", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.4475, 38.93472] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KIAD", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 95.0976 + }, + "stationIdentifier": "KIAD", + "name": "Washington/Dulles International Airport, DC", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 34587.939860418 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 282 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ053", + "county": "https://api.weather.gov/zones/county/VAC059", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ053" + } + }, + { + "id": "https://api.weather.gov/stations/KGAI", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.16551, 39.16957] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KGAI", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 150.876 + }, + "stationIdentifier": "KGAI", + "name": "Gaithersburg - Montgomery County Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 34683.691088332 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 344 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ504", + "county": "https://api.weather.gov/zones/county/MDC031", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ504" + } + }, + { + "id": "https://api.weather.gov/stations/KHEF", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.51667, 38.71667] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KHEF", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 59.1312 + }, + "stationIdentifier": "KHEF", + "name": "Manassas, Manassas Regional Airport/Harry P. Davis Field", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 43324.86402354 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 247 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ527", + "county": "https://api.weather.gov/zones/county/VAC683", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ527" + } + }, + { + "id": "https://api.weather.gov/stations/KNYG", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.30129, 38.50326] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KNYG", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 2.1336 + }, + "stationIdentifier": "KNYG", + "name": "Quantico Marine Corps Airfield - Turner Field", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 45906.349012092 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 207 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ527", + "county": "https://api.weather.gov/zones/county/VAC153", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ527" + } + }, + { + "id": "https://api.weather.gov/stations/KBWI", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.68404, 39.17329] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KBWI", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 41.148 + }, + "stationIdentifier": "KBWI", + "name": "Baltimore, Baltimore-Washington International Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 46680.187081868 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 43 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ014", + "county": "https://api.weather.gov/zones/county/MDC003", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ014" + } + }, + { + "id": "https://api.weather.gov/stations/KJYO", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.56667, 39.08333] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KJYO", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 118.872 + }, + "stationIdentifier": "KJYO", + "name": "Leesburg / Godfrey", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 50093.979211268 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 298 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ506", + "county": "https://api.weather.gov/zones/county/VAC107", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ506" + } + }, + { + "id": "https://api.weather.gov/stations/KNAK", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.48907, 38.99125] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KNAK", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 0.9144 + }, + "stationIdentifier": "KNAK", + "name": "Annapolis, United States Naval Academy", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 50940.029746488 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 74 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ014", + "county": "https://api.weather.gov/zones/county/MDC003", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ014" + } + }, + { + "id": "https://api.weather.gov/stations/KDMH", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.61667, 39.28333] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KDMH", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 6.096 + }, + "stationIdentifier": "KDMH", + "name": "Baltimore, Inner Harbor", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 59684.848549395 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 39 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ011", + "county": "https://api.weather.gov/zones/county/MDC510", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ011" + } + }, + { + "id": "https://api.weather.gov/stations/KRMN", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.45528, 38.39806] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KRMN", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 64.9224 + }, + "stationIdentifier": "KRMN", + "name": "Stafford, Stafford Regional Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 62803.929543738 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 213 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ055", + "county": "https://api.weather.gov/zones/county/VAC179", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ055" + } + }, + { + "id": "https://api.weather.gov/stations/KW29", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.33, 38.9767] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KW29", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 14.9352 + }, + "stationIdentifier": "KW29", + "name": "Bay Bridge Field", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 63992.315724071 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 79 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ015", + "county": "https://api.weather.gov/zones/county/MDC035", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ015" + } + }, + { + "id": "https://api.weather.gov/stations/KHWY", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.71501, 38.58765] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KHWY", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 92.0496 + }, + "stationIdentifier": "KHWY", + "name": "Warrenton-Fauquier Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 65127.84173743 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 241 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ502", + "county": "https://api.weather.gov/zones/county/VAC061", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ502" + } + }, + { + "id": "https://api.weather.gov/stations/KFDK", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.36982, 39.41775] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KFDK", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 81.9912 + }, + "stationIdentifier": "KFDK", + "name": "Frederick Municipal Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 66692.582365459 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 336 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ004", + "county": "https://api.weather.gov/zones/county/MDC021", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ004" + } + }, + { + "id": "https://api.weather.gov/stations/KEZF", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.45, 38.26667] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KEZF", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 25.908 + }, + "stationIdentifier": "KEZF", + "name": "Fredericksburg, Shannon Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 75229.907706335 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 207 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ056", + "county": "https://api.weather.gov/zones/county/VAC177", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ056" + } + }, + { + "id": "https://api.weather.gov/stations/KMTN", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.41667, 39.33333] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KMTN", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 7.0104 + }, + "stationIdentifier": "KMTN", + "name": "Baltimore / Martin", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 75581.565023524 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 46 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ011", + "county": "https://api.weather.gov/zones/county/MDC005", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ011" + } + }, + { + "id": "https://api.weather.gov/stations/K2W6", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.5501, 38.3154] + }, + "properties": { + "@id": "https://api.weather.gov/stations/K2W6", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 43.8912 + }, + "stationIdentifier": "K2W6", + "name": "St Marys County Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 75712.983389938 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 144 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ017", + "county": "https://api.weather.gov/zones/county/MDC037", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ017" + } + }, + { + "id": "https://api.weather.gov/stations/KCJR", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.85738, 38.52607] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KCJR", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 89.916 + }, + "stationIdentifier": "KCJR", + "name": "Culpeper Regional Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 79274.931842245 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 241 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ051", + "county": "https://api.weather.gov/zones/county/VAC047", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ051" + } + }, + { + "id": "https://api.weather.gov/stations/KDMW", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.0077, 39.6083] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KDMW", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 240.4872 + }, + "stationIdentifier": "KDMW", + "name": "Carroll County Regional Jack B Poage Field", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 82279.382252508 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 2 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ005", + "county": "https://api.weather.gov/zones/county/MDC013", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ005" + } + }, + { + "id": "https://api.weather.gov/stations/KESN", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.06667, 38.8] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KESN", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 21.9456 + }, + "stationIdentifier": "KESN", + "name": "Easton Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 86100.892604455 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 94 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ019", + "county": "https://api.weather.gov/zones/county/MDC041", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ019" + } + }, + { + "id": "https://api.weather.gov/stations/KNHK", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.41389, 38.27861] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KNHK", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 11.8872 + }, + "stationIdentifier": "KNHK", + "name": "Patuxent River, Naval Air Station", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 86239.928763087 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 139 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ017", + "county": "https://api.weather.gov/zones/county/MDC037", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ017" + } + }, + { + "id": "https://api.weather.gov/stations/KRSP", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.468, 39.645] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KRSP", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 561.1368 + }, + "stationIdentifier": "KRSP", + "name": "Camp David", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 93237.282967055 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 337 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ004", + "county": "https://api.weather.gov/zones/county/MDC021", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ004" + } + }, + { + "id": "https://api.weather.gov/stations/KNUI", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.42, 38.14889] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KNUI", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 6.096 + }, + "stationIdentifier": "KNUI", + "name": "St. Inigoes, Webster Field, Naval Electronic Systems Engineering Activity", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 97399.572233461 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 145 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ017", + "county": "https://api.weather.gov/zones/county/MDC037", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ017" + } + }, + { + "id": "https://api.weather.gov/stations/KMRB", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.975, 39.40372] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KMRB", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 163.9824 + }, + "stationIdentifier": "KMRB", + "name": "Eastern WV Regional Airport/Shepherd Field", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 99011.527250549 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 307 + }, + "forecast": "https://api.weather.gov/zones/forecast/WVZ052", + "county": "https://api.weather.gov/zones/county/WVC003", + "fireWeatherZone": "https://api.weather.gov/zones/fire/WVZ052" + } + }, + { + "id": "https://api.weather.gov/stations/KOKV", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.15, 39.15] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KOKV", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 221.8944 + }, + "stationIdentifier": "KOKV", + "name": "Winchester Regional", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 99483.258804184 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 288 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ028", + "county": "https://api.weather.gov/zones/county/VAC069", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ028" + } + }, + { + "id": "https://api.weather.gov/stations/KAPG", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.16667, 39.46667] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KAPG", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 17.9832 + }, + "stationIdentifier": "KAPG", + "name": "Phillips Army Air Field / Aberdeen", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 101486.28902381 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 48 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ508", + "county": "https://api.weather.gov/zones/county/MDC025", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ508" + } + }, + { + "id": "https://api.weather.gov/stations/KFRR", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.2535, 38.9175] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KFRR", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 216.1032 + }, + "stationIdentifier": "KFRR", + "name": "Front Royal-warren County Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 103711.79430435 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 273 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ030", + "county": "https://api.weather.gov/zones/county/VAC187", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ030" + } + }, + { + "id": "https://api.weather.gov/stations/K0W3", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.20297, 39.5682] + }, + "properties": { + "@id": "https://api.weather.gov/stations/K0W3", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 125.5776 + }, + "stationIdentifier": "K0W3", + "name": "Harford County Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 106997.11216766 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 43 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ508", + "county": "https://api.weather.gov/zones/county/MDC025", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ508" + } + }, + { + "id": "https://api.weather.gov/stations/KHGR", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.73, 39.70583] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KHGR", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 213.9696 + }, + "stationIdentifier": "KHGR", + "name": "Hagerstown, Washington County Regional Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 109586.26730048 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 328 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ003", + "county": "https://api.weather.gov/zones/county/MDC043", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ003" + } + }, + { + "id": "https://api.weather.gov/stations/KOMH", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.04556, 38.24722] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KOMH", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 142.0368 + }, + "stationIdentifier": "KOMH", + "name": "Orange, Orange County Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 110351.40846398 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 231 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ050", + "county": "https://api.weather.gov/zones/county/VAC137", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ050" + } + }, + { + "id": "https://api.weather.gov/stations/K7W4", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.7459, 37.9658] + }, + "properties": { + "@id": "https://api.weather.gov/stations/K7W4", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 106.9848 + }, + "stationIdentifier": "K7W4", + "name": "Lake Anna Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 117039.9799578 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 211 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ510", + "county": "https://api.weather.gov/zones/county/VAC109", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ510" + } + }, + { + "id": "https://api.weather.gov/stations/KTHV", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.87694, 39.91944] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KTHV", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 145.9992 + }, + "stationIdentifier": "KTHV", + "name": "York, York Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 117785.75882145 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 7 + }, + "forecast": "https://api.weather.gov/zones/forecast/PAZ065", + "county": "https://api.weather.gov/zones/county/PAC133", + "fireWeatherZone": "https://api.weather.gov/zones/fire/PAZ065" + } + }, + { + "id": "https://api.weather.gov/stations/KLKU", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.97028, 38.00972] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KLKU", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 149.9616 + }, + "stationIdentifier": "KLKU", + "name": "Louisa, Louisa County Airport/Freeman Field", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 124364.21495608 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 220 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ510", + "county": "https://api.weather.gov/zones/county/VAC109", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ510" + } + }, + { + "id": "https://api.weather.gov/stations/KGVE", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.1658, 38.156] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KGVE", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 138.0744 + }, + "stationIdentifier": "KGVE", + "name": "Gordonsville Municipal Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 124909.61245374 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 230 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ050", + "county": "https://api.weather.gov/zones/county/VAC137", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ050" + } + }, + { + "id": "https://api.weather.gov/stations/KOFP", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.43444, 37.70806] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KOFP", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 61.8744 + }, + "stationIdentifier": "KOFP", + "name": "Ashland, Hanover County Municipal Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 133267.46930022 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 194 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ511", + "county": "https://api.weather.gov/zones/county/VAC085", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ511" + } + }, + { + "id": "https://api.weather.gov/stations/K8W2", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.7081, 38.6557] + }, + "properties": { + "@id": "https://api.weather.gov/stations/K8W2", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 297.18 + }, + "stationIdentifier": "K8W2", + "name": "New Market Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 145135.20416818 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 261 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ027", + "county": "https://api.weather.gov/zones/county/VAC171", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ027" + } + }, + { + "id": "https://api.weather.gov/stations/KCHO", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.45516, 38.13738] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KCHO", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 195.072 + }, + "stationIdentifier": "KCHO", + "name": "Charlottesville-Albemarle Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 146394.21605562 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 236 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ037", + "county": "https://api.weather.gov/zones/county/VAC003", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ037" + } + }, + { + "id": "https://api.weather.gov/stations/KRIC", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-77.32333, 37.51111] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KRIC", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 50.9016 + }, + "stationIdentifier": "KRIC", + "name": "Richmond, Richmond International Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 152812.69388052 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 188 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ516", + "county": "https://api.weather.gov/zones/county/VAC087", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ516" + } + }, + { + "id": "https://api.weather.gov/stations/KILG", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-75.60567, 39.67442] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KILG", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 21.9456 + }, + "stationIdentifier": "KILG", + "name": "Wilmington Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 153674.36438971 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 53 + }, + "forecast": "https://api.weather.gov/zones/forecast/DEZ001", + "county": "https://api.weather.gov/zones/county/DEC003", + "fireWeatherZone": "https://api.weather.gov/zones/fire/DEZ001" + } + }, + { + "id": "https://api.weather.gov/stations/KLNS", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-76.29446, 40.12058] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KLNS", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 121.0056 + }, + "stationIdentifier": "KLNS", + "name": "Lancaster, Lancaster Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 153739.95516367 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 24 + }, + "forecast": "https://api.weather.gov/zones/forecast/PAZ066", + "county": "https://api.weather.gov/zones/county/PAC071", + "fireWeatherZone": "https://api.weather.gov/zones/fire/PAZ066" + } + }, + { + "id": "https://api.weather.gov/stations/KCBE", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.76083, 39.61528] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KCBE", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 235.9152 + }, + "stationIdentifier": "KCBE", + "name": "Cumberland, Greater Cumberland Regional Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 168568.42779476 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 300 + }, + "forecast": "https://api.weather.gov/zones/forecast/WVZ504", + "county": "https://api.weather.gov/zones/county/WVC057", + "fireWeatherZone": "https://api.weather.gov/zones/fire/WVZ504" + } + }, + { + "id": "https://api.weather.gov/stations/KSHD", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.9, 38.26667] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KSHD", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 366.0648 + }, + "stationIdentifier": "KSHD", + "name": "Staunton / Shenandoah", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 173695.8603158 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 247 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ025", + "county": "https://api.weather.gov/zones/county/VAC015", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ025" + } + }, + { + "id": "https://api.weather.gov/stations/KVBW", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.96033, 38.36674] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KVBW", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 355.092 + }, + "stationIdentifier": "KVBW", + "name": "Bridgewater Air Park", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 174565.90990218 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 251 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ026", + "county": "https://api.weather.gov/zones/county/VAC165", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ026" + } + }, + { + "id": "https://api.weather.gov/stations/KMFV", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-75.76667, 37.65] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KMFV", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 14.9352 + }, + "stationIdentifier": "KMFV", + "name": "Melfa / Accomack Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 176261.84200174 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 139 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ099", + "county": "https://api.weather.gov/zones/county/VAC001", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ099" + } + }, + { + "id": "https://api.weather.gov/stations/KW13", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.9444, 38.0769] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KW13", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 437.9976 + }, + "stationIdentifier": "KW13", + "name": "Eagles Nest Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 186456.91815645 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 242 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ025", + "county": "https://api.weather.gov/zones/county/VAC015", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ025" + } + }, + { + "id": "https://api.weather.gov/stations/KFVX", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-78.43333, 37.35] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KFVX", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 124.968 + }, + "stationIdentifier": "KFVX", + "name": "Farmville", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 207471.35283371 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 215 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ061", + "county": "https://api.weather.gov/zones/county/VAC049", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ061" + } + }, + { + "id": "https://api.weather.gov/stations/K2G4", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-79.3394, 39.5803] + }, + "properties": { + "@id": "https://api.weather.gov/stations/K2G4", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 893.9784 + }, + "stationIdentifier": "K2G4", + "name": "Garrett County Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 211917.76730527 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 292 + }, + "forecast": "https://api.weather.gov/zones/forecast/MDZ509", + "county": "https://api.weather.gov/zones/county/MDC023", + "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ509" + } + }, + { + "id": "https://api.weather.gov/stations/K2G9", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-79.015, 40.0389] + }, + "properties": { + "@id": "https://api.weather.gov/stations/K2G9", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 693.42 + }, + "stationIdentifier": "K2G9", + "name": "Somerset County Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 212550.3935379 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 308 + }, + "forecast": "https://api.weather.gov/zones/forecast/PAZ033", + "county": "https://api.weather.gov/zones/county/PAC111", + "fireWeatherZone": "https://api.weather.gov/zones/fire/PAZ033" + } + }, + { + "id": "https://api.weather.gov/stations/KEKN", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-79.85278, 38.88528] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KEKN", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 605.028 + }, + "stationIdentifier": "KEKN", + "name": "Elkins, Elkins-Randolph County-Jennings Randolph Field", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 242035.43677875 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 271 + }, + "forecast": "https://api.weather.gov/zones/forecast/WVZ525", + "county": "https://api.weather.gov/zones/county/WVC083", + "fireWeatherZone": "https://api.weather.gov/zones/fire/WVZ525" + } + }, + { + "id": "https://api.weather.gov/stations/KLYH", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-79.20667, 37.32083] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KLYH", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 284.988 + }, + "stationIdentifier": "KLYH", + "name": "Lynchburg, Lynchburg Regional Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 255021.94789795 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 228 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ045", + "county": "https://api.weather.gov/zones/county/VAC031", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ045" + } + }, + { + "id": "https://api.weather.gov/stations/KMGW", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-79.92065, 39.64985] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KMGW", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 373.9896 + }, + "stationIdentifier": "KMGW", + "name": "Morgantown Municipal-Hart Field", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 261388.09543822 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 290 + }, + "forecast": "https://api.weather.gov/zones/forecast/WVZ509", + "county": "https://api.weather.gov/zones/county/WVC061", + "fireWeatherZone": "https://api.weather.gov/zones/fire/WVZ509" + } + }, + { + "id": "https://api.weather.gov/stations/KHSP", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-79.83333, 37.95] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KHSP", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 1156.1064 + }, + "stationIdentifier": "KHSP", + "name": "Hot Springs / Ingalls", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 262623.28570565 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 247 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ020", + "county": "https://api.weather.gov/zones/county/VAC017", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ020" + } + }, + { + "id": "https://api.weather.gov/stations/KROA", + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [-79.97417, 37.31694] + }, + "properties": { + "@id": "https://api.weather.gov/stations/KROA", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 358.14 + }, + "stationIdentifier": "KROA", + "name": "Roanoke, Roanoke Regional Airport", + "timeZone": "America/New_York", + "distance": { + "unitCode": "wmoUnit:m", + "value": 308160.42662802 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 236 + }, + "forecast": "https://api.weather.gov/zones/forecast/VAZ022", + "county": "https://api.weather.gov/zones/county/VAC770", + "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ022" + } + } + ], + "observationStations": [ + "https://api.weather.gov/stations/KDCA", + "https://api.weather.gov/stations/KCGS", + "https://api.weather.gov/stations/KADW", + "https://api.weather.gov/stations/KDAA", + "https://api.weather.gov/stations/KFME", + "https://api.weather.gov/stations/KIAD", + "https://api.weather.gov/stations/KGAI", + "https://api.weather.gov/stations/KHEF", + "https://api.weather.gov/stations/KNYG", + "https://api.weather.gov/stations/KBWI", + "https://api.weather.gov/stations/KJYO", + "https://api.weather.gov/stations/KNAK", + "https://api.weather.gov/stations/KDMH", + "https://api.weather.gov/stations/KRMN", + "https://api.weather.gov/stations/KW29", + "https://api.weather.gov/stations/KHWY", + "https://api.weather.gov/stations/KFDK", + "https://api.weather.gov/stations/KEZF", + "https://api.weather.gov/stations/KMTN", + "https://api.weather.gov/stations/K2W6", + "https://api.weather.gov/stations/KCJR", + "https://api.weather.gov/stations/KDMW", + "https://api.weather.gov/stations/KESN", + "https://api.weather.gov/stations/KNHK", + "https://api.weather.gov/stations/KRSP", + "https://api.weather.gov/stations/KNUI", + "https://api.weather.gov/stations/KMRB", + "https://api.weather.gov/stations/KOKV", + "https://api.weather.gov/stations/KAPG", + "https://api.weather.gov/stations/KFRR", + "https://api.weather.gov/stations/K0W3", + "https://api.weather.gov/stations/KHGR", + "https://api.weather.gov/stations/KOMH", + "https://api.weather.gov/stations/K7W4", + "https://api.weather.gov/stations/KTHV", + "https://api.weather.gov/stations/KLKU", + "https://api.weather.gov/stations/KGVE", + "https://api.weather.gov/stations/KOFP", + "https://api.weather.gov/stations/K8W2", + "https://api.weather.gov/stations/KCHO", + "https://api.weather.gov/stations/KRIC", + "https://api.weather.gov/stations/KILG", + "https://api.weather.gov/stations/KLNS", + "https://api.weather.gov/stations/KCBE", + "https://api.weather.gov/stations/KSHD", + "https://api.weather.gov/stations/KVBW", + "https://api.weather.gov/stations/KMFV", + "https://api.weather.gov/stations/KW13", + "https://api.weather.gov/stations/KFVX", + "https://api.weather.gov/stations/K2G4", + "https://api.weather.gov/stations/K2G9", + "https://api.weather.gov/stations/KEKN", + "https://api.weather.gov/stations/KLYH", + "https://api.weather.gov/stations/KMGW", + "https://api.weather.gov/stations/KHSP", + "https://api.weather.gov/stations/KROA" + ], + "pagination": { + "next": "https://api.weather.gov/stations?id%5B0%5D=K0W3&id%5B1%5D=K2G4&id%5B2%5D=K2G9&id%5B3%5D=K2W6&id%5B4%5D=K7W4&id%5B5%5D=K8W2&id%5B6%5D=KADW&id%5B7%5D=KAPG&id%5B8%5D=KBWI&id%5B9%5D=KCBE&id%5B10%5D=KCGS&id%5B11%5D=KCHO&id%5B12%5D=KCJR&id%5B13%5D=KDAA&id%5B14%5D=KDCA&id%5B15%5D=KDMH&id%5B16%5D=KDMW&id%5B17%5D=KEKN&id%5B18%5D=KESN&id%5B19%5D=KEZF&id%5B20%5D=KFDK&id%5B21%5D=KFME&id%5B22%5D=KFRR&id%5B23%5D=KFVX&id%5B24%5D=KGAI&id%5B25%5D=KGVE&id%5B26%5D=KHEF&id%5B27%5D=KHGR&id%5B28%5D=KHSP&id%5B29%5D=KHWY&id%5B30%5D=KIAD&id%5B31%5D=KILG&id%5B32%5D=KJYO&id%5B33%5D=KLKU&id%5B34%5D=KLNS&id%5B35%5D=KLYH&id%5B36%5D=KMFV&id%5B37%5D=KMGW&id%5B38%5D=KMRB&id%5B39%5D=KMTN&id%5B40%5D=KNAK&id%5B41%5D=KNHK&id%5B42%5D=KNUI&id%5B43%5D=KNYG&id%5B44%5D=KOFP&id%5B45%5D=KOKV&id%5B46%5D=KOMH&id%5B47%5D=KRIC&id%5B48%5D=KRMN&id%5B49%5D=KROA&id%5B50%5D=KRSP&id%5B51%5D=KSHD&id%5B52%5D=KTHV&id%5B53%5D=KVBW&id%5B54%5D=KW13&id%5B55%5D=KW29&cursor=eyJzIjo1MDB9" + } +} diff --git a/tests/mocks/weather_yr.json b/tests/mocks/weather_yr.json new file mode 100644 index 0000000000..3d7dc66d80 --- /dev/null +++ b/tests/mocks/weather_yr.json @@ -0,0 +1,707 @@ +{ + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [10.7522, 59.9139, 5] }, + "properties": { + "meta": { + "updated_at": "2026-02-06T20:27:06Z", + "units": { "air_pressure_at_sea_level": "hPa", "air_temperature": "celsius", "cloud_area_fraction": "%", "precipitation_amount": "mm", "relative_humidity": "%", "wind_from_direction": "degrees", "wind_speed": "m/s" } + }, + "timeseries": [ + { + "time": "2026-02-06T21:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1014.6, "air_temperature": -5.8, "cloud_area_fraction": 100.0, "relative_humidity": 66.5, "wind_from_direction": 37.0, "wind_speed": 6.0 } }, + "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.5 } }, + "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 3.5 } } + } + }, + { + "time": "2026-02-06T22:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1014.8, "air_temperature": -5.9, "cloud_area_fraction": 100.0, "relative_humidity": 70.5, "wind_from_direction": 39.0, "wind_speed": 6.4 } }, + "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.7 } }, + "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 3.3 } } + } + }, + { + "time": "2026-02-06T23:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1015.1, "air_temperature": -5.9, "cloud_area_fraction": 100.0, "relative_humidity": 73.3, "wind_from_direction": 41.0, "wind_speed": 6.6 } }, + "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.8 } }, + "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 2.6 } } + } + }, + { + "time": "2026-02-07T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1015.4, "air_temperature": -5.8, "cloud_area_fraction": 100.0, "relative_humidity": 74.6, "wind_from_direction": 40.0, "wind_speed": 6.9 } }, + "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.6 } }, + "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 1.9 } } + } + }, + { + "time": "2026-02-07T01:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1015.5, "air_temperature": -5.7, "cloud_area_fraction": 100.0, "relative_humidity": 75.5, "wind_from_direction": 41.0, "wind_speed": 6.9 } }, + "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.5 } }, + "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 1.4 } } + } + }, + { + "time": "2026-02-07T02:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1015.7, "air_temperature": -5.5, "cloud_area_fraction": 100.0, "relative_humidity": 76.2, "wind_from_direction": 38.0, "wind_speed": 5.6 } }, + "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.3 } }, + "next_6_hours": { "summary": { "symbol_code": "lightsnow" }, "details": { "precipitation_amount": 0.9 } } + } + }, + { + "time": "2026-02-07T03:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1015.7, "air_temperature": -5.3, "cloud_area_fraction": 100.0, "relative_humidity": 76.6, "wind_from_direction": 37.0, "wind_speed": 5.2 } }, + "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "lightsnow" }, "details": { "precipitation_amount": 0.2 } }, + "next_6_hours": { "summary": { "symbol_code": "lightsnow" }, "details": { "precipitation_amount": 0.6 } } + } + }, + { + "time": "2026-02-07T04:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1015.7, "air_temperature": -5.2, "cloud_area_fraction": 100.0, "relative_humidity": 76.1, "wind_from_direction": 36.0, "wind_speed": 4.8 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "lightsnow" }, "details": { "precipitation_amount": 0.2 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T05:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1015.9, "air_temperature": -5.1, "cloud_area_fraction": 100.0, "relative_humidity": 75.6, "wind_from_direction": 35.0, "wind_speed": 4.4 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1016.5, "air_temperature": -5.0, "cloud_area_fraction": 100.0, "relative_humidity": 74.7, "wind_from_direction": 33.0, "wind_speed": 4.0 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T07:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1017.2, "air_temperature": -4.9, "cloud_area_fraction": 100.0, "relative_humidity": 73.7, "wind_from_direction": 35.0, "wind_speed": 4.3 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T08:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1017.9, "air_temperature": -4.7, "cloud_area_fraction": 99.8, "relative_humidity": 71.7, "wind_from_direction": 38.0, "wind_speed": 4.6 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T09:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1018.5, "air_temperature": -4.5, "cloud_area_fraction": 99.8, "relative_humidity": 70.2, "wind_from_direction": 43.0, "wind_speed": 5.5 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T10:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1019.0, "air_temperature": -4.1, "cloud_area_fraction": 100.0, "relative_humidity": 69.5, "wind_from_direction": 45.0, "wind_speed": 5.7 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T11:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1019.2, "air_temperature": -3.7, "cloud_area_fraction": 99.9, "relative_humidity": 68.7, "wind_from_direction": 45.0, "wind_speed": 5.7 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1019.2, "air_temperature": -3.1, "cloud_area_fraction": 93.4, "relative_humidity": 63.4, "wind_from_direction": 43.0, "wind_speed": 5.8 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T13:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1019.3, "air_temperature": -2.8, "cloud_area_fraction": 83.1, "relative_humidity": 59.5, "wind_from_direction": 46.0, "wind_speed": 6.1 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T14:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1019.5, "air_temperature": -2.7, "cloud_area_fraction": 79.7, "relative_humidity": 57.7, "wind_from_direction": 43.0, "wind_speed": 5.9 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T15:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1019.8, "air_temperature": -2.9, "cloud_area_fraction": 70.8, "relative_humidity": 56.6, "wind_from_direction": 40.0, "wind_speed": 5.6 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T16:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1020.3, "air_temperature": -3.6, "cloud_area_fraction": 55.6, "relative_humidity": 55.7, "wind_from_direction": 42.0, "wind_speed": 5.5 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T17:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1020.8, "air_temperature": -4.3, "cloud_area_fraction": 43.1, "relative_humidity": 54.0, "wind_from_direction": 43.0, "wind_speed": 5.4 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1021.5, "air_temperature": -4.8, "cloud_area_fraction": 27.4, "relative_humidity": 52.3, "wind_from_direction": 42.0, "wind_speed": 5.2 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T19:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1022.1, "air_temperature": -5.2, "cloud_area_fraction": 19.3, "relative_humidity": 53.2, "wind_from_direction": 43.0, "wind_speed": 5.4 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T20:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1022.7, "air_temperature": -5.5, "cloud_area_fraction": 10.2, "relative_humidity": 55.0, "wind_from_direction": 43.0, "wind_speed": 5.7 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "clearsky_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T21:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1023.5, "air_temperature": -5.6, "cloud_area_fraction": 6.8, "relative_humidity": 61.3, "wind_from_direction": 43.0, "wind_speed": 5.6 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "clearsky_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T22:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1024.2, "air_temperature": -5.9, "cloud_area_fraction": 38.5, "relative_humidity": 71.4, "wind_from_direction": 38.0, "wind_speed": 4.7 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-07T23:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1024.7, "air_temperature": -6.2, "cloud_area_fraction": 75.2, "relative_humidity": 77.8, "wind_from_direction": 36.0, "wind_speed": 4.0 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.2, "air_temperature": -6.4, "cloud_area_fraction": 79.6, "relative_humidity": 79.8, "wind_from_direction": 36.0, "wind_speed": 3.2 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T01:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.5, "air_temperature": -6.5, "cloud_area_fraction": 77.6, "relative_humidity": 80.0, "wind_from_direction": 34.0, "wind_speed": 3.1 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T02:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.5, "air_temperature": -6.5, "cloud_area_fraction": 71.4, "relative_humidity": 79.7, "wind_from_direction": 32.0, "wind_speed": 3.4 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T03:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.3, "air_temperature": -6.7, "cloud_area_fraction": 63.1, "relative_humidity": 79.9, "wind_from_direction": 32.0, "wind_speed": 3.3 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T04:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.3, "air_temperature": -7.1, "cloud_area_fraction": 62.1, "relative_humidity": 80.4, "wind_from_direction": 33.0, "wind_speed": 3.1 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T05:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.2, "air_temperature": -7.5, "cloud_area_fraction": 65.0, "relative_humidity": 82.2, "wind_from_direction": 45.0, "wind_speed": 2.4 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.5, "air_temperature": -7.7, "cloud_area_fraction": 77.7, "relative_humidity": 82.7, "wind_from_direction": 48.0, "wind_speed": 2.2 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T07:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.8, "air_temperature": -7.8, "cloud_area_fraction": 84.5, "relative_humidity": 82.2, "wind_from_direction": 48.0, "wind_speed": 2.6 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T08:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1026.2, "air_temperature": -7.6, "cloud_area_fraction": 82.8, "relative_humidity": 80.9, "wind_from_direction": 48.0, "wind_speed": 3.0 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T09:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1026.4, "air_temperature": -6.9, "cloud_area_fraction": 77.9, "relative_humidity": 78.9, "wind_from_direction": 46.0, "wind_speed": 3.3 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T10:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1026.3, "air_temperature": -6.2, "cloud_area_fraction": 82.3, "relative_humidity": 77.0, "wind_from_direction": 43.0, "wind_speed": 3.5 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T11:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1026.3, "air_temperature": -5.5, "cloud_area_fraction": 93.0, "relative_humidity": 76.6, "wind_from_direction": 49.0, "wind_speed": 3.2 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1026.1, "air_temperature": -5.1, "cloud_area_fraction": 98.9, "relative_humidity": 76.2, "wind_from_direction": 47.0, "wind_speed": 2.6 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T13:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.7, "air_temperature": -4.8, "cloud_area_fraction": 99.4, "relative_humidity": 76.2, "wind_from_direction": 50.0, "wind_speed": 2.3 } }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T14:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.4, "air_temperature": -4.8, "cloud_area_fraction": 95.5, "relative_humidity": 76.3, "wind_from_direction": 56.0, "wind_speed": 2.5 } }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T15:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1025.1, "air_temperature": -5.4, "cloud_area_fraction": 84.9, "relative_humidity": 77.2, "wind_from_direction": 56.0, "wind_speed": 2.6 } }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T16:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1024.8, "air_temperature": -6.1, "cloud_area_fraction": 57.9, "relative_humidity": 78.9, "wind_from_direction": 48.0, "wind_speed": 2.7 } }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T17:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1024.5, "air_temperature": -6.5, "cloud_area_fraction": 50.7, "relative_humidity": 81.3, "wind_from_direction": 38.0, "wind_speed": 2.5 } }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1024.3, "air_temperature": -6.9, "cloud_area_fraction": 72.7, "relative_humidity": 82.2, "wind_from_direction": 38.0, "wind_speed": 2.5 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T19:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1024.3, "air_temperature": -6.9, "cloud_area_fraction": 89.8, "relative_humidity": 81.9, "wind_from_direction": 44.0, "wind_speed": 1.9 } }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T20:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1024.2, "air_temperature": -7.0, "cloud_area_fraction": 96.6, "relative_humidity": 81.3, "wind_from_direction": 39.0, "wind_speed": 2.3 } }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T21:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1024.1, "air_temperature": -6.7, "cloud_area_fraction": 97.2, "relative_humidity": 79.9, "wind_from_direction": 40.0, "wind_speed": 2.8 } }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T22:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1023.8, "air_temperature": -6.7, "cloud_area_fraction": 97.6, "relative_humidity": 80.3, "wind_from_direction": 50.0, "wind_speed": 2.6 } }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-08T23:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1023.4, "air_temperature": -6.7, "cloud_area_fraction": 93.5, "relative_humidity": 80.7, "wind_from_direction": 53.0, "wind_speed": 2.3 } }, + "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-09T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1023.1, "air_temperature": -7.1, "cloud_area_fraction": 80.0, "relative_humidity": 81.2, "wind_from_direction": 60.0, "wind_speed": 2.3 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-09T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1019.1, "air_temperature": -4.4, "cloud_area_fraction": 99.2, "relative_humidity": 85.9, "wind_from_direction": 339.8, "wind_speed": 1.1 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-09T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1017.8, "air_temperature": -4.3, "cloud_area_fraction": 100.0, "relative_humidity": 72.3, "wind_from_direction": 285.3, "wind_speed": 0.7 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-09T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1014.7, "air_temperature": -6.8, "cloud_area_fraction": 95.7, "relative_humidity": 82.1, "wind_from_direction": 346.8, "wind_speed": 0.6 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-10T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1012.9, "air_temperature": -8.8, "cloud_area_fraction": 97.7, "relative_humidity": 83.2, "wind_from_direction": 15.8, "wind_speed": 1.0 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-10T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1009.9, "air_temperature": -5.8, "cloud_area_fraction": 93.7, "relative_humidity": 82.2, "wind_from_direction": 22.4, "wind_speed": 1.0 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-10T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1007.5, "air_temperature": -3.5, "cloud_area_fraction": 100.0, "relative_humidity": 71.4, "wind_from_direction": 202.3, "wind_speed": 0.9 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-10T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1004.3, "air_temperature": -3.0, "cloud_area_fraction": 100.0, "relative_humidity": 81.9, "wind_from_direction": 22.3, "wind_speed": 1.0 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-11T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1002.5, "air_temperature": -2.3, "cloud_area_fraction": 100.0, "relative_humidity": 85.0, "wind_from_direction": 28.5, "wind_speed": 1.0 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-11T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1000.9, "air_temperature": -3.2, "cloud_area_fraction": 100.0, "relative_humidity": 85.5, "wind_from_direction": 28.1, "wind_speed": 1.6 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-11T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 999.8, "air_temperature": -2.0, "cloud_area_fraction": 100.0, "relative_humidity": 74.9, "wind_from_direction": 56.3, "wind_speed": 2.2 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-11T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 998.8, "air_temperature": -2.4, "cloud_area_fraction": 82.0, "relative_humidity": 77.8, "wind_from_direction": 29.5, "wind_speed": 2.2 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-12T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 998.3, "air_temperature": -2.9, "cloud_area_fraction": 100.0, "relative_humidity": 83.4, "wind_from_direction": 33.1, "wind_speed": 2.5 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-12T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 998.4, "air_temperature": -3.9, "cloud_area_fraction": 100.0, "relative_humidity": 83.0, "wind_from_direction": 24.1, "wind_speed": 2.5 } }, + "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-12T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 998.9, "air_temperature": -3.3, "cloud_area_fraction": 99.6, "relative_humidity": 73.0, "wind_from_direction": 54.4, "wind_speed": 2.6 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-12T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 999.9, "air_temperature": -4.3, "cloud_area_fraction": 98.0, "relative_humidity": 81.3, "wind_from_direction": 24.0, "wind_speed": 2.2 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-13T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1001.9, "air_temperature": -4.6, "cloud_area_fraction": 39.8, "relative_humidity": 80.6, "wind_from_direction": 23.4, "wind_speed": 2.0 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-13T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1004.1, "air_temperature": -7.4, "cloud_area_fraction": 36.3, "relative_humidity": 81.8, "wind_from_direction": 21.9, "wind_speed": 1.9 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-13T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1005.7, "air_temperature": -5.8, "cloud_area_fraction": 100.0, "relative_humidity": 73.2, "wind_from_direction": 33.1, "wind_speed": 1.5 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-13T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1004.7, "air_temperature": -5.0, "cloud_area_fraction": 0.0, "relative_humidity": 76.6, "wind_from_direction": 20.2, "wind_speed": 1.7 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-14T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1007.8, "air_temperature": -7.8, "cloud_area_fraction": 6.2, "relative_humidity": 78.8, "wind_from_direction": 23.1, "wind_speed": 1.7 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-14T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1007.4, "air_temperature": -11.8, "cloud_area_fraction": 21.9, "relative_humidity": 79.9, "wind_from_direction": 21.8, "wind_speed": 1.7 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "fair_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-14T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1007.5, "air_temperature": -6.3, "cloud_area_fraction": 100.0, "relative_humidity": 70.5, "wind_from_direction": 25.3, "wind_speed": 1.2 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-14T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1008.0, "air_temperature": -5.5, "cloud_area_fraction": 100.0, "relative_humidity": 76.6, "wind_from_direction": 22.4, "wind_speed": 1.2 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-15T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1009.5, "air_temperature": -6.4, "cloud_area_fraction": 25.4, "relative_humidity": 76.8, "wind_from_direction": 18.6, "wind_speed": 1.5 } }, + "next_12_hours": { "summary": { "symbol_code": "fair_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-15T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1012.1, "air_temperature": -11.2, "cloud_area_fraction": 16.8, "relative_humidity": 79.5, "wind_from_direction": 17.5, "wind_speed": 1.6 } }, + "next_12_hours": { "summary": { "symbol_code": "clearsky_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "fair_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-15T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1013.1, "air_temperature": -5.3, "cloud_area_fraction": 2.7, "relative_humidity": 59.4, "wind_from_direction": 197.5, "wind_speed": 1.2 } }, + "next_12_hours": { "summary": { "symbol_code": "clearsky_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "clearsky_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-15T18:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1015.2, "air_temperature": -7.4, "cloud_area_fraction": 2.3, "relative_humidity": 74.9, "wind_from_direction": 22.8, "wind_speed": 1.4 } }, + "next_12_hours": { "summary": { "symbol_code": "fair_night" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "clearsky_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-16T00:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1017.9, "air_temperature": -9.3, "cloud_area_fraction": 2.3, "relative_humidity": 78.8, "wind_from_direction": 22.1, "wind_speed": 1.5 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "clearsky_night" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-16T06:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1017.5, "air_temperature": -8.6, "cloud_area_fraction": 100.0, "relative_humidity": 82.1, "wind_from_direction": 17.7, "wind_speed": 1.4 } }, + "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} }, + "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-16T12:00:00Z", + "data": { + "instant": { "details": { "air_pressure_at_sea_level": 1012.1, "air_temperature": -3.0, "cloud_area_fraction": 3.9, "relative_humidity": 62.3, "wind_from_direction": 30.4, "wind_speed": 1.4 } }, + "next_6_hours": { "summary": { "symbol_code": "fair_day" }, "details": { "precipitation_amount": 0.0 } } + } + }, + { + "time": "2026-02-16T18:00:00Z", + "data": { "instant": { "details": { "air_pressure_at_sea_level": 1017.1, "air_temperature": -5.9, "cloud_area_fraction": 100.0, "relative_humidity": 82.0, "wind_from_direction": 26.6, "wind_speed": 1.9 } } } + } + ] + } +} diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index c0953d4877..91ee3cac79 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -164,6 +164,7 @@ describe("server_functions tests", () => { }); it("Gets User-Agent from configuration", async () => { + const previousConfig = global.config; global.config = {}; let userAgent; @@ -177,6 +178,8 @@ describe("server_functions tests", () => { global.config.userAgent = () => "Mozilla/5.0 (Bar)"; userAgent = getUserAgent(); expect(userAgent).toBe("Mozilla/5.0 (Bar)"); + + global.config = previousConfig; }); }); }); diff --git a/tests/unit/modules/default/utils_spec.js b/tests/unit/modules/default/utils_spec.js index 4af7db6765..efea6e28e7 100644 --- a/tests/unit/modules/default/utils_spec.js +++ b/tests/unit/modules/default/utils_spec.js @@ -1,111 +1,9 @@ global.moment = require("moment-timezone"); const defaults = require("../../../../js/defaults"); -const { performWebRequest, formatTime } = require(`../../../../${defaults.defaultModulesDir}/utils`); +const { formatTime } = require(`../../../../${defaults.defaultModulesDir}/utils`); describe("Default modules utils tests", () => { - describe("performWebRequest", () => { - const locationHost = "localhost:8080"; - const locationProtocol = "http"; - - let fetchResponse; - let fetchMock; - let urlToCall; - - beforeEach(() => { - fetchResponse = new Response(); - global.fetch = vi.fn(() => Promise.resolve(fetchResponse)); - fetchMock = global.fetch; - }); - - describe("When using cors proxy", () => { - Object.defineProperty(global, "location", { - value: { - host: locationHost, - protocol: locationProtocol - } - }); - - it("Calls correct URL once", async () => { - urlToCall = "http://www.test.com/path?param1=value1"; - - await performWebRequest(urlToCall, "json", true); - - expect(fetchMock.mock.calls).toHaveLength(1); - expect(fetchMock.mock.calls[0][0]).toBe(`${locationProtocol}//${locationHost}/cors?url=${urlToCall}`); - }); - - it("Sends correct headers", async () => { - urlToCall = "http://www.test.com/path?param1=value1"; - - const headers = [ - { name: "header1", value: "value1" }, - { name: "header2", value: "value2" } - ]; - - await performWebRequest(urlToCall, "json", true, headers); - - expect(fetchMock.mock.calls).toHaveLength(1); - expect(fetchMock.mock.calls[0][0]).toBe(`${locationProtocol}//${locationHost}/cors?sendheaders=header1:value1,header2:value2&url=${urlToCall}`); - }); - }); - - describe("When not using cors proxy", () => { - it("Calls correct URL once", async () => { - urlToCall = "http://www.test.com/path?param1=value1"; - - await performWebRequest(urlToCall); - - expect(fetchMock.mock.calls).toHaveLength(1); - expect(fetchMock.mock.calls[0][0]).toBe(urlToCall); - }); - - it("Sends correct headers", async () => { - urlToCall = "http://www.test.com/path?param1=value1"; - const headers = [ - { name: "header1", value: "value1" }, - { name: "header2", value: "value2" } - ]; - - await performWebRequest(urlToCall, "json", false, headers); - - const expectedHeaders = { headers: { header1: "value1", header2: "value2" } }; - expect(fetchMock.mock.calls).toHaveLength(1); - expect(fetchMock.mock.calls[0][1]).toStrictEqual(expectedHeaders); - }); - }); - - describe("When receiving json format", () => { - it("Returns undefined when no data is received", async () => { - urlToCall = "www.test.com"; - - const response = await performWebRequest(urlToCall); - - expect(response).toBeUndefined(); - }); - - it("Returns object when data is received", async () => { - urlToCall = "www.test.com"; - fetchResponse = new Response("{\"body\": \"some content\"}"); - - const response = await performWebRequest(urlToCall); - - expect(response.body).toBe("some content"); - }); - - it("Returns expected headers when data is received", async () => { - urlToCall = "www.test.com"; - fetchResponse = new Response("{\"body\": \"some content\"}", { headers: { header1: "value1", header2: "value2" } }); - - const response = await performWebRequest(urlToCall, "json", false, undefined, ["header1"]); - - expect(response.headers).toHaveLength(1); - expect(response.headers[0].name).toBe("header1"); - expect(response.headers[0].value).toBe("value1"); - }); - }); - }); - describe("formatTime", () => { const time = new Date(); diff --git a/tests/unit/modules/default/weather/provider_utils_spec.js b/tests/unit/modules/default/weather/provider_utils_spec.js new file mode 100644 index 0000000000..511a84340f --- /dev/null +++ b/tests/unit/modules/default/weather/provider_utils_spec.js @@ -0,0 +1,167 @@ +const defaults = require("../../../../../js/defaults"); + +const providerUtils = require(`../../../../../${defaults.defaultModulesDir}/weather/provider-utils`); + +describe("Weather provider utils tests", () => { + describe("convertWeatherType", () => { + it("should convert OpenWeatherMap day icons correctly", () => { + expect(providerUtils.convertWeatherType("01d")).toBe("day-sunny"); + expect(providerUtils.convertWeatherType("02d")).toBe("day-cloudy"); + expect(providerUtils.convertWeatherType("10d")).toBe("rain"); + expect(providerUtils.convertWeatherType("13d")).toBe("snow"); + }); + + it("should convert OpenWeatherMap night icons correctly", () => { + expect(providerUtils.convertWeatherType("01n")).toBe("night-clear"); + expect(providerUtils.convertWeatherType("02n")).toBe("night-cloudy"); + expect(providerUtils.convertWeatherType("10n")).toBe("night-rain"); + }); + + it("should return null for unknown weather types", () => { + expect(providerUtils.convertWeatherType("99x")).toBeNull(); + expect(providerUtils.convertWeatherType("")).toBeNull(); + }); + }); + + describe("applyTimezoneOffset", () => { + it("should apply positive offset correctly", () => { + const date = new Date("2026-02-02T12:00:00Z"); + const result = providerUtils.applyTimezoneOffset(date, 120); // +2 hours + // The function converts to UTC, then applies offset + const expected = new Date(date.getTime() + date.getTimezoneOffset() * 60000 + 120 * 60000); + expect(result.getTime()).toBe(expected.getTime()); + }); + + it("should apply negative offset correctly", () => { + const date = new Date("2026-02-02T12:00:00Z"); + const result = providerUtils.applyTimezoneOffset(date, -300); // -5 hours + const expected = new Date(date.getTime() + date.getTimezoneOffset() * 60000 - 300 * 60000); + expect(result.getTime()).toBe(expected.getTime()); + }); + + it("should handle zero offset", () => { + const date = new Date("2026-02-02T12:00:00Z"); + const result = providerUtils.applyTimezoneOffset(date, 0); + const expected = new Date(date.getTime() + date.getTimezoneOffset() * 60000); + expect(result.getTime()).toBe(expected.getTime()); + }); + }); + + describe("limitDecimals", () => { + it("should truncate decimals correctly", () => { + expect(providerUtils.limitDecimals(12.3456789, 4)).toBe(12.3456); + expect(providerUtils.limitDecimals(12.3456789, 2)).toBe(12.34); + }); + + it("should handle values with fewer decimals than limit", () => { + expect(providerUtils.limitDecimals(12.34, 6)).toBe(12.34); + expect(providerUtils.limitDecimals(12, 4)).toBe(12); + }); + + it("should handle negative values", () => { + expect(providerUtils.limitDecimals(-12.3456789, 2)).toBe(-12.34); + }); + + it("should truncate not round", () => { + expect(providerUtils.limitDecimals(12.9999, 2)).toBe(12.99); + expect(providerUtils.limitDecimals(12.9999, 0)).toBe(12); + }); + }); + + describe("getSunTimes", () => { + it("should return sunrise and sunset times", () => { + const date = new Date("2026-06-21T12:00:00Z"); // Summer solstice + const lat = 52.52; // Berlin + const lon = 13.405; + + const result = providerUtils.getSunTimes(date, lat, lon); + + expect(result).toHaveProperty("sunrise"); + expect(result).toHaveProperty("sunset"); + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + expect(result.sunrise.getTime()).toBeLessThan(result.sunset.getTime()); + }); + + it("should handle different locations", () => { + const date = new Date("2026-06-21T12:00:00Z"); + + // London + const london = providerUtils.getSunTimes(date, 51.5074, -0.1278); + // Tokyo + const tokyo = providerUtils.getSunTimes(date, 35.6762, 139.6503); + + expect(london.sunrise.getTime()).not.toBe(tokyo.sunrise.getTime()); + }); + }); + + describe("isDayTime", () => { + it("should return true when time is between sunrise and sunset", () => { + const sunrise = new Date("2026-02-02T07:00:00Z"); + const sunset = new Date("2026-02-02T17:00:00Z"); + const noon = new Date("2026-02-02T12:00:00Z"); + + expect(providerUtils.isDayTime(noon, sunrise, sunset)).toBe(true); + }); + + it("should return false when time is before sunrise", () => { + const sunrise = new Date("2026-02-02T07:00:00Z"); + const sunset = new Date("2026-02-02T17:00:00Z"); + const night = new Date("2026-02-02T03:00:00Z"); + + expect(providerUtils.isDayTime(night, sunrise, sunset)).toBe(false); + }); + + it("should return false when time is after sunset", () => { + const sunrise = new Date("2026-02-02T07:00:00Z"); + const sunset = new Date("2026-02-02T17:00:00Z"); + const night = new Date("2026-02-02T20:00:00Z"); + + expect(providerUtils.isDayTime(night, sunrise, sunset)).toBe(false); + }); + + it("should return true if sunrise/sunset are null", () => { + const noon = new Date("2026-02-02T12:00:00Z"); + expect(providerUtils.isDayTime(noon, null, null)).toBe(true); + }); + }); + + describe("formatTimezoneOffset", () => { + it("should format positive offsets correctly", () => { + expect(providerUtils.formatTimezoneOffset(60)).toBe("+01:00"); + expect(providerUtils.formatTimezoneOffset(120)).toBe("+02:00"); + expect(providerUtils.formatTimezoneOffset(330)).toBe("+05:30"); // India + }); + + it("should format negative offsets correctly", () => { + expect(providerUtils.formatTimezoneOffset(-300)).toBe("-05:00"); // EST + expect(providerUtils.formatTimezoneOffset(-480)).toBe("-08:00"); // PST + }); + + it("should format zero offset correctly", () => { + expect(providerUtils.formatTimezoneOffset(0)).toBe("+00:00"); + }); + + it("should pad single digits with zero", () => { + expect(providerUtils.formatTimezoneOffset(5)).toBe("+00:05"); + expect(providerUtils.formatTimezoneOffset(-5)).toBe("-00:05"); + }); + }); + + describe("getDateString", () => { + it("should format date as YYYY-MM-DD (local time)", () => { + const date = new Date(2026, 1, 2, 12, 34, 56); // Feb 2, 2026 (month is 0-indexed) + expect(providerUtils.getDateString(date)).toBe("2026-02-02"); + }); + + it("should handle single-digit months and days correctly", () => { + const date = new Date(2026, 0, 5, 12, 0, 0); // Jan 5, 2026 + expect(providerUtils.getDateString(date)).toBe("2026-01-05"); + }); + + it("should handle end of year", () => { + const date = new Date(2025, 11, 31, 23, 59, 59); // Dec 31, 2025 + expect(providerUtils.getDateString(date)).toBe("2025-12-31"); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/envcanada_spec.js b/tests/unit/modules/default/weather/providers/envcanada_spec.js new file mode 100644 index 0000000000..85533c5199 --- /dev/null +++ b/tests/unit/modules/default/weather/providers/envcanada_spec.js @@ -0,0 +1,309 @@ +/** + * Environment Canada Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + * Environment Canada is the Canadian weather service (XML-based). + */ + +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const indexHTML = fs.readFileSync(path.join(__dirname, "../../../../../mocks/weather_envcanada_index.html"), "utf-8"); +const cityPageXML = fs.readFileSync(path.join(__dirname, "../../../../../mocks/weather_envcanada.xml"), "utf-8"); + +// Match directory listing (index) - must end with / and nothing after +const ENVCANADA_INDEX_PATTERN = /https:\/\/dd\.weather\.gc\.ca\/today\/citypage_weather\/[A-Z]{2}\/\d{2}\/$/; +// Match actual XML files +const ENVCANADA_CITYPAGE_PATTERN = /https:\/\/dd\.weather\.gc\.ca\/today\/citypage_weather\/[A-Z]{2}\/\d{2}\/.*\.xml$/; + +let server; + +beforeAll(() => { + server = setupServer( + http.get(ENVCANADA_INDEX_PATTERN, () => { + return new HttpResponse(indexHTML, { + headers: { "Content-Type": "text/html" } + }); + }), + http.get(ENVCANADA_CITYPAGE_PATTERN, () => { + return new HttpResponse(cityPageXML, { + headers: { "Content-Type": "application/xml" } + }); + }) + ); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("EnvCanadaProvider", () => { + let EnvCanadaProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/envcanada"); + EnvCanadaProvider = module.default || module; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "current" + }); + expect(provider.config.siteCode).toBe("s0000458"); + expect(provider.config.provCode).toBe("ON"); + expect(provider.config.type).toBe("current"); + }); + + it("should throw error if siteCode or provCode missing", async () => { + const provider = new EnvCanadaProvider({ siteCode: "", provCode: "" }); + provider.setCallbacks(vi.fn(), vi.fn()); + await expect(provider.initialize()).rejects.toThrow("siteCode and provCode are required"); + }); + }); + + describe("Two-Step Fetch Pattern", () => { + it("should first fetch index page then city page", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + expect(result).toBeDefined(); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather from XML", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "current" + }); + + const dataPromise = new Promise((resolve, reject) => { + provider.setCallbacks( + (data) => { + resolve(data); + }, + (error) => { + reject(error); + } + ); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(result.temperature).toBe(-20.3); + expect(result.windSpeed).toBeCloseTo(5.28, 1); // 19 km/h -> m/s + expect(result.windFromDirection).toBe(346); // NNW + expect(result.humidity).toBe(67); + }); + + it("should use wind chill for feels like temperature when available", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // XML has windChill of -31 + expect(result.feelsLikeTemp).toBe(-31); + }); + + it("should parse sunrise/sunset from XML", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + }); + + it("should convert icon code to weather type", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Icon code 40 = "Blowing Snow" → "snow-wind" + expect(result.weatherType).toBe("snow-wind"); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast from XML", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const day = result[0]; + expect(day).toHaveProperty("date"); + expect(day).toHaveProperty("minTemperature"); + expect(day).toHaveProperty("maxTemperature"); + expect(day).toHaveProperty("precipitationProbability"); + expect(day).toHaveProperty("weatherType"); + }); + + it("should extract max precipitation probability from day/night", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Real data has 40% for both day and night periods + expect(result[0].precipitationProbability).toBe(40); + }); + }); + + describe("Hourly Parsing", () => { + it("should parse hourly forecast from XML", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(24); // Real data has 24 hourly forecasts + const hour = result[0]; + expect(hour).toHaveProperty("date"); + expect(hour).toHaveProperty("temperature"); + expect(hour).toHaveProperty("precipitationProbability"); + expect(hour).toHaveProperty("weatherType"); + }); + + it("should parse EC time format correctly", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s0000458", + provCode: "ON", + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // First hourly forecast is for 202602071300 = 2026-02-07 13:00 UTC + const expectedDate = new Date(Date.UTC(2026, 1, 7, 13, 0, 0)); + expect(result[0].date.getTime()).toBe(expectedDate.getTime()); + }); + }); + + describe("Error Handling", () => { + it("should handle missing city page URL", async () => { + const provider = new EnvCanadaProvider({ + siteCode: "s9999999", // Invalid site code + provCode: "ON", + type: "current" + }); + + let errorCalled = false; + provider.setCallbacks(vi.fn(), () => { + errorCalled = true; + }); + + await provider.initialize(); + provider.start(); + + // Should not call error callback if URL not found (it's expected during hour transitions) + // Wait a bit to see if callback is called + await new Promise((resolve) => setTimeout(resolve, 100)); + + expect(errorCalled).toBe(false); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/openmeteo_spec.js b/tests/unit/modules/default/weather/providers/openmeteo_spec.js new file mode 100644 index 0000000000..7201c293ae --- /dev/null +++ b/tests/unit/modules/default/weather/providers/openmeteo_spec.js @@ -0,0 +1,305 @@ +/** + * OpenMeteo Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + * Uses MSW to mock HTTP responses from the Open-Meteo API. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +import openMeteoData from "../../../../../mocks/weather_openmeteo_current.json" with { type: "json" }; +import openMeteoCurrentWeatherData from "../../../../../mocks/weather_openmeteo_current_weather.json" with { type: "json" }; +// Real API returns current + forecast in one response +const currentData = openMeteoCurrentWeatherData; +const forecastData = openMeteoData; + +const GEOCODE_URL = "https://api.bigdatacloud.net/data/reverse-geocode-client*"; + +let server; + +beforeAll(() => { + // Mock global fetch for geocoding (used by provider's #fetchLocation) + server = setupServer( + http.get(GEOCODE_URL, () => { + return HttpResponse.json({ + city: "Munich", + locality: "Munich", + principalSubdivisionCode: "BY" + }); + }) + ); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("OpenMeteoProvider", () => { + let OpenMeteoProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/openmeteo"); + OpenMeteoProvider = module.default; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "current" + }); + expect(provider.config.lat).toBe(48.14); + expect(provider.config.lon).toBe(11.58); + expect(provider.config.type).toBe("current"); + }); + + it("should have default values", () => { + const provider = new OpenMeteoProvider({}); + expect(provider.config.lat).toBe(0); + expect(provider.config.lon).toBe(0); + expect(provider.config.type).toBe("current"); + expect(provider.config.maxNumberOfDays).toBe(5); + expect(provider.config.apiBase).toBe("https://api.open-meteo.com/v1"); + }); + + it("should initialize without callbacks", async () => { + const provider = new OpenMeteoProvider({ lat: 48.14, lon: 11.58 }); + await expect(provider.initialize()).resolves.not.toThrow(); + }); + + it("should resolve location name via geocoding", async () => { + const provider = new OpenMeteoProvider({ lat: 48.14, lon: 11.58 }); + await provider.initialize(); + expect(provider.locationName).toBe("Munich, BY"); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather data correctly", async () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "current" + }); + + const dataPromise = new Promise((resolve, reject) => { + provider.setCallbacks( + (data) => { + resolve(data); + }, + (error) => { + reject(error); + } + ); + }); + + server.use( + http.get("https://api.open-meteo.com/v1/forecast*", () => { + return HttpResponse.json(currentData); + }) + ); + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + 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); + }); + + it("should include sunrise and sunset from daily data", async () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "current" + }); + + const dataPromise = new Promise((resolve, reject) => { + provider.setCallbacks( + (data) => { + resolve(data); + }, + (error) => { + reject(error); + } + ); + }); + + server.use( + http.get("https://api.open-meteo.com/v1/forecast*", () => { + return HttpResponse.json(currentData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + expect(result.minTemperature).toBe(4.7); + expect(result.maxTemperature).toBe(9.5); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data correctly", async () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://api.open-meteo.com/v1/forecast*", () => { + return HttpResponse.json(forecastData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(7); + const firstDay = result[0]; + expect(firstDay.minTemperature).toBe(-9.2); + expect(firstDay.maxTemperature).toBe(-0.2); + expect(firstDay.temperature).toBeCloseTo(-4.7, 0); // (-0.2+-9.2)/2 + + expect(firstDay.sunrise).toBeInstanceOf(Date); + expect(firstDay.sunset).toBeInstanceOf(Date); + }); + + it("should include precipitation data in forecast", async () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://api.open-meteo.com/v1/forecast*", () => { + return HttpResponse.json(forecastData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Mock data has no rain_sum field - provider returns null for missing data + expect(result[0].rain).toBeNull(); + // precipitation_sum has value 0.0 in mock data + expect(result[0].precipitationAmount).toBe(0.0); + }); + }); + + describe("Error Handling", () => { + it("should call error callback on invalid API response", async () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get("https://api.open-meteo.com/v1/forecast*", () => { + return HttpResponse.json({}); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error).toHaveProperty("message"); + expect(error).toHaveProperty("translationKey"); + }); + + it("should call error callback on network failure", async () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get("https://api.open-meteo.com/v1/forecast*", () => { + return HttpResponse.error(); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error).toHaveProperty("url"); + }); + }); + + describe("Callback Interface", () => { + it("should store callbacks via setCallbacks", () => { + const provider = new OpenMeteoProvider({}); + const onData = vi.fn(); + const onError = vi.fn(); + provider.setCallbacks(onData, onError); + expect(provider.onDataCallback).toBe(onData); + expect(provider.onErrorCallback).toBe(onError); + }); + }); + + describe("Lifecycle", () => { + it("should have start/stop methods", () => { + const provider = new OpenMeteoProvider({}); + expect(typeof provider.start).toBe("function"); + expect(typeof provider.stop).toBe("function"); + }); + + it("should clear timer on stop", async () => { + const provider = new OpenMeteoProvider({ lat: 48.14, lon: 11.58 }); + provider.setCallbacks(vi.fn(), vi.fn()); + + server.use( + http.get("https://api.open-meteo.com/v1/forecast*", () => { + return HttpResponse.json(currentData); + }) + ); + + await provider.initialize(); + provider.stop(); + + // Should not throw + expect(provider.fetcher).not.toBeNull(); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/openweathermap_spec.js b/tests/unit/modules/default/weather/providers/openweathermap_spec.js new file mode 100644 index 0000000000..6303978441 --- /dev/null +++ b/tests/unit/modules/default/weather/providers/openweathermap_spec.js @@ -0,0 +1,235 @@ +/** + * OpenWeatherMap Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + */ +import { http, HttpResponse } from "msw"; +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" }; + +let server; + +beforeAll(() => { + server = setupServer(); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("OpenWeatherMapProvider", () => { + let OpenWeatherMapProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/openweathermap"); + OpenWeatherMapProvider = module.default; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new OpenWeatherMapProvider({ + lat: 48.14, + lon: 11.58, + apiKey: "test-key" + }); + expect(provider.config.lat).toBe(48.14); + expect(provider.config.lon).toBe(11.58); + expect(provider.config.apiKey).toBe("test-key"); + }); + + it("should have default values", () => { + const provider = new OpenWeatherMapProvider({ apiKey: "test" }); + expect(provider.config.apiVersion).toBe("3.0"); + expect(provider.config.weatherEndpoint).toBe("/onecall"); + expect(provider.config.apiBase).toBe("https://api.openweathermap.org/data/"); + }); + }); + + describe("API Key Validation", () => { + it("should call error callback without API key", async () => { + const provider = new OpenWeatherMapProvider({ apiKey: "" }); + const onError = vi.fn(); + provider.setCallbacks(vi.fn(), onError); + await provider.initialize(); + expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ message: "API key is required" }) + ); + }); + + it("should not create fetcher without API key", async () => { + const provider = new OpenWeatherMapProvider({ apiKey: "" }); + provider.setCallbacks(vi.fn(), vi.fn()); + await provider.initialize(); + expect(provider.fetcher).toBeNull(); + }); + + it("should throw if setCallbacks not called before initialize", async () => { + const provider = new OpenWeatherMapProvider({ apiKey: "test" }); + await expect(provider.initialize()).rejects.toThrow("setCallbacks"); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse onecall current weather data", async () => { + const provider = new OpenWeatherMapProvider({ + lat: 48.14, + lon: 11.58, + apiKey: "test-key", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://api.openweathermap.org/data/3.0/onecall", () => { + return HttpResponse.json(onecallData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.temperature).toBe(-0.27); + expect(result.windSpeed).toBe(3.09); + expect(result.windFromDirection).toBe(220); + expect(result.humidity).toBe(54); + expect(result.uvIndex).toBe(0); + expect(result.feelsLikeTemp).toBe(-3.9); + expect(result.weatherType).toBe("cloudy-windy"); + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + }); + + it("should include precipitation data in current weather", async () => { + const provider = new OpenWeatherMapProvider({ + lat: 48.14, + lon: 11.58, + apiKey: "test-key", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://api.openweathermap.org/data/3.0/onecall", () => { + return HttpResponse.json(onecallData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Real data has no precipitation + expect(result.rain).toBeUndefined(); + expect(result.snow).toBeUndefined(); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data", async () => { + const provider = new OpenWeatherMapProvider({ + lat: 48.14, + lon: 11.58, + apiKey: "test-key", + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://api.openweathermap.org/data/3.0/onecall", () => { + return HttpResponse.json(onecallData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(8); + expect(result[0].minTemperature).toBe(-11.86); + expect(result[0].maxTemperature).toBe(-0.27); + expect(result[0].snow).toBe(0.69); + expect(result[0].precipitationProbability).toBe(100); + }); + }); + + describe("Hourly Parsing", () => { + it("should parse hourly forecast data", async () => { + const provider = new OpenWeatherMapProvider({ + lat: 48.14, + lon: 11.58, + apiKey: "test-key", + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://api.openweathermap.org/data/3.0/onecall", () => { + return HttpResponse.json(onecallData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(48); + expect(result[0].temperature).toBe(-0.66); + expect(result[0].precipitationProbability).toBe(0); + expect(result[0].rain).toBeUndefined(); + }); + }); + + describe("Timezone Handling", () => { + it("should set location name from timezone", async () => { + const provider = new OpenWeatherMapProvider({ + lat: 48.14, + lon: 11.58, + apiKey: "test-key", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://api.openweathermap.org/data/3.0/onecall", () => { + return HttpResponse.json(onecallData); + }) + ); + + await provider.initialize(); + provider.start(); + + await dataPromise; + + expect(provider.locationName).toBe("America/New_York"); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/pirateweather_spec.js b/tests/unit/modules/default/weather/providers/pirateweather_spec.js new file mode 100644 index 0000000000..e2e3a8e103 --- /dev/null +++ b/tests/unit/modules/default/weather/providers/pirateweather_spec.js @@ -0,0 +1,366 @@ +/** + * Pirate Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + * Pirate Weather is a Dark Sky API compatible service. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +import pirateweatherData from "../../../../../mocks/weather_pirateweather.json" with { type: "json" }; + +const PIRATEWEATHER_URL = "https://api.pirateweather.net/forecast/*"; + +let server; + +beforeAll(() => { + server = setupServer(); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("PirateweatherProvider", () => { + let PirateweatherProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/pirateweather"); + PirateweatherProvider = module.default || module; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new PirateweatherProvider({ + apiKey: "test-api-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + expect(provider.config.apiKey).toBe("test-api-key"); + expect(provider.config.lat).toBe(40.71); + expect(provider.config.lon).toBe(-74.0); + }); + + it("should error if API key is missing", async () => { + const provider = new PirateweatherProvider({ + lat: 40.71, + lon: -74.0 + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + await provider.initialize(); + + const error = await errorPromise; + expect(error.message).toContain("API key"); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather data", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(result.temperature).toBe(-0.26); + expect(result.feelsLikeTemp).toBe(-4.77); + expect(result.windSpeed).toBe(2.32); + expect(result.windFromDirection).toBe(166); + expect(Math.round(result.humidity)).toBe(56); // 0.56 * 100 with rounding + }); + + it("should include sunrise/sunset from daily data", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + }); + + it("should convert icon to weather type", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // "cloudy" icon from real data + expect(result.weatherType).toBe("cloudy"); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(8); + const day = result[0]; + expect(day).toHaveProperty("date"); + expect(day).toHaveProperty("minTemperature"); + expect(day).toHaveProperty("maxTemperature"); + expect(day).toHaveProperty("weatherType"); + expect(day).toHaveProperty("precipitationProbability"); + }); + + it("should convert precipitation accumulation from cm to mm", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // First day has precipAccumulation: 0.0 cm + expect(result[0].precipitationAmount).toBe(0); + }); + + it("should categorize precipitation by type", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // First day has precipType: "snow" + expect(result[0].rain).toBe(0); + expect(result[0].snow).toBe(0); + + // Second day has precipType: "snow" with 0.0 accumulation + expect(result[1].rain).toBe(0); + expect(result[1].snow).toBe(0); + }); + + it("should convert precipitation probability to percentage", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // 0.33 -> 33% + expect(result[0].precipitationProbability).toBe(33); + }); + }); + + describe("Hourly Parsing", () => { + it("should parse hourly forecast data", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(48); + + const hour = result[0]; + expect(hour).toHaveProperty("date"); + expect(hour).toHaveProperty("temperature"); + expect(hour).toHaveProperty("feelsLikeTemp"); + expect(hour).toHaveProperty("windSpeed"); + expect(hour).toHaveProperty("weatherType"); + }); + + it("should handle hourly precipitation", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json(pirateweatherData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // First hour has 0.0 cm precipitation + expect(result[0].precipitationAmount).toBe(0); + expect(result[0].rain).toBe(0); + }); + }); + + describe("Error Handling", () => { + it("should handle invalid JSON response", async () => { + const provider = new PirateweatherProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get(PIRATEWEATHER_URL, () => { + return HttpResponse.json({}); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error.message).toContain("No usable data"); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/smhi_spec.js b/tests/unit/modules/default/weather/providers/smhi_spec.js new file mode 100644 index 0000000000..b7e1211785 --- /dev/null +++ b/tests/unit/modules/default/weather/providers/smhi_spec.js @@ -0,0 +1,208 @@ +/** + * SMHI Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + * SMHI provides data only for Sweden, uses metric system. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +import smhiData from "../../../../../mocks/weather_smhi.json" with { type: "json" }; + +let server; + +beforeAll(() => { + server = setupServer(); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("SMHIProvider", () => { + let SMHIProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/smhi"); + SMHIProvider = module.default; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new SMHIProvider({ + lat: 59.3293, + lon: 18.0686 + }); + expect(provider.config.lat).toBe(59.3293); + expect(provider.config.lon).toBe(18.0686); + expect(provider.config.precipitationValue).toBe("pmedian"); + }); + + it("should fallback to pmedian for invalid precipitationValue", () => { + const provider = new SMHIProvider({ + precipitationValue: "invalid" + }); + expect(provider.config.precipitationValue).toBe("pmedian"); + }); + + it("should accept valid precipitationValue options", () => { + for (const value of ["pmin", "pmean", "pmedian", "pmax"]) { + const provider = new SMHIProvider({ precipitationValue: value }); + expect(provider.config.precipitationValue).toBe(value); + } + }); + }); + + describe("Coordinate Validation", () => { + it("should limit coordinates to 6 decimal places", async () => { + const provider = new SMHIProvider({ + lat: 59.32930123456789, + lon: 18.06860123456789 + }); + provider.setCallbacks(vi.fn(), vi.fn()); + + server.use( + http.get("https://opendata-download-metfcst.smhi.se/*", () => { + return HttpResponse.json(smhiData); + }) + ); + + await provider.initialize(); + + // After validateCoordinates(config, 6), decimals should be truncated + expect(provider.config.lat.toString().split(".")[1]?.length).toBeLessThanOrEqual(6); + expect(provider.config.lon.toString().split(".")[1]?.length).toBeLessThanOrEqual(6); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather from timeSeries", async () => { + const provider = new SMHIProvider({ + lat: 59.3293, + lon: 18.0686, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://opendata-download-metfcst.smhi.se/*", () => { + return HttpResponse.json(smhiData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(typeof result.temperature).toBe("number"); + expect(typeof result.windSpeed).toBe("number"); + expect(typeof result.humidity).toBe("number"); + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + }); + + it("should detect precipitation category correctly", async () => { + const provider = new SMHIProvider({ + lat: 59.3293, + lon: 18.0686, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + // Use data with rain (pcat=3 at index 2) + 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(); + + server.use( + http.get("https://opendata-download-metfcst.smhi.se/*", () => { + return HttpResponse.json(rainData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.rain).toBe(0.0); // pmedian value with pcat=3 (rain) + expect(result.precipitationAmount).toBe(0.0); + expect(result.snow).toBe(0); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data", async () => { + const provider = new SMHIProvider({ + lat: 59.3293, + lon: 18.0686, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get("https://opendata-download-metfcst.smhi.se/*", () => { + return HttpResponse.json(smhiData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const firstDay = result[0]; + expect(firstDay).toHaveProperty("date"); + expect(firstDay).toHaveProperty("minTemperature"); + expect(firstDay).toHaveProperty("maxTemperature"); + expect(firstDay.minTemperature).toBeLessThanOrEqual(firstDay.maxTemperature); + }); + }); + + describe("Error Handling", () => { + it("should call error callback on invalid data", async () => { + const provider = new SMHIProvider({ + lat: 59.3293, + lon: 18.0686, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get("https://opendata-download-metfcst.smhi.se/*", () => { + return HttpResponse.json({ invalid: true }); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error).toHaveProperty("message"); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/ukmetofficedatahub_spec.js b/tests/unit/modules/default/weather/providers/ukmetofficedatahub_spec.js new file mode 100644 index 0000000000..7bda9a6b09 --- /dev/null +++ b/tests/unit/modules/default/weather/providers/ukmetofficedatahub_spec.js @@ -0,0 +1,348 @@ +/** + * UK Met Office DataHub Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +import hourlyData from "../../../../../mocks/weather_ukmetoffice.json" with { type: "json" }; +import dailyData from "../../../../../mocks/weather_ukmetoffice_daily.json" with { type: "json" }; + +const UKMETOFFICE_HOURLY_URL = "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/hourly*"; +const UKMETOFFICE_THREE_HOURLY_URL = "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/three-hourly*"; +const UKMETOFFICE_DAILY_URL = "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/daily*"; + +/** + * Returns a copy of the daily mock response with dates shifted to today and future days. + * @param {object} source Source UK Met Office daily mock payload. + * @returns {object} Cloned payload with deterministic future dates in `timeSeries`. + */ +function withFutureDailyTimes (source) { + const clone = JSON.parse(JSON.stringify(source)); + const today = new Date(); + today.setUTCHours(0, 0, 0, 0); + + clone.features[0].properties.timeSeries = clone.features[0].properties.timeSeries.map((day, index) => { + const shiftedDate = new Date(today); + shiftedDate.setUTCDate(today.getUTCDate() + index); + + return { + ...day, + time: `${shiftedDate.toISOString().split("T")[0]}T00:00Z` + }; + }); + + return clone; +} + +let server; + +beforeAll(() => { + server = setupServer(); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("UKMetOfficeDataHubProvider", () => { + let UKMetOfficeDataHubProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/ukmetofficedatahub"); + UKMetOfficeDataHubProvider = module.default || module; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-api-key", + lat: 51.5, + lon: -0.12, + type: "current" + }); + expect(provider.config.apiKey).toBe("test-api-key"); + expect(provider.config.lat).toBe(51.5); + expect(provider.config.lon).toBe(-0.12); + }); + + it("should error if API key is missing", async () => { + const provider = new UKMetOfficeDataHubProvider({ + lat: 51.5, + lon: -0.12 + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + await provider.initialize(); + + const error = await errorPromise; + expect(error.message).toContain("API key"); + }); + }); + + describe("Forecast Type Mapping", () => { + it("should use hourly endpoint for current type", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "current" + }); + + let requestedUrl = null; + server.use( + http.get(UKMETOFFICE_HOURLY_URL, ({ request }) => { + requestedUrl = request.url; + return HttpResponse.json(hourlyData); + }) + ); + + provider.setCallbacks(vi.fn(), vi.fn()); + await provider.initialize(); + provider.start(); + + await new Promise((resolve) => setTimeout(resolve, 100)); + expect(requestedUrl).toContain("/hourly?"); + }); + + it("should use daily endpoint for forecast type", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "forecast" + }); + + let requestedUrl = null; + server.use( + http.get(UKMETOFFICE_DAILY_URL, ({ request }) => { + requestedUrl = request.url; + return HttpResponse.json(dailyData); + }) + ); + + provider.setCallbacks(vi.fn(), vi.fn()); + await provider.initialize(); + provider.start(); + + await new Promise((resolve) => setTimeout(resolve, 100)); + expect(requestedUrl).toContain("/daily?"); + }); + + it("should use three-hourly endpoint for hourly type", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "hourly" + }); + + let requestedUrl = null; + server.use( + http.get(UKMETOFFICE_THREE_HOURLY_URL, ({ request }) => { + requestedUrl = request.url; + return HttpResponse.json(hourlyData); + }) + ); + + provider.setCallbacks(vi.fn(), vi.fn()); + await provider.initialize(); + provider.start(); + + await new Promise((resolve) => setTimeout(resolve, 100)); + expect(requestedUrl).toContain("/three-hourly?"); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather from hourly data", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(UKMETOFFICE_HOURLY_URL, () => { + return HttpResponse.json(hourlyData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(result.temperature).toBeDefined(); + expect(result.windSpeed).toBeDefined(); + expect(result.humidity).toBeDefined(); + expect(result.weatherType).not.toBeNull(); + }); + + it("should include sunrise/sunset from SunCalc", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(UKMETOFFICE_HOURLY_URL, () => { + return HttpResponse.json(hourlyData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + }); + + it("should convert weather code to weather type", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(UKMETOFFICE_HOURLY_URL, () => { + return HttpResponse.json(hourlyData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.weatherType).toBeTruthy(); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(UKMETOFFICE_DAILY_URL, () => { + return HttpResponse.json(withFutureDailyTimes(dailyData)); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const day = result[0]; + expect(day).toHaveProperty("date"); + expect(day).toHaveProperty("minTemperature"); + expect(day).toHaveProperty("maxTemperature"); + expect(day).toHaveProperty("weatherType"); + }); + }); + + describe("Hourly Parsing", () => { + it("should parse hourly forecast data", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(UKMETOFFICE_THREE_HOURLY_URL, () => { + return HttpResponse.json(hourlyData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const hour = result[0]; + expect(hour).toHaveProperty("date"); + expect(hour).toHaveProperty("temperature"); + expect(hour).toHaveProperty("windSpeed"); + expect(hour).toHaveProperty("weatherType"); + }); + }); + + describe("Error Handling", () => { + it("should handle invalid response", async () => { + const provider = new UKMetOfficeDataHubProvider({ + apiKey: "test-key", + lat: 51.5, + lon: -0.12, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get(UKMETOFFICE_HOURLY_URL, () => { + return HttpResponse.json({}); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error).toHaveProperty("message"); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/weatherapi_spec.js b/tests/unit/modules/default/weather/providers/weatherapi_spec.js new file mode 100644 index 0000000000..413360f61c --- /dev/null +++ b/tests/unit/modules/default/weather/providers/weatherapi_spec.js @@ -0,0 +1,311 @@ +/** + * WeatherAPI Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +const WEATHER_API_URL = "https://api.weatherapi.com/v1/forecast.json*"; + +/** + * Builds a stable WeatherAPI mock payload for current, daily, and hourly parsing tests. + * @returns {object} WeatherAPI forecast response fixture. + */ +function buildWeatherApiResponse () { + return { + location: { + name: "Toronto", + region: "Ontario", + country: "Canada" + }, + current: { + last_updated_epoch: 4102444800, + temp_c: -2.5, + feelslike_c: -7.1, + humidity: 75, + wind_kph: 18, + wind_degree: 220, + condition: { code: 1003 }, + is_day: 1, + snow_cm: 0.2, + precip_mm: 1.1, + uv: 2 + }, + forecast: { + forecastday: [ + { + date: "2100-01-01", + date_epoch: 4102444800, + astro: { + sunrise: "07:45 AM", + sunset: "05:05 PM" + }, + day: { + mintemp_c: -8, + maxtemp_c: -1, + avgtemp_c: -4, + avghumidity: 81, + totalsnow_cm: 0.6, + totalprecip_mm: 2, + maxwind_kph: 22, + uv: 1, + condition: { code: 1183 } + }, + hour: [ + { + time: "2100-01-01 01:00", + time_epoch: 4102448400, + temp_c: -5, + humidity: 85, + wind_kph: 15, + wind_degree: 210, + wind_dir: "SSW", + condition: { code: 1183 }, + is_day: 0, + snow_cm: 0.1, + precip_mm: 0.5, + will_it_rain: 1, + will_it_snow: 0, + uv: 0 + }, + { + time: "2100-01-01 02:00", + time_epoch: 4102452000, + temp_c: -4.5, + humidity: 83, + wind_kph: 13, + wind_degree: 205, + wind_dir: "SSW", + condition: { code: 1003 }, + is_day: 0, + snow_cm: 0, + precip_mm: 0.2, + will_it_rain: 0, + will_it_snow: 0, + uv: 0 + }, + { + time: "2100-01-01 03:00", + time_epoch: 4102455600, + temp_c: -4, + humidity: 80, + wind_kph: 12, + wind_degree: 200, + wind_dir: "SSW", + condition: { code: 1000 }, + is_day: 0, + snow_cm: 0, + precip_mm: 0, + will_it_rain: 0, + will_it_snow: 0, + uv: 0 + } + ] + }, + { + date: "2100-01-02", + date_epoch: 4102531200, + astro: { + sunrise: "07:44 AM", + sunset: "05:06 PM" + }, + day: { + mintemp_c: -7, + maxtemp_c: 0, + avgtemp_c: -3.3, + avghumidity: 78, + totalsnow_cm: 0, + totalprecip_mm: 0.4, + maxwind_kph: 20, + uv: 2, + condition: { code: 1006 } + }, + hour: [] + } + ] + } + }; +} + +let server; + +beforeAll(() => { + server = setupServer(); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("WeatherAPIProvider", () => { + let WeatherAPIProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/weatherapi"); + WeatherAPIProvider = module.default; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new WeatherAPIProvider({ + lat: 43.65, + lon: -79.38, + apiKey: "test-key", + type: "current" + }); + expect(provider.config.lat).toBe(43.65); + expect(provider.config.lon).toBe(-79.38); + expect(provider.config.apiKey).toBe("test-key"); + expect(provider.config.type).toBe("current"); + }); + + it("should have default values", () => { + const provider = new WeatherAPIProvider({ apiKey: "test-key" }); + expect(provider.config.apiBase).toBe("https://api.weatherapi.com/v1"); + expect(provider.config.type).toBe("current"); + expect(provider.config.maxEntries).toBe(5); + expect(provider.config.updateInterval).toBe(10 * 60 * 1000); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather data correctly", async () => { + const provider = new WeatherAPIProvider({ + lat: 43.65, + lon: -79.38, + apiKey: "test-key", + type: "current" + }); + + const dataPromise = new Promise((resolve, reject) => { + provider.setCallbacks(resolve, reject); + }); + + server.use( + http.get(WEATHER_API_URL, () => HttpResponse.json(buildWeatherApiResponse())) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(result.temperature).toBe(-2.5); + expect(result.feelsLikeTemp).toBe(-7.1); + expect(result.humidity).toBe(75); + expect(result.windSpeed).toBeCloseTo(5, 1); + expect(result.windFromDirection).toBe(220); + expect(result.weatherType).toBe("day-cloudy"); + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + expect(result.minTemperature).toBe(-8); + expect(result.maxTemperature).toBe(-1); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data correctly", async () => { + const provider = new WeatherAPIProvider({ + lat: 43.65, + lon: -79.38, + apiKey: "test-key", + type: "forecast", + maxEntries: 2, + maxNumberOfDays: 2 + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHER_API_URL, () => HttpResponse.json(buildWeatherApiResponse())) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(2); + expect(result[0].minTemperature).toBe(-8); + expect(result[0].maxTemperature).toBe(-1); + expect(result[0].weatherType).toBe("day-sprinkle"); + expect(result[0].sunrise).toBeInstanceOf(Date); + expect(result[0].sunset).toBeInstanceOf(Date); + }); + }); + + describe("Hourly Parsing", () => { + it("should parse hourly forecast data correctly", async () => { + const provider = new WeatherAPIProvider({ + lat: 43.65, + lon: -79.38, + apiKey: "test-key", + type: "hourly", + maxEntries: 3, + maxNumberOfDays: 1 + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHER_API_URL, () => HttpResponse.json(buildWeatherApiResponse())) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(3); + expect(result[0].temperature).toBe(-5); + expect(result[0].humidity).toBe(85); + expect(result[0].windFromDirection).toBe(210); + expect(result[0].weatherType).toBe("night-sprinkle"); + expect(result[0].precipitationProbability).toBe(50); + }); + }); + + describe("Error Handling", () => { + it("should call error callback on invalid API response", async () => { + const provider = new WeatherAPIProvider({ + lat: 43.65, + lon: -79.38, + apiKey: "test-key", + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get(WEATHER_API_URL, () => HttpResponse.json({ + location: {}, + current: {}, + forecast: { forecastday: "invalid" } + })) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error).toHaveProperty("message"); + expect(error).toHaveProperty("translationKey"); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/weatherbit_spec.js b/tests/unit/modules/default/weather/providers/weatherbit_spec.js new file mode 100644 index 0000000000..8bea45f141 --- /dev/null +++ b/tests/unit/modules/default/weather/providers/weatherbit_spec.js @@ -0,0 +1,247 @@ +/** + * Weatherbit Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +import currentData from "../../../../../mocks/weather_weatherbit.json" with { type: "json" }; +import forecastData from "../../../../../mocks/weather_weatherbit_forecast.json" with { type: "json" }; +import hourlyData from "../../../../../mocks/weather_weatherbit_hourly.json" with { type: "json" }; + +const WEATHERBIT_CURRENT_URL = "https://api.weatherbit.io/v2.0/current*"; +const WEATHERBIT_FORECAST_URL = "https://api.weatherbit.io/v2.0/forecast/daily*"; +const WEATHERBIT_HOURLY_URL = "https://api.weatherbit.io/v2.0/forecast/hourly*"; + +let server; + +beforeAll(() => { + server = setupServer(); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("WeatherbitProvider", () => { + let WeatherbitProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/weatherbit"); + WeatherbitProvider = module.default || module; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new WeatherbitProvider({ + apiKey: "test-api-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + expect(provider.config.apiKey).toBe("test-api-key"); + expect(provider.config.lat).toBe(40.71); + expect(provider.config.lon).toBe(-74.0); + }); + + it("should error if API key is missing", async () => { + const provider = new WeatherbitProvider({ + lat: 40.71, + lon: -74.0 + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + await provider.initialize(); + + const error = await errorPromise; + expect(error.message).toContain("API key"); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather data", async () => { + const provider = new WeatherbitProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERBIT_CURRENT_URL, () => { + return HttpResponse.json(currentData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(result.temperature).toBe(1); + expect(result.windSpeed).toBe(1.5); + expect(result.windFromDirection).toBe(210); + expect(result.humidity).toBe(47); + }); + + it("should parse sunrise/sunset from HH:mm format", async () => { + const provider = new WeatherbitProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERBIT_CURRENT_URL, () => { + return HttpResponse.json(currentData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + }); + + it("should convert icon code to weather type", async () => { + const provider = new WeatherbitProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERBIT_CURRENT_URL, () => { + return HttpResponse.json(currentData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.weatherType).not.toBeNull(); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data", async () => { + const provider = new WeatherbitProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERBIT_FORECAST_URL, () => { + return HttpResponse.json(forecastData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const day = result[0]; + expect(day).toHaveProperty("date"); + expect(day).toHaveProperty("minTemperature"); + expect(day).toHaveProperty("maxTemperature"); + expect(day).toHaveProperty("weatherType"); + expect(day).toHaveProperty("precipitationProbability"); + }); + }); + + describe("Hourly Parsing", () => { + it("should handle hourly API endpoint access error", async () => { + const provider = new WeatherbitProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "hourly" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get(WEATHERBIT_HOURLY_URL, () => { + return HttpResponse.json(hourlyData); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + + expect(error).toBeDefined(); + expect(error.message || error).toContain("No usable data"); + }); + }); + + describe("Error Handling", () => { + it("should handle invalid response", async () => { + const provider = new WeatherbitProvider({ + apiKey: "test-key", + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get(WEATHERBIT_CURRENT_URL, () => { + return HttpResponse.json({ data: [] }); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error).toHaveProperty("message"); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/weatherflow_spec.js b/tests/unit/modules/default/weather/providers/weatherflow_spec.js new file mode 100644 index 0000000000..2eb2fdb4a4 --- /dev/null +++ b/tests/unit/modules/default/weather/providers/weatherflow_spec.js @@ -0,0 +1,264 @@ +/** + * WeatherFlow Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +import weatherflowData from "../../../../../mocks/weather_weatherflow.json" with { type: "json" }; + +const WEATHERFLOW_URL = "https://swd.weatherflow.com/swd/rest/better_forecast*"; + +let server; + +beforeAll(() => { + server = setupServer(); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +describe("WeatherFlowProvider", () => { + let WeatherFlowProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/weatherflow"); + WeatherFlowProvider = module.default || module; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new WeatherFlowProvider({ + token: "test-token", + stationid: "12345", + type: "current" + }); + expect(provider.config.token).toBe("test-token"); + expect(provider.config.stationid).toBe("12345"); + }); + + it("should error if token or stationid is missing", async () => { + const provider = new WeatherFlowProvider({}); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + await provider.initialize(); + + const error = await errorPromise; + expect(error.message).toContain("token"); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather data", async () => { + const provider = new WeatherFlowProvider({ + token: "test-token", + stationid: "12345", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERFLOW_URL, () => { + return HttpResponse.json(weatherflowData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(result.temperature).toBe(16); + expect(result.humidity).toBe(28); + expect(result.weatherType).not.toBeNull(); + }); + + it("should convert wind speed from km/h to m/s", async () => { + const provider = new WeatherFlowProvider({ + token: "test-token", + stationid: "12345", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERFLOW_URL, () => { + return HttpResponse.json(weatherflowData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Wind speed 15 km/h -> ~4.17 m/s + expect(result.windSpeed).toBeCloseTo(4.17, 1); + }); + + it("should include sunrise/sunset", async () => { + const provider = new WeatherFlowProvider({ + token: "test-token", + stationid: "12345", + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERFLOW_URL, () => { + return HttpResponse.json(weatherflowData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data", async () => { + const provider = new WeatherFlowProvider({ + token: "test-token", + stationid: "12345", + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERFLOW_URL, () => { + return HttpResponse.json(weatherflowData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const day = result[0]; + expect(day).toHaveProperty("date"); + expect(day).toHaveProperty("minTemperature"); + expect(day).toHaveProperty("maxTemperature"); + expect(day).toHaveProperty("weatherType"); + }); + }); + + describe("Hourly Parsing", () => { + it("should parse hourly forecast data", async () => { + const provider = new WeatherFlowProvider({ + token: "test-token", + stationid: "12345", + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERFLOW_URL, () => { + return HttpResponse.json(weatherflowData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const hour = result[0]; + expect(hour).toHaveProperty("date"); + expect(hour).toHaveProperty("temperature"); + expect(hour).toHaveProperty("windSpeed"); + }); + + it("should aggregate UV data from hourly forecasts", async () => { + const provider = new WeatherFlowProvider({ + token: "test-token", + stationid: "12345", + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERFLOW_URL, () => { + return HttpResponse.json(weatherflowData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // First day should have UV from hourly data + expect(result[0]).toHaveProperty("uvIndex"); + expect(result[0].uvIndex).toBeGreaterThanOrEqual(0); + }); + }); + + describe("Error Handling", () => { + it("should handle invalid response", async () => { + const provider = new WeatherFlowProvider({ + token: "test-token", + stationid: "12345", + type: "current" + }); + + // Invalid responses return null without calling error callback + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERFLOW_URL, () => { + return HttpResponse.json({}); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + expect(result).toBeNull(); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/weathergov_spec.js b/tests/unit/modules/default/weather/providers/weathergov_spec.js new file mode 100644 index 0000000000..81a7edd94f --- /dev/null +++ b/tests/unit/modules/default/weather/providers/weathergov_spec.js @@ -0,0 +1,412 @@ +/** + * Weather.gov Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + * Weather.gov is the US National Weather Service API. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest"; + +import pointsData from "../../../../../mocks/weather_weathergov_points.json" with { type: "json" }; +import stationsData from "../../../../../mocks/weather_weathergov_stations.json" with { type: "json" }; +import currentData from "../../../../../mocks/weather_weathergov_current.json" with { type: "json" }; +import forecastData from "../../../../../mocks/weather_weathergov_forecast.json" with { type: "json" }; +import hourlyData from "../../../../../mocks/weather_weathergov_hourly.json" with { type: "json" }; + +const WEATHERGOV_POINTS_URL = "https://api.weather.gov/points/*"; +const WEATHERGOV_STATIONS_URL = "https://api.weather.gov/gridpoints/*/stations"; +const WEATHERGOV_CURRENT_URL = "https://api.weather.gov/stations/*/observations/latest"; +const WEATHERGOV_FORECAST_URL = "https://api.weather.gov/gridpoints/*/forecast*"; +const WEATHERGOV_HOURLY_URL = "https://api.weather.gov/gridpoints/*/forecast/hourly*"; + +let server; + +beforeAll(() => { + server = setupServer( + // Default handlers for initialization + http.get(WEATHERGOV_POINTS_URL, () => { + return HttpResponse.json(pointsData); + }), + http.get(WEATHERGOV_STATIONS_URL, () => { + return HttpResponse.json(stationsData); + }) + ); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +afterEach(() => { + server.resetHandlers(); + // Re-add default initialization handlers + server.use( + http.get(WEATHERGOV_POINTS_URL, () => { + return HttpResponse.json(pointsData); + }), + http.get(WEATHERGOV_STATIONS_URL, () => { + return HttpResponse.json(stationsData); + }) + ); +}); + +describe("WeatherGovProvider", () => { + let WeatherGovProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/weathergov"); + WeatherGovProvider = module.default || module; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "current" + }); + expect(provider.config.lat).toBe(40.71); + expect(provider.config.lon).toBe(-74.0); + expect(provider.config.type).toBe("current"); + }); + + it("should have default update interval", () => { + const provider = new WeatherGovProvider({}); + expect(provider.config.updateInterval).toBe(600000); // 10 minutes + }); + }); + + describe("Two-Step Initialization", () => { + it("should fetch points URL and then stations URL", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "current" + }); + + provider.setCallbacks(vi.fn(), vi.fn()); + + let pointsRequested = false; + let stationsRequested = false; + + server.use( + http.get(WEATHERGOV_POINTS_URL, () => { + pointsRequested = true; + return HttpResponse.json(pointsData); + }), + http.get(WEATHERGOV_STATIONS_URL, () => { + stationsRequested = true; + return HttpResponse.json(stationsData); + }) + ); + + await provider.initialize(); + + expect(pointsRequested).toBe(true); + expect(stationsRequested).toBe(true); + expect(provider.locationName).toBe("Washington, DC"); + }); + + it("should store forecast URLs after initialization", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0 + }); + + provider.setCallbacks(vi.fn(), vi.fn()); + await provider.initialize(); + + expect(provider.forecastURL).toContain("forecast?units=si"); + expect(provider.forecastHourlyURL).toContain("forecast/hourly?units=si"); + expect(provider.stationObsURL).toContain("observations/latest"); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather data", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERGOV_CURRENT_URL, () => { + return HttpResponse.json(currentData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(result.temperature).toBe(-1); + expect(result.windSpeed).toBe(0); + expect(result.windFromDirection).toBe(0); + expect(result.humidity).toBe(64); // Rounded from 63.77 + expect(result.weatherType).not.toBeNull(); + }); + + it("should use heat index or wind chill for feels like temperature", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERGOV_CURRENT_URL, () => { + return HttpResponse.json(currentData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Real data has null windChill - falls back to temperature + expect(result.feelsLikeTemp).toBe(-1); + }); + + it("should include sunrise/sunset", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERGOV_CURRENT_URL, () => { + return HttpResponse.json(currentData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERGOV_FORECAST_URL, () => { + return HttpResponse.json(forecastData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const day = result[0]; + expect(day).toHaveProperty("date"); + expect(day).toHaveProperty("minTemperature"); + expect(day).toHaveProperty("maxTemperature"); + expect(day).toHaveProperty("weatherType"); + expect(day).toHaveProperty("precipitationProbability"); + }); + }); + + describe("Hourly Parsing", () => { + it("should parse hourly forecast data", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERGOV_HOURLY_URL, () => { + return HttpResponse.json(hourlyData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result).toHaveLength(156); // Real API returns 156 hourly periods + expect(result[0]).toHaveProperty("temperature"); + expect(result[0]).toHaveProperty("windSpeed"); + expect(result[0]).toHaveProperty("windFromDirection"); + expect(result[0]).toHaveProperty("weatherType"); + }); + + it("should convert wind direction strings to degrees", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERGOV_HOURLY_URL, () => { + return HttpResponse.json(hourlyData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Real data has "S" wind for both hours + expect(result[0].windFromDirection).toBe(180); + // Third hour also has "S" wind + expect(result[2].windFromDirection).toBe(180); + }); + + it("should parse wind speed with units", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERGOV_HOURLY_URL, () => { + return HttpResponse.json(hourlyData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Wind speeds should be converted from km/h to m/s + expect(result[0].windSpeed).toBeCloseTo(1.11, 1); // Real data: 4 km/h -> ~1.11 m/s + }); + }); + + describe("Error Handling", () => { + it("should categorize DNS errors as retryable", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get(WEATHERGOV_POINTS_URL, () => { + return HttpResponse.error(); + }) + ); + + await provider.initialize(); + + // Should call error callback + const error = await errorPromise; + expect(error).toHaveProperty("message"); + }); + + it("should handle invalid JSON response", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get(WEATHERGOV_CURRENT_URL, () => { + return HttpResponse.json({ properties: null }); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error.message).toContain("Invalid"); + }); + }); + + describe("Weather Type Conversion", () => { + it("should convert textDescription to weather types", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + const testData = JSON.parse(JSON.stringify(currentData)); + testData.properties.textDescription = "Thunderstorm"; + + server.use( + http.get(WEATHERGOV_CURRENT_URL, () => { + return HttpResponse.json(testData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Thunderstorm should map to day or night thunderstorm + expect(["thunderstorm", "night-thunderstorm"]).toContain(result.weatherType); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/providers/yr_spec.js b/tests/unit/modules/default/weather/providers/yr_spec.js new file mode 100644 index 0000000000..4602a8d840 --- /dev/null +++ b/tests/unit/modules/default/weather/providers/yr_spec.js @@ -0,0 +1,287 @@ +/** + * Yr.no Weather Provider Tests + * + * Tests data parsing for current, forecast, and hourly weather types. + * Yr.no is the Norwegian Meteorological Institute API. + * + * Uses fake timers to ensure deterministic timeseries selection. + * The provider picks the closest past entry from timeseries based on new Date(). + * Fixed to 2026-02-06T21:30:00Z → selects timeseries[0] at 21:00 with T=-5.8°C. + */ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { describe, it, expect, vi, beforeAll, beforeEach, afterAll, afterEach } from "vitest"; + +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. +const FAKE_NOW = new Date("2026-02-06T21:30:00Z"); + +let server; + +beforeAll(() => { + server = setupServer( + http.get(({ request }) => request.url.includes("/locationforecast/"), () => { + return HttpResponse.json(yrData); + }), + http.get(({ request }) => request.url.includes("/sunrise/"), () => { + return HttpResponse.json({ + when: { interval: ["2026-02-06T00:00:00+01:00"] }, + properties: { + sunrise: { time: "2026-02-06T08:30:00+01:00" }, + sunset: { time: "2026-02-06T16:30:00+01:00" } + } + }); + }) + ); + server.listen({ onUnhandledRequest: "bypass" }); +}); + +afterAll(() => { + server.close(); +}); + +beforeEach(() => { + vi.useFakeTimers({ now: FAKE_NOW }); +}); + +afterEach(() => { + vi.useRealTimers(); + server.resetHandlers(); +}); + +describe("YrProvider", () => { + let YrProvider; + + beforeAll(async () => { + const module = await import("../../../../../../defaultmodules/weather/providers/yr"); + YrProvider = module.default; + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + const provider = new YrProvider({ + lat: 59.91, + lon: 10.72, + altitude: 94 + }); + expect(provider.config.lat).toBe(59.91); + expect(provider.config.lon).toBe(10.72); + expect(provider.config.altitude).toBe(94); + }); + + it("should enforce minimum 10-minute update interval", () => { + const provider = new YrProvider({ + updateInterval: 60000 // 1 minute - too short + }); + expect(provider.config.updateInterval).toBe(600000); + }); + + it("should allow intervals >= 10 minutes", () => { + const provider = new YrProvider({ + updateInterval: 900000 // 15 minutes + }); + expect(provider.config.updateInterval).toBe(900000); + }); + }); + + describe("Coordinate Validation", () => { + it("should limit coordinates to 4 decimal places", async () => { + const provider = new YrProvider({ + lat: 59.91234567, + lon: 10.72345678 + }); + provider.setCallbacks(vi.fn(), vi.fn()); + + server.use( + http.get(YR_FORECAST_URL, () => { + return HttpResponse.json(yrData); + }) + ); + + await provider.initialize(); + + expect(provider.config.lat.toString().split(".")[1]?.length).toBeLessThanOrEqual(4); + expect(provider.config.lon.toString().split(".")[1]?.length).toBeLessThanOrEqual(4); + }); + }); + + describe("Current Weather Parsing", () => { + it("should parse current weather from timeseries", async () => { + const provider = new YrProvider({ + lat: 59.91, + lon: 10.72, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(YR_FORECAST_URL, () => { + return HttpResponse.json(yrData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + // With fake time at 21:30, provider selects timeseries[0] (21:00 UTC) + expect(result.temperature).toBe(-5.8); + expect(result.windSpeed).toBe(6.0); + expect(result.windFromDirection).toBe(37.0); + expect(result.humidity).toBe(66.5); + // 21:00 is after sunset (16:30), symbol_code "snow" maps to "snow" + expect(result.weatherType).toBe("snow"); + }); + + it("should include sunrise/sunset from stellar data", async () => { + const provider = new YrProvider({ + lat: 59.91, + lon: 10.72, + type: "current" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(result).toBeDefined(); + expect(result.sunrise).toBeInstanceOf(Date); + expect(result.sunset).toBeInstanceOf(Date); + expect(result.sunset.getTime()).toBeGreaterThan(result.sunrise.getTime()); + }); + }); + + describe("Forecast Parsing", () => { + it("should parse daily forecast data", async () => { + const provider = new YrProvider({ + lat: 59.91, + lon: 10.72, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(YR_FORECAST_URL, () => { + return HttpResponse.json(yrData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const day = result[0]; + expect(day).toHaveProperty("date"); + expect(day).toHaveProperty("minTemperature"); + expect(day).toHaveProperty("maxTemperature"); + expect(day.minTemperature).toBeLessThanOrEqual(day.maxTemperature); + }); + }); + + describe("Hourly Parsing", () => { + it("should parse hourly forecast data", async () => { + const provider = new YrProvider({ + lat: 59.91, + lon: 10.72, + type: "hourly" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(YR_FORECAST_URL, () => { + return HttpResponse.json(yrData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBeGreaterThan(0); + + const hour = result[0]; + expect(hour).toHaveProperty("temperature"); + expect(hour).toHaveProperty("windSpeed"); + expect(hour).toHaveProperty("precipitationAmount"); + expect(hour).toHaveProperty("weatherType"); + }); + }); + + describe("Error Handling", () => { + it("should call error callback on invalid data", async () => { + const provider = new YrProvider({ + lat: 59.91, + lon: 10.72, + type: "current" + }); + + const errorPromise = new Promise((resolve) => { + provider.setCallbacks(vi.fn(), resolve); + }); + + server.use( + http.get(YR_FORECAST_URL, () => { + return HttpResponse.json({ properties: {} }); + }) + ); + + await provider.initialize(); + provider.start(); + + const error = await errorPromise; + expect(error).toHaveProperty("message"); + }); + }); + + describe("Weather Type Conversion", () => { + it("should convert yr symbol codes correctly", async () => { + const provider = new YrProvider({ + lat: 59.91, + lon: 10.72, + type: "current", + currentForecastHours: 1 + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + // Uses yrData from beforeAll which has symbol_code "snow" + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // 21:00 is after sunset (16:30), next_1_hours symbol_code is "snow" + expect(result.weatherType).toBe("snow"); + }); + }); +}); diff --git a/tests/unit/modules/default/weather/weather_providers_spec.js b/tests/unit/modules/default/weather/weather_providers_spec.js new file mode 100644 index 0000000000..4d226da202 --- /dev/null +++ b/tests/unit/modules/default/weather/weather_providers_spec.js @@ -0,0 +1,189 @@ +/** + * Weather Provider Smoke Tests + * + * Tests basic provider functionality: configuration, callbacks, and validation. + * Parser logic with private methods (#) is validated through live testing. + */ +import { describe, it, expect, vi, beforeEach, beforeAll, afterAll } from "vitest"; + +// Mock global fetch for location lookup +const originalFetch = global.fetch; + +global.fetch = vi.fn(() => Promise.resolve({ + ok: true, + json: () => Promise.resolve({ city: "Munich", locality: "Munich" }) +})); + +// Restore original fetch after all tests +afterAll(() => { + global.fetch = originalFetch; +}); + +describe("Weather Provider Smoke Tests", () => { + describe("OpenMeteoProvider", () => { + let OpenMeteoProvider; + let provider; + + beforeAll(async () => { + const module = await import("../../../../../defaultmodules/weather/providers/openmeteo"); + OpenMeteoProvider = module.default; + }); + + beforeEach(() => { + provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "current", + updateInterval: 600000 + }); + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + expect(provider.config.lat).toBe(48.14); + expect(provider.config.lon).toBe(11.58); + expect(provider.config.type).toBe("current"); + expect(provider.config.updateInterval).toBe(600000); + }); + + it("should have default values", () => { + const defaultProvider = new OpenMeteoProvider({}); + expect(defaultProvider.config.lat).toBe(0); + expect(defaultProvider.config.lon).toBe(0); + expect(defaultProvider.config.type).toBe("current"); + expect(defaultProvider.config.maxNumberOfDays).toBe(5); + }); + + it("should accept all supported types", () => { + expect(new OpenMeteoProvider({ type: "current" }).config.type).toBe("current"); + expect(new OpenMeteoProvider({ type: "forecast" }).config.type).toBe("forecast"); + expect(new OpenMeteoProvider({ type: "hourly" }).config.type).toBe("hourly"); + }); + }); + + describe("Callback Interface", () => { + it("should store callbacks via setCallbacks", () => { + const onData = vi.fn(); + const onError = vi.fn(); + provider.setCallbacks(onData, onError); + expect(provider.onDataCallback).toBe(onData); + expect(provider.onErrorCallback).toBe(onError); + }); + + it("should initialize without callbacks", async () => { + await expect(provider.initialize()).resolves.not.toThrow(); + }); + }); + + describe("Public Methods", () => { + it("should have start/stop methods", () => { + expect(typeof provider.start).toBe("function"); + expect(typeof provider.stop).toBe("function"); + }); + + it("should have initialize method", () => { + expect(typeof provider.initialize).toBe("function"); + }); + + it("should have setCallbacks method", () => { + expect(typeof provider.setCallbacks).toBe("function"); + }); + }); + }); + + describe("OpenWeatherMapProvider", () => { + let OpenWeatherMapProvider; + let provider; + + beforeAll(async () => { + const module = await import("../../../../../defaultmodules/weather/providers/openweathermap"); + OpenWeatherMapProvider = module.default; + }); + + beforeEach(() => { + provider = new OpenWeatherMapProvider({ + lat: 48.14, + lon: 11.58, + apiKey: "test-api-key", + type: "current" + }); + }); + + describe("Constructor & Configuration", () => { + it("should set config values from params", () => { + expect(provider.config.lat).toBe(48.14); + expect(provider.config.lon).toBe(11.58); + expect(provider.config.apiKey).toBe("test-api-key"); + expect(provider.config.type).toBe("current"); + }); + + it("should have default values", () => { + const defaultProvider = new OpenWeatherMapProvider({ apiKey: "test" }); + expect(defaultProvider.config.apiVersion).toBe("3.0"); + expect(defaultProvider.config.weatherEndpoint).toBe("/onecall"); + expect(defaultProvider.config.apiBase).toBe("https://api.openweathermap.org/data/"); + }); + + it("should accept all supported types", () => { + expect(new OpenWeatherMapProvider({ apiKey: "test", type: "current" }).config.type).toBe("current"); + expect(new OpenWeatherMapProvider({ apiKey: "test", type: "forecast" }).config.type).toBe("forecast"); + expect(new OpenWeatherMapProvider({ apiKey: "test", type: "hourly" }).config.type).toBe("hourly"); + }); + }); + + describe("API Key Validation", () => { + it("should call onErrorCallback if no API key provided", async () => { + const noKeyProvider = new OpenWeatherMapProvider({ + lat: 48.14, + lon: 11.58, + apiKey: "" + }); + + const onError = vi.fn(); + noKeyProvider.setCallbacks(vi.fn(), onError); + await noKeyProvider.initialize(); + + expect(onError).toHaveBeenCalledWith( + expect.objectContaining({ + message: "API key is required" + }) + ); + }); + + it("should not create fetcher without API key", async () => { + const noKeyProvider = new OpenWeatherMapProvider({ + apiKey: "" + }); + noKeyProvider.setCallbacks(vi.fn(), vi.fn()); + await noKeyProvider.initialize(); + + expect(noKeyProvider.fetcher).toBeNull(); + }); + }); + + describe("Callback Interface", () => { + it("should store callbacks via setCallbacks", () => { + const onData = vi.fn(); + const onError = vi.fn(); + provider.setCallbacks(onData, onError); + expect(provider.onDataCallback).toBe(onData); + expect(provider.onErrorCallback).toBe(onError); + }); + }); + + describe("Public Methods", () => { + it("should have start/stop methods", () => { + expect(typeof provider.start).toBe("function"); + expect(typeof provider.stop).toBe("function"); + }); + + it("should have initialize method", () => { + expect(typeof provider.initialize).toBe("function"); + }); + + it("should have setCallbacks method", () => { + expect(typeof provider.setCallbacks).toBe("function"); + }); + }); + }); +}); diff --git a/tests/utils/weather_mocker.js b/tests/utils/weather_mocker.js deleted file mode 100644 index c0ebbba1c4..0000000000 --- a/tests/utils/weather_mocker.js +++ /dev/null @@ -1,52 +0,0 @@ -const fs = require("node:fs"); -const path = require("node:path"); -const exec = require("node:child_process").execSync; - -/** - * @param {string} type what data to read, can be "current" "forecast" or "hourly - * @param {object} extendedData extra data to add to the default mock data - * @returns {string} mocked current weather data - */ -const readMockData = (type, extendedData = {}) => { - let fileName; - - switch (type) { - case "forecast": - fileName = "weather_forecast.json"; - break; - case "hourly": - fileName = "weather_hourly.json"; - break; - case "current": - default: - fileName = "weather_current.json"; - break; - } - - const fileData = JSON.parse(fs.readFileSync(path.resolve(`${__dirname}/../mocks/${fileName}`)).toString()); - const mergedData = JSON.stringify({ ...{}, ...fileData, ...extendedData }); - return mergedData; -}; - -const injectMockData = (configFileName, extendedData = {}) => { - let mockWeather; - if (configFileName.includes("forecast")) { - mockWeather = readMockData("forecast", extendedData); - } else if (configFileName.includes("hourly")) { - mockWeather = readMockData("hourly", extendedData); - } else { - mockWeather = readMockData("current", extendedData); - } - let content = fs.readFileSync(configFileName).toString(); - content = content.replace("#####WEATHERDATA#####", mockWeather); - const tempFile = configFileName.replace(".js", "_temp.js"); - fs.writeFileSync(tempFile, content); - return tempFile; -}; - -const cleanupMockData = () => { - const tempDir = path.resolve(`${__dirname}/../configs`).toString(); - exec(`find ${tempDir} -type f -name *_temp.js -delete`); -}; - -module.exports = { injectMockData, cleanupMockData }; From 729f7f0fd1328a3f54b6d2e476adbc95ed5d93e2 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 25 Feb 2026 10:55:56 +0100 Subject: [PATCH 369/418] [core] refactor: enable ESLint rule require-await and handle detected issues (#4038) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable the `require-await` ESLint rule. Async functions without `await` are just regular functions with extra overhead — marking them `async` adds implicit Promise wrapping, can hide missing `return` statements, and misleads readers into expecting asynchronous behavior where there is none. While fixing the violations, I removed unnecessary `async` keywords from source files and from various test callbacks that never used `await`. --- defaultmodules/weather/providers/envcanada.js | 2 +- defaultmodules/weather/providers/openweathermap.js | 2 +- defaultmodules/weather/providers/pirateweather.js | 2 +- defaultmodules/weather/providers/smhi.js | 2 +- .../weather/providers/ukmetofficedatahub.js | 2 +- defaultmodules/weather/providers/weatherapi.js | 2 +- defaultmodules/weather/providers/weatherbit.js | 2 +- defaultmodules/weather/providers/weatherflow.js | 2 +- eslint.config.mjs | 1 + js/loader.js | 6 +++--- js/module.js | 2 +- serveronly/watcher.js | 4 ++-- tests/e2e/clientonly_spec.js | 4 ++-- tests/e2e/config_variables_spec.js | 8 ++++---- tests/e2e/modules/newsfeed_spec.js | 2 +- tests/unit/classes/translator_spec.js | 12 ++++++------ tests/unit/functions/server_functions_spec.js | 2 +- tests/unit/functions/updatenotification_spec.js | 2 +- tests/unit/helpers/global-setup.js | 2 +- tests/unit/modules/default/utils_spec.js | 2 +- .../default/weather/providers/envcanada_spec.js | 4 ++-- .../default/weather/providers/openweathermap_spec.js | 4 ++-- 22 files changed, 36 insertions(+), 35 deletions(-) diff --git a/defaultmodules/weather/providers/envcanada.js b/defaultmodules/weather/providers/envcanada.js index a50a812143..d09715fc19 100644 --- a/defaultmodules/weather/providers/envcanada.js +++ b/defaultmodules/weather/providers/envcanada.js @@ -31,7 +31,7 @@ class EnvCanadaProvider { this.currentHour = null; // Track current hour for URL updates } - async initialize () { + initialize () { this.#validateConfig(); this.#initializeFetcher(); } diff --git a/defaultmodules/weather/providers/openweathermap.js b/defaultmodules/weather/providers/openweathermap.js index c75e1f927c..119df32b36 100644 --- a/defaultmodules/weather/providers/openweathermap.js +++ b/defaultmodules/weather/providers/openweathermap.js @@ -28,7 +28,7 @@ class OpenWeatherMapProvider { this.locationName = null; } - async initialize () { + initialize () { // Validate callbacks exist if (typeof this.onErrorCallback !== "function") { throw new Error("setCallbacks() must be called before initialize()"); diff --git a/defaultmodules/weather/providers/pirateweather.js b/defaultmodules/weather/providers/pirateweather.js index fbf14403b5..539eb877c6 100644 --- a/defaultmodules/weather/providers/pirateweather.js +++ b/defaultmodules/weather/providers/pirateweather.js @@ -24,7 +24,7 @@ class PirateweatherProvider { this.onErrorCallback = onErrorCallback; } - async initialize () { + initialize () { if (!this.config.apiKey) { Log.error("[pirateweather] No API key configured"); if (this.onErrorCallback) { diff --git a/defaultmodules/weather/providers/smhi.js b/defaultmodules/weather/providers/smhi.js index 26deb54ede..70ffba8f9c 100644 --- a/defaultmodules/weather/providers/smhi.js +++ b/defaultmodules/weather/providers/smhi.js @@ -29,7 +29,7 @@ class SMHIProvider { this.onErrorCallback = null; } - async initialize () { + initialize () { try { // SMHI requires max 6 decimal places validateCoordinates(this.config, 6); diff --git a/defaultmodules/weather/providers/ukmetofficedatahub.js b/defaultmodules/weather/providers/ukmetofficedatahub.js index b55a6f2c91..715458b0fd 100644 --- a/defaultmodules/weather/providers/ukmetofficedatahub.js +++ b/defaultmodules/weather/providers/ukmetofficedatahub.js @@ -35,7 +35,7 @@ class UkMetOfficeDataHubProvider { this.onErrorCallback = onErrorCallback; } - async initialize () { + initialize () { if (!this.config.apiKey || this.config.apiKey === "YOUR_API_KEY_HERE") { Log.error("[ukmetofficedatahub] No API key configured"); if (this.onErrorCallback) { diff --git a/defaultmodules/weather/providers/weatherapi.js b/defaultmodules/weather/providers/weatherapi.js index 46aef7f87b..93f2f3195a 100644 --- a/defaultmodules/weather/providers/weatherapi.js +++ b/defaultmodules/weather/providers/weatherapi.js @@ -25,7 +25,7 @@ class WeatherAPIProvider { this.onErrorCallback = null; } - async initialize () { + initialize () { this.#validateConfig(); this.#initializeFetcher(); } diff --git a/defaultmodules/weather/providers/weatherbit.js b/defaultmodules/weather/providers/weatherbit.js index 14a6447668..32c261fed0 100644 --- a/defaultmodules/weather/providers/weatherbit.js +++ b/defaultmodules/weather/providers/weatherbit.js @@ -27,7 +27,7 @@ class WeatherbitProvider { this.onErrorCallback = onErrorCallback; } - async initialize () { + initialize () { if (!this.config.apiKey || this.config.apiKey === "YOUR_API_KEY_HERE") { Log.error("[weatherbit] No API key configured"); if (this.onErrorCallback) { diff --git a/defaultmodules/weather/providers/weatherflow.js b/defaultmodules/weather/providers/weatherflow.js index e4ba4a2006..4797fa02ea 100644 --- a/defaultmodules/weather/providers/weatherflow.js +++ b/defaultmodules/weather/providers/weatherflow.js @@ -31,7 +31,7 @@ class WeatherFlowProvider { /** * Initialize the provider */ - async initialize () { + initialize () { if (!this.config.token || this.config.token === "YOUR_API_TOKEN_HERE") { Log.error("[weatherflow] No API token configured. Get one at https://tempestwx.com/"); if (this.onErrorCallback) { diff --git a/eslint.config.mjs b/eslint.config.mjs index ee3af12c86..8e1ed23c8a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -75,6 +75,7 @@ export default defineConfig([ "object-shorthand": ["error", "methods"], "one-var": "off", "prefer-template": "error", + "require-await": "error", "sort-keys": "off" } }, diff --git a/js/loader.js b/js/loader.js index b6db83869b..53283d59b6 100644 --- a/js/loader.js +++ b/js/loader.js @@ -193,7 +193,7 @@ const Loader = (function () { * @param {string} fileName Path of the file we want to load. * @returns {Promise} resolved when the file is loaded */ - const loadFile = async function (fileName) { + const loadFile = function (fileName) { const extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1); let script, stylesheet; @@ -267,10 +267,10 @@ const Loader = (function () { * @param {Module} module The module that calls the loadFile function. * @returns {Promise} resolved when the file is loaded */ - async loadFileForModule (fileName, module) { + loadFileForModule (fileName, module) { if (loadedFiles.indexOf(fileName.toLowerCase()) !== -1) { Log.log(`File already loaded: ${fileName}`); - return; + return Promise.resolve(); } if (fileName.indexOf("http://") === 0 || fileName.indexOf("https://") === 0 || fileName.indexOf("/") !== -1) { diff --git a/js/module.js b/js/module.js index a600c50cd8..176ef98076 100644 --- a/js/module.js +++ b/js/module.js @@ -43,7 +43,7 @@ const Module = Class.extend({ /** * Called when the module is started. */ - async start () { + start () { Log.info(`Starting module: ${this.name}`); }, diff --git a/serveronly/watcher.js b/serveronly/watcher.js index 0f75a5fb49..95b62c2a12 100644 --- a/serveronly/watcher.js +++ b/serveronly/watcher.js @@ -145,10 +145,10 @@ function notifyClientsToReload () { * Restart the server process * @param {string} reason The reason for the restart */ -async function restartServer (reason) { +function restartServer (reason) { if (restartTimer) clearTimeout(restartTimer); - restartTimer = setTimeout(async () => { + restartTimer = setTimeout(() => { Log.info(reason); if (child) { diff --git a/tests/e2e/clientonly_spec.js b/tests/e2e/clientonly_spec.js index 6df9a3c325..e19d4eee46 100644 --- a/tests/e2e/clientonly_spec.js +++ b/tests/e2e/clientonly_spec.js @@ -133,7 +133,7 @@ describe("Clientonly parameter handling", () => { }); describe("Display environment check", () => { - it("should fail without DISPLAY or WAYLAND_DISPLAY when connecting to valid server", async () => { + it("should fail without DISPLAY or WAYLAND_DISPLAY when connecting to valid server", () => { // This test needs a running server to get past the connection phase // Without DISPLAY, it should fail with display error // For now, we just verify it fails (connection error comes first without server) @@ -159,7 +159,7 @@ describe("Clientonly with running server", () => { await delay(2000); }); - afterAll(async () => { + afterAll(() => { if (serverProcess && serverProcess.pid) { try { process.kill(-serverProcess.pid); diff --git a/tests/e2e/config_variables_spec.js b/tests/e2e/config_variables_spec.js index f3bf650527..4fb9cedd17 100644 --- a/tests/e2e/config_variables_spec.js +++ b/tests/e2e/config_variables_spec.js @@ -9,19 +9,19 @@ describe("config with variables and secrets", () => { await helpers.stopApplication(); }); - it("config.language should be \"de\"", async () => { + it("config.language should be \"de\"", () => { expect(config.language).toBe("de"); }); - it("config.loglevel should be [\"ERROR\", \"LOG\", \"WARN\", \"INFO\"]", async () => { + it("config.loglevel should be [\"ERROR\", \"LOG\", \"WARN\", \"INFO\"]", () => { expect(config.logLevel).toStrictEqual(["ERROR", "LOG", "WARN", "INFO"]); }); - it("config.ipWhitelist should be [\"::ffff:127.0.0.1\", \"::1\", \"127.0.0.1\"]", async () => { + it("config.ipWhitelist should be [\"::ffff:127.0.0.1\", \"::1\", \"127.0.0.1\"]", () => { expect(config.ipWhitelist).toStrictEqual(["::ffff:127.0.0.1", "::1", "127.0.0.1"]); }); - it("config.timeFormat should be 12", async () => { + it("config.timeFormat should be 12", () => { expect(config.timeFormat).toBe(12); // default is 24 }); diff --git a/tests/e2e/modules/newsfeed_spec.js b/tests/e2e/modules/newsfeed_spec.js index 4a86d4af24..0d4c161e9a 100644 --- a/tests/e2e/modules/newsfeed_spec.js +++ b/tests/e2e/modules/newsfeed_spec.js @@ -2,7 +2,7 @@ const fs = require("node:fs"); const { expect } = require("playwright/test"); const helpers = require("../helpers/global-setup"); -const runTests = async () => { +const runTests = () => { let page; describe("Default configuration", () => { diff --git a/tests/unit/classes/translator_spec.js b/tests/unit/classes/translator_spec.js index 383f823bf8..2f4de65393 100644 --- a/tests/unit/classes/translator_spec.js +++ b/tests/unit/classes/translator_spec.js @@ -93,7 +93,7 @@ describe("Translator", () => { Translator.coreTranslationsFallback = coreTranslationsFallback; }; - it("should return custom module translation", async () => { + it("should return custom module translation", () => { const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); @@ -104,7 +104,7 @@ describe("Translator", () => { expect(translation).toBe("Hallo fewieden"); }); - it("should return core translation", async () => { + it("should return core translation", () => { const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); let translation = Translator.translate({ name: "MMM-Module" }, "FOO"); @@ -113,28 +113,28 @@ describe("Translator", () => { expect(translation).toBe("Bar Lorem Ipsum"); }); - it("should return custom module translation fallback", async () => { + it("should return custom module translation fallback", () => { const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); const translation = Translator.translate({ name: "MMM-Module" }, "A key"); expect(translation).toBe("A translation"); }); - it("should return core translation fallback", async () => { + it("should return core translation fallback", () => { const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); const translation = Translator.translate({ name: "MMM-Module" }, "Fallback"); expect(translation).toBe("core fallback"); }); - it("should return translation with placeholder for missing variables", async () => { + it("should return translation with placeholder for missing variables", () => { const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); const translation = Translator.translate({ name: "MMM-Module" }, "Hello {username}"); expect(translation).toBe("Hallo {username}"); }); - it("should return key if no translation was found", async () => { + it("should return key if no translation was found", () => { const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); const translation = Translator.translate({ name: "MMM-Module" }, "MISSING"); diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index 91ee3cac79..8fd0a01450 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -163,7 +163,7 @@ describe("server_functions tests", () => { expect(corsResponse.set.mock.calls[2][1]).toBe("value2"); }); - it("Gets User-Agent from configuration", async () => { + it("Gets User-Agent from configuration", () => { const previousConfig = global.config; global.config = {}; let userAgent; diff --git a/tests/unit/functions/updatenotification_spec.js b/tests/unit/functions/updatenotification_spec.js index 09b39b18cb..f6617e4bf7 100644 --- a/tests/unit/functions/updatenotification_spec.js +++ b/tests/unit/functions/updatenotification_spec.js @@ -320,7 +320,7 @@ describe("Updatenotification", () => { describe("custom module", () => { const moduleName = "MMM-Fuel"; - beforeEach(async () => { + beforeEach(() => { gitRemoteOut = `origin\thttps://github.com/fewieden/${moduleName}.git (fetch)\norigin\thttps://github.com/fewieden/${moduleName}.git (push)\n`; gitRevParseOut = "9d8310163da94441073a93cead711ba43e8888d0"; gitStatusOut = "## master...origin/master"; diff --git a/tests/unit/helpers/global-setup.js b/tests/unit/helpers/global-setup.js index 132a02bbd6..d4a4977858 100644 --- a/tests/unit/helpers/global-setup.js +++ b/tests/unit/helpers/global-setup.js @@ -1,3 +1,3 @@ -module.exports = async () => { +module.exports = () => { process.env.TZ = "UTC"; }; diff --git a/tests/unit/modules/default/utils_spec.js b/tests/unit/modules/default/utils_spec.js index efea6e28e7..e5d01632a8 100644 --- a/tests/unit/modules/default/utils_spec.js +++ b/tests/unit/modules/default/utils_spec.js @@ -7,7 +7,7 @@ describe("Default modules utils tests", () => { describe("formatTime", () => { const time = new Date(); - beforeEach(async () => { + beforeEach(() => { time.setHours(13, 13); }); diff --git a/tests/unit/modules/default/weather/providers/envcanada_spec.js b/tests/unit/modules/default/weather/providers/envcanada_spec.js index 85533c5199..63086710b5 100644 --- a/tests/unit/modules/default/weather/providers/envcanada_spec.js +++ b/tests/unit/modules/default/weather/providers/envcanada_spec.js @@ -67,10 +67,10 @@ describe("EnvCanadaProvider", () => { expect(provider.config.type).toBe("current"); }); - it("should throw error if siteCode or provCode missing", async () => { + it("should throw error if siteCode or provCode missing", () => { const provider = new EnvCanadaProvider({ siteCode: "", provCode: "" }); provider.setCallbacks(vi.fn(), vi.fn()); - await expect(provider.initialize()).rejects.toThrow("siteCode and provCode are required"); + expect(() => provider.initialize()).toThrow("siteCode and provCode are required"); }); }); diff --git a/tests/unit/modules/default/weather/providers/openweathermap_spec.js b/tests/unit/modules/default/weather/providers/openweathermap_spec.js index 6303978441..7b27fd711f 100644 --- a/tests/unit/modules/default/weather/providers/openweathermap_spec.js +++ b/tests/unit/modules/default/weather/providers/openweathermap_spec.js @@ -70,9 +70,9 @@ describe("OpenWeatherMapProvider", () => { expect(provider.fetcher).toBeNull(); }); - it("should throw if setCallbacks not called before initialize", async () => { + it("should throw if setCallbacks not called before initialize", () => { const provider = new OpenWeatherMapProvider({ apiKey: "test" }); - await expect(provider.initialize()).rejects.toThrow("setCallbacks"); + expect(() => provider.initialize()).toThrow("setCallbacks"); }); }); From df8a8829663907132ca75fdae86593ac54ebe9f5 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 1 Mar 2026 00:32:42 +0100 Subject: [PATCH 370/418] fix(newsfeed): fix full article view and add framing check (#4039) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I was playing around with the newsfeed notification system (`ARTICLE_MORE_DETAILS`, `ARTICLE_TOGGLE_FULL`, …) and discovered some issues with the full article view: The iframe was loading the CORS proxy URL instead of the actual article URL, which could cause blank screens depending on the feed. Also, many news sites block iframes entirely (`X-Frame-Options: DENY`) and the user got no feedback at all — just an empty page. On top of that, scrolling used `window.scrollTo()` which moved the entire MagicMirror page instead of just the article. This PR cleans that up: - Use the raw article URL for the iframe (CORS proxy is only needed for server-side feed fetching) - Check `X-Frame-Options` / `Content-Security-Policy` headers server-side before showing the iframe — if the site blocks it, show a brief "Article cannot be displayed here." message and return to normal view - Show the iframe as a fixed full-screen overlay so other modules aren't affected, scroll via `container.scrollTop` - Keep the progressive disclosure behavior for `ARTICLE_MORE_DETAILS` (title → description → iframe → scroll) - Delete `fullarticle.njk`, replace with `getDom()` override - Fix `ARTICLE_INFO_RESPONSE` returning proxy URL instead of real URL - A few smaller fixes (negative scroll, null guard) - Add `NEWSFEED_ARTICLE_UNAVAILABLE` translation to all 47 language files - Add e2e tests for the notification handlers (`ARTICLE_NEXT`, `ARTICLE_PREVIOUS`, `ARTICLE_INFO_REQUEST`, `ARTICLE_LESS_DETAILS`) ## What this means for users - The full article view now works reliably across different feeds - If a news site blocks iframes, the user sees a brief message instead of a blank screen - Additional e2e tests make the module more robust and less likely to break silently in future MagicMirror versions --- defaultmodules/newsfeed/fullarticle.njk | 3 - defaultmodules/newsfeed/newsfeed.css | 22 ++- defaultmodules/newsfeed/newsfeed.js | 124 +++++++++++---- defaultmodules/newsfeed/node_helper.js | 22 +++ .../configs/modules/newsfeed/notifications.js | 26 ++++ tests/e2e/modules/newsfeed_spec.js | 142 ++++++++++++++++++ translations/af.json | 1 + translations/ar.json | 1 + translations/bg.json | 1 + translations/ca.json | 1 + translations/cs.json | 1 + translations/cv.json | 1 + translations/cy.json | 1 + translations/da.json | 1 + translations/de.json | 1 + translations/el.json | 1 + translations/en.json | 1 + translations/eo.json | 1 + translations/es.json | 1 + translations/et.json | 1 + translations/fi.json | 1 + translations/fr.json | 1 + translations/fy.json | 1 + translations/gl.json | 1 + translations/gu.json | 1 + translations/he.json | 1 + translations/hi.json | 1 + translations/hr.json | 1 + translations/hu.json | 1 + translations/id.json | 1 + translations/is.json | 1 + translations/it.json | 1 + translations/ja.json | 1 + translations/ko.json | 1 + translations/lt.json | 1 + translations/ms-my.json | 1 + translations/nb.json | 1 + translations/nl.json | 1 + translations/nn.json | 1 + translations/pl.json | 1 + translations/ps.json | 5 +- translations/pt-br.json | 1 + translations/pt.json | 1 + translations/ro.json | 1 + translations/ru.json | 1 + translations/sk.json | 1 + translations/sv.json | 1 + translations/th.json | 1 + translations/tlh.json | 1 + translations/tr.json | 1 + translations/uk.json | 1 + translations/zh-cn.json | 1 + translations/zh-tw.json | 1 + 53 files changed, 349 insertions(+), 41 deletions(-) delete mode 100644 defaultmodules/newsfeed/fullarticle.njk create mode 100644 tests/configs/modules/newsfeed/notifications.js diff --git a/defaultmodules/newsfeed/fullarticle.njk b/defaultmodules/newsfeed/fullarticle.njk deleted file mode 100644 index fbd6e437a1..0000000000 --- a/defaultmodules/newsfeed/fullarticle.njk +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/defaultmodules/newsfeed/newsfeed.css b/defaultmodules/newsfeed/newsfeed.css index 2c690a48e2..bdbcf1ca9b 100644 --- a/defaultmodules/newsfeed/newsfeed.css +++ b/defaultmodules/newsfeed/newsfeed.css @@ -1,12 +1,24 @@ -iframe.newsfeed-fullarticle { +.newsfeed-fullarticle-container { + position: fixed; width: 100vw; - - /* very large height value to allow scrolling */ - height: 3000px; + height: 100vh; top: 0; left: 0; + overflow-y: auto; + scrollbar-width: none; + z-index: 1000; + background: black; +} + +.newsfeed-fullarticle-container::-webkit-scrollbar { + display: none; +} + +iframe.newsfeed-fullarticle { + display: block; + width: 100%; + height: 5000px; border: none; - z-index: 1; } .region.bottom.bar.newsfeed-fullarticle { diff --git a/defaultmodules/newsfeed/newsfeed.js b/defaultmodules/newsfeed/newsfeed.js index cbe6e3264d..b24906962c 100644 --- a/defaultmodules/newsfeed/newsfeed.js +++ b/defaultmodules/newsfeed/newsfeed.js @@ -74,6 +74,10 @@ Module.register("newsfeed", { this.error = null; this.activeItem = 0; this.scrollPosition = 0; + this.articleIframe = null; + this.articleContainer = null; + this.articleFrameCheckPending = false; + this.articleUnavailable = false; this.registerFeeds(); @@ -97,15 +101,60 @@ Module.register("newsfeed", { } else if (notification === "NEWSFEED_ERROR") { this.error = this.translate(payload.error_type); this.scheduleUpdateInterval(); + } else if (notification === "ARTICLE_URL_STATUS") { + if (this.config.showFullArticle) { + this.articleFrameCheckPending = false; + this.articleUnavailable = !payload.canFrame; + if (!this.articleUnavailable) { + // Article can be framed — now shift the bottom bar to allow scrolling + document.getElementsByClassName("region bottom bar")[0].classList.add("newsfeed-fullarticle"); + } + this.updateDom(100); + if (this.articleUnavailable) { + // Briefly show the unavailable message, then return to normal newsfeed view + setTimeout(() => { + this.resetDescrOrFullArticleAndTimer(); + this.updateDom(500); + }, 3000); + } + } + } + }, + + //Override getDom to handle the full article case with error handling + getDom () { + if (this.config.showFullArticle) { + this.activeItemHash = this.newsItems[this.activeItem]?.hash; + const wrapper = document.createElement("div"); + if (this.articleFrameCheckPending) { + // Still waiting for the server-side framing check + wrapper.innerHTML = `
${this.translate("LOADING")}
`; + } else if (this.articleUnavailable) { + wrapper.innerHTML = `
${this.translate("NEWSFEED_ARTICLE_UNAVAILABLE")}
`; + } else { + const container = document.createElement("div"); + container.className = "newsfeed-fullarticle-container"; + container.scrollTop = this.scrollPosition; + const iframe = document.createElement("iframe"); + iframe.className = "newsfeed-fullarticle"; + // Always use the direct article URL — the CORS proxy is for server-side + // RSS feed fetching, not for browser iframes. + const item = this.newsItems[this.activeItem]; + iframe.src = item ? (typeof item.url === "string" ? item.url : item.url.href) : ""; + this.articleIframe = iframe; + this.articleContainer = container; + container.appendChild(iframe); + wrapper.appendChild(container); + } + return Promise.resolve(wrapper); } + return this._super(); }, //Override fetching of template name getTemplate () { if (this.config.feedUrl) { return "oldconfig.njk"; - } else if (this.config.showFullArticle) { - return "fullarticle.njk"; } return "newsfeed.njk"; }, @@ -116,13 +165,6 @@ Module.register("newsfeed", { this.activeItem = 0; } this.activeItemCount = this.newsItems.length; - // this.config.showFullArticle is a run-time configuration, triggered by optional notifications - if (this.config.showFullArticle) { - this.activeItemHash = this.newsItems[this.activeItem]?.hash; - return { - url: this.getActiveItemURL() - }; - } if (this.error) { this.activeItemHash = undefined; return { @@ -358,6 +400,10 @@ Module.register("newsfeed", { this.isShowingDescription = this.config.showDescription; this.config.showFullArticle = false; this.scrollPosition = 0; + this.articleIframe = null; + this.articleContainer = null; + this.articleFrameCheckPending = false; + this.articleUnavailable = false; // reset bottom bar alignment document.getElementsByClassName("region bottom bar")[0].classList.remove("newsfeed-fullarticle"); if (!this.timer) { @@ -386,23 +432,26 @@ Module.register("newsfeed", { Log.debug(`[newsfeed] going from article #${before} to #${this.activeItem} (of ${this.newsItems.length})`); this.updateDom(100); } - // if "more details" is received the first time: show article summary, on second time show full article else if (notification === "ARTICLE_MORE_DETAILS") { - // full article is already showing, so scrolling down if (this.config.showFullArticle === true) { + // iframe already showing — scroll down this.scrollPosition += this.config.scrollLength; - window.scrollTo(0, this.scrollPosition); - Log.debug("[newsfeed] scrolling down"); - Log.debug(`[newsfeed] ARTICLE_MORE_DETAILS, scroll position: ${this.config.scrollLength}`); - } else { + if (this.articleContainer) this.articleContainer.scrollTop = this.scrollPosition; + Log.debug(`[newsfeed] scrolling down, offset: ${this.scrollPosition}`); + } else if (this.isShowingDescription) { + // description visible — step up to full article this.showFullArticle(); + } else { + // only title visible — show description first + this.isShowingDescription = true; + Log.debug("[newsfeed] showing article description"); + this.updateDom(100); } } else if (notification === "ARTICLE_SCROLL_UP") { if (this.config.showFullArticle === true) { - this.scrollPosition -= this.config.scrollLength; - window.scrollTo(0, this.scrollPosition); - Log.debug("[newsfeed] scrolling up"); - Log.debug(`[newsfeed] ARTICLE_SCROLL_UP, scroll position: ${this.config.scrollLength}`); + this.scrollPosition = Math.max(0, this.scrollPosition - this.config.scrollLength); + if (this.articleContainer) this.articleContainer.scrollTop = this.scrollPosition; + Log.debug(`[newsfeed] scrolling up, offset: ${this.scrollPosition}`); } } else if (notification === "ARTICLE_LESS_DETAILS") { this.resetDescrOrFullArticleAndTimer(); @@ -416,26 +465,37 @@ Module.register("newsfeed", { this.showFullArticle(); } } else if (notification === "ARTICLE_INFO_REQUEST") { - this.sendNotification("ARTICLE_INFO_RESPONSE", { - title: this.newsItems[this.activeItem].title, - source: this.newsItems[this.activeItem].sourceTitle, - date: this.newsItems[this.activeItem].pubdate, - desc: this.newsItems[this.activeItem].description, - url: this.getActiveItemURL() - }); + const infoItem = this.newsItems[this.activeItem]; + if (infoItem) { + this.sendNotification("ARTICLE_INFO_RESPONSE", { + title: infoItem.title, + source: infoItem.sourceTitle, + date: infoItem.pubdate, + desc: infoItem.description, + url: typeof infoItem.url === "string" ? infoItem.url : infoItem.url.href + }); + } } }, showFullArticle () { - this.isShowingDescription = !this.isShowingDescription; - this.config.showFullArticle = !this.isShowingDescription; - // make bottom bar align to top to allow scrolling - if (this.config.showFullArticle === true) { - document.getElementsByClassName("region bottom bar")[0].classList.add("newsfeed-fullarticle"); + const item = this.newsItems[this.activeItem]; + const hasUrl = item && item.url && (typeof item.url === "string" ? item.url : item.url.href); + if (!hasUrl) { + Log.debug("[newsfeed] no article URL available, skipping full article view"); + return; } + this.isShowingDescription = false; + this.config.showFullArticle = true; + // Check server-side whether the article URL allows framing. + // The bottom bar CSS class is only added once we know the iframe will be shown. + this.articleFrameCheckPending = true; + this.articleUnavailable = false; + const rawUrl = typeof item.url === "string" ? item.url : item.url.href; + this.sendSocketNotification("CHECK_ARTICLE_URL", { url: rawUrl }); clearInterval(this.timer); this.timer = null; - Log.debug(`[newsfeed] showing ${this.isShowingDescription ? "article description" : "full article"}`); + Log.debug("[newsfeed] showing full article"); this.updateDom(100); } }); diff --git a/defaultmodules/newsfeed/node_helper.js b/defaultmodules/newsfeed/node_helper.js index 1101a72e4f..cede93f698 100644 --- a/defaultmodules/newsfeed/node_helper.js +++ b/defaultmodules/newsfeed/node_helper.js @@ -13,6 +13,28 @@ module.exports = NodeHelper.create({ socketNotificationReceived (notification, payload) { if (notification === "ADD_FEED") { this.createFetcher(payload.feed, payload.config); + } else if (notification === "CHECK_ARTICLE_URL") { + this.checkArticleUrl(payload.url); + } + }, + + /** + * Checks whether a URL can be displayed in an iframe by inspecting + * X-Frame-Options and Content-Security-Policy headers server-side. + * @param {string} url The article URL to check. + */ + async checkArticleUrl (url) { + try { + const response = await fetch(url, { method: "HEAD" }); + const xfo = response.headers.get("x-frame-options"); + const csp = response.headers.get("content-security-policy"); + // sameorigin also blocks since the article is on a different origin than MM + const blockedByXFO = xfo && ["deny", "sameorigin"].includes(xfo.toLowerCase().trim()); + const blockedByCSP = csp && (/frame-ancestors\s+['"]?none['"]?/).test(csp); + this.sendSocketNotification("ARTICLE_URL_STATUS", { url, canFrame: !blockedByXFO && !blockedByCSP }); + } catch { + // Network error or HEAD not supported — let the browser try the iframe anyway + this.sendSocketNotification("ARTICLE_URL_STATUS", { url, canFrame: true }); } }, diff --git a/tests/configs/modules/newsfeed/notifications.js b/tests/configs/modules/newsfeed/notifications.js new file mode 100644 index 0000000000..43bd0b1db1 --- /dev/null +++ b/tests/configs/modules/newsfeed/notifications.js @@ -0,0 +1,26 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 12, + + modules: [ + { + module: "newsfeed", + position: "bottom_bar", + config: { + feeds: [ + { + title: "Rodrigo Ramirez Blog", + url: "http://localhost:8080/tests/mocks/newsfeed_test.xml" + } + ], + updateInterval: 3600 * 1000 // 1 hour - prevent auto-rotation during tests + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/e2e/modules/newsfeed_spec.js b/tests/e2e/modules/newsfeed_spec.js index 0d4c161e9a..b68b6ea5a6 100644 --- a/tests/e2e/modules/newsfeed_spec.js +++ b/tests/e2e/modules/newsfeed_spec.js @@ -70,6 +70,148 @@ const runTests = () => { }); }; +describe("Newsfeed module > Notifications", () => { + let page; + + afterAll(async () => { + await helpers.stopApplication(); + }); + + /** + * Helper: call notificationReceived on the newsfeed module directly. + * @param {object} p - playwright page + * @param {string} notification - notification name + * @param {object} payload - notification payload + * @returns {Promise} resolves when the notification has been dispatched + */ + const notify = (p, notification, payload = {}) => p.evaluate( + ({ n, pl }) => { + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + nf.notificationReceived(n, pl, nf); + }, + { n: notification, pl: payload } + ); + + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/newsfeed/notifications.js"); + await helpers.getDocument(); + page = helpers.getPage(); + await expect(page.locator(".newsfeed .newsfeed-title")).toBeVisible(); + }); + + it("ARTICLE_NEXT should show the next article", async () => { + const title1 = await page.locator(".newsfeed .newsfeed-title").textContent(); + await notify(page, "ARTICLE_NEXT"); + await expect(page.locator(".newsfeed .newsfeed-title")).not.toContainText(title1.trim()); + }); + + it("ARTICLE_PREVIOUS should return to the previous article", async () => { + // Start at article 0, go to article 1, then back + await page.evaluate(() => { + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + nf.activeItem = 0; + nf.resetDescrOrFullArticleAndTimer(); + nf.updateDom(0); + }); + await expect(page.locator(".newsfeed .newsfeed-title")).toContainText("QPanel"); + const title0 = await page.locator(".newsfeed .newsfeed-title").textContent(); + + await notify(page, "ARTICLE_NEXT"); + await expect(page.locator(".newsfeed .newsfeed-title")).not.toContainText(title0.trim()); + + await notify(page, "ARTICLE_PREVIOUS"); + await expect(page.locator(".newsfeed .newsfeed-title")).toContainText(title0.trim()); + }); + + it("ARTICLE_NEXT should wrap around from the last article to the first", async () => { + // Jump to the last article + await page.evaluate(() => { + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + nf.activeItem = nf.newsItems.length - 1; + nf.resetDescrOrFullArticleAndTimer(); + nf.updateDom(0); + }); + await expect(page.locator(".newsfeed .newsfeed-title")).toBeVisible(); + const titleLast = await page.locator(".newsfeed .newsfeed-title").textContent(); + + await notify(page, "ARTICLE_NEXT"); + await expect(page.locator(".newsfeed .newsfeed-title")).not.toContainText(titleLast.trim()); + + // activeItem should now be 0 + const activeItem = await page.evaluate(() => MM.getModules().find((m) => m.name === "newsfeed").activeItem); + expect(activeItem).toBe(0); + }); + + it("ARTICLE_PREVIOUS should wrap around from the first article to the last", async () => { + await page.evaluate(() => { + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + nf.activeItem = 0; + nf.resetDescrOrFullArticleAndTimer(); + }); + await notify(page, "ARTICLE_PREVIOUS"); + + const activeItem = await page.evaluate(() => { + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + return { activeItem: nf.activeItem, total: nf.newsItems.length }; + }); + expect(activeItem.activeItem).toBe(activeItem.total - 1); + }); + + it("ARTICLE_INFO_REQUEST should respond with title, source, date, desc and raw url", async () => { + await page.evaluate(() => { + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + nf.activeItem = 0; + nf.resetDescrOrFullArticleAndTimer(); + }); + + const info = await page.evaluate(() => new Promise((resolve, reject) => { + const timer = setTimeout(() => reject(new Error("ARTICLE_INFO_RESPONSE timeout")), 3000); + const origSend = MM.sendNotification.bind(MM); + MM.sendNotification = function (n, p, s) { + if (n === "ARTICLE_INFO_RESPONSE") { + clearTimeout(timer); + MM.sendNotification = origSend; + resolve(p); + } + return origSend(n, p, s); + }; + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + nf.notificationReceived("ARTICLE_INFO_REQUEST", {}, nf); + })); + + expect(info).toHaveProperty("title"); + expect(info).toHaveProperty("source"); + expect(info).toHaveProperty("date"); + expect(info).toHaveProperty("desc"); + expect(info).toHaveProperty("url"); + expect(info.title).toBe("QPanel 0.13.0"); + expect(info.source).toBe("Rodrigo Ramirez Blog"); + // URL must be the raw article URL, not a CORS proxy URL + expect(info.url).toMatch(/^https?:\/\//); + expect(info.url).not.toContain("localhost"); + }); + + it("ARTICLE_LESS_DETAILS should reset the full article view", async () => { + // Simulate full article view being active + await page.evaluate(() => { + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + nf.config.showFullArticle = true; + nf.articleFrameCheckPending = false; + nf.articleUnavailable = false; + }); + + await notify(page, "ARTICLE_LESS_DETAILS"); + + const state = await page.evaluate(() => { + const nf = MM.getModules().find((m) => m.name === "newsfeed"); + return { showFullArticle: nf.config.showFullArticle }; + }); + expect(state.showFullArticle).toBe(false); + // Normal newsfeed title should be visible again + await expect(page.locator(".newsfeed .newsfeed-title")).toBeVisible(); + }); +}); + describe("Newsfeed module", () => { afterAll(async () => { await helpers.stopApplication(); diff --git a/translations/af.json b/translations/af.json index 149e90a6be..8a138c24be 100644 --- a/translations/af.json +++ b/translations/af.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Gaan die logs na vir meer besonderhede.", "NEWSFEED_NO_ITEMS": "Geen nuus op die oomblik.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikel kan nie hier vertoon word nie.", "UPDATE_NOTIFICATION": "MagicMirror² update beskikbaar.", "UPDATE_NOTIFICATION_MODULE": "Update beskikbaar vir {MODULE_NAME} module.", diff --git a/translations/ar.json b/translations/ar.json index a0b7c09a7a..fd2bfb6b05 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -40,6 +40,7 @@ "MODULE_ERROR_UNSPECIFIED": "تحقق من السجلات لمزيد من التفاصيل.", "NEWSFEED_NO_ITEMS": "لا توجد أخبار في الوقت الحالي.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "لا يمكن عرض المقالة هنا.", "UPDATE_NOTIFICATION": "تحديث MagicMirror² متاح.", "UPDATE_NOTIFICATION_MODULE": "تحديث متاح لوحدة {MODULE_NAME}.", diff --git a/translations/bg.json b/translations/bg.json index 1f6b5eab55..018422cbad 100644 --- a/translations/bg.json +++ b/translations/bg.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Проверете логовете за повече подробности.", "NEWSFEED_NO_ITEMS": "Няма новини в момента.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Статията не може да бъде показана тук.", "UPDATE_NOTIFICATION": "Налична е актуализация за MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Налична е актуализация за модула „{MODULE_NAME}“.", diff --git a/translations/ca.json b/translations/ca.json index f9b5a0e63a..1832d2cb9f 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Consulta els registres per a més detalls.", "NEWSFEED_NO_ITEMS": "No hi ha notícies disponibles en aquest moment.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "L'article no es pot mostrar aquí.", "UPDATE_NOTIFICATION": "MagicMirror² actualizació disponible.", "UPDATE_NOTIFICATION_MODULE": "Disponible una actualizació per al mòdul {MODULE_NAME}.", diff --git a/translations/cs.json b/translations/cs.json index 931ea113a5..72034ace0f 100644 --- a/translations/cs.json +++ b/translations/cs.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Zkontrolujte protokoly pro více informací.", "NEWSFEED_NO_ITEMS": "Žádné zprávy.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Článek zde nelze zobrazit.", "UPDATE_NOTIFICATION": "Dostupná aktualizace pro MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostupná aktualizace pro modul {MODULE_NAME}.", diff --git a/translations/cv.json b/translations/cv.json index 6e4eafb3b6..22e2325ec7 100644 --- a/translations/cv.json +++ b/translations/cv.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Тӗп лог ҫӗнтерӗ.", "NEWSFEED_NO_ITEMS": "Пулас ҫӗнтер ҫук.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Article cannot be displayed here.", "UPDATE_NOTIFICATION": "MagicMirror² валли ҫӗнетӳ пур.", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} модуль валли ҫӗнетӳ пур.", diff --git a/translations/cy.json b/translations/cy.json index 39395f3d09..d172aa2d7b 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Gwiriwch y logiau am ragor o fanylion.", "NEWSFEED_NO_ITEMS": "Dim newyddion ar hyn o bryd.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Ni ellir dangos yr erthygl yma.", "UPDATE_NOTIFICATION": "MagicMirror² mwy diweddar yn barod.", "UPDATE_NOTIFICATION_MODULE": "Mae diweddaraiad ar gyfer y modiwl {MODULE_NAME}.", diff --git a/translations/da.json b/translations/da.json index edc650c2e9..6b56913955 100644 --- a/translations/da.json +++ b/translations/da.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Tjek logfiler for flere detaljer.", "NEWSFEED_NO_ITEMS": "Ingen nyheder i øjeblikket.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artiklen kan ikke vises her.", "UPDATE_NOTIFICATION": "MagicMirror² opdatering tilgængelig.", "UPDATE_NOTIFICATION_MODULE": "Opdatering tilgængelig for {MODULE_NAME} modulet.", diff --git a/translations/de.json b/translations/de.json index 69b17b1be4..af50e69c4e 100644 --- a/translations/de.json +++ b/translations/de.json @@ -43,6 +43,7 @@ "MODULE_ERROR_UNSPECIFIED": "Prüfe die Logdateien für weitere Details.", "NEWSFEED_NO_ITEMS": "Momentan keine Neuigkeiten.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikel kann hier nicht angezeigt werden.", "UPDATE_NOTIFICATION": "Aktualisierung für MagicMirror² verfügbar.", "UPDATE_NOTIFICATION_MODULE": "Aktualisierung für das Modul „{MODULE_NAME}“ verfügbar.", diff --git a/translations/el.json b/translations/el.json index 10146303f4..9cc161d55e 100644 --- a/translations/el.json +++ b/translations/el.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Ελέγξτε τα αρχεία καταγραφής για περισσότερες λεπτομέρειες.", "NEWSFEED_NO_ITEMS": "Δεν υπάρχουν ειδήσεις αυτή τη στιγμή.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Το άρθρο δεν μπορεί να εμφανιστεί εδώ.", "UPDATE_NOTIFICATION": "Διατίθεται ενημέρωση MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Διατίθεται ενημέρωση για το module {MODULE_NAME}.", diff --git a/translations/en.json b/translations/en.json index 9e95afa348..311d4973a2 100644 --- a/translations/en.json +++ b/translations/en.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Check logs for more details.", "NEWSFEED_NO_ITEMS": "No news at the moment.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Article cannot be displayed here.", "UPDATE_NOTIFICATION": "MagicMirror² update available.", "UPDATE_NOTIFICATION_MODULE": "Update available for {MODULE_NAME} module.", diff --git a/translations/eo.json b/translations/eo.json index 824282cd33..e1a9475fe3 100644 --- a/translations/eo.json +++ b/translations/eo.json @@ -43,6 +43,7 @@ "MODULE_ERROR_UNSPECIFIED": "Kontrolu la protokolajn dosierojn por pli da detaloj.", "NEWSFEED_NO_ITEMS": "Momente neniu novaĵoj.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikolo ne estas montrebla ĉi tie.", "UPDATE_NOTIFICATION": "Ĝisdatigo por MagicMirror² disponebla.", "UPDATE_NOTIFICATION_MODULE": "Ĝisdatigo por la modulo „{MODULE_NAME}“ disponebla.", diff --git a/translations/es.json b/translations/es.json index 30e06e7881..f157d35512 100644 --- a/translations/es.json +++ b/translations/es.json @@ -43,6 +43,7 @@ "MODULE_ERROR_UNSPECIFIED": "Por favor, consulte los registros para obtener más información.", "NEWSFEED_NO_ITEMS": "No hay noticias disponibles en este momento.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "El artículo no se puede mostrar aquí.", "UPDATE_NOTIFICATION": "MagicMirror² actualización disponible.", "UPDATE_NOTIFICATION_MODULE": "Disponible una actualización para el módulo {MODULE_NAME}.", diff --git a/translations/et.json b/translations/et.json index cf9e0099ed..e0777983d6 100644 --- a/translations/et.json +++ b/translations/et.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Lisateabe saamiseks kontrollige logifaile.", "NEWSFEED_NO_ITEMS": "Hetkel ei ole uudiseid.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artiklit ei saa siin kuvada.", "UPDATE_NOTIFICATION": "MagicMirror²'le on uuendus saadaval.", "UPDATE_NOTIFICATION_MODULE": "Uuendus saadaval {MODULE_NAME} moodulile.", diff --git a/translations/fi.json b/translations/fi.json index c201fbb8e0..b6e2d303c7 100644 --- a/translations/fi.json +++ b/translations/fi.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Tarkista lokitiedostot saadaksesi lisätietoja.", "NEWSFEED_NO_ITEMS": "Ei uutisia tällä hetkellä.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikkelia ei voi näyttää täällä.", "UPDATE_NOTIFICATION": "MagicMirror² päivitys saatavilla.", "UPDATE_NOTIFICATION_MODULE": "Päivitys saatavilla moduulille {MODULE_NAME}.", diff --git a/translations/fr.json b/translations/fr.json index e4c05e7985..47c9369b78 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -43,6 +43,7 @@ "MODULE_ERROR_UNSPECIFIED": "Consultez les journaux pour plus de détails.", "NEWSFEED_NO_ITEMS": "Aucune nouvelle pour le moment.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "L'article ne peut pas être affiché ici.", "UPDATE_NOTIFICATION": "Une mise à jour de MagicMirror² est disponible", "UPDATE_NOTIFICATION_MODULE": "Une mise à jour est disponible pour le module {MODULE_NAME}.", diff --git a/translations/fy.json b/translations/fy.json index 939002669f..01d0133bed 100644 --- a/translations/fy.json +++ b/translations/fy.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Sjoch de logs foar mear ynformaasje.", "NEWSFEED_NO_ITEMS": "Op it stuit gjin nijsberjochten.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikel kin hjir net werjûn wurde.", "UPDATE_NOTIFICATION": "Der is in update beskikber foar MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Der is in update beskikber foar it {MODULE_NAME} module.", diff --git a/translations/gl.json b/translations/gl.json index 7d410971da..217029b537 100644 --- a/translations/gl.json +++ b/translations/gl.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Verifique os rexistros para obter máis información.", "NEWSFEED_NO_ITEMS": "Non hai novas no momento.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "O artigo non se pode mostrar aquí.", "UPDATE_NOTIFICATION": "Actualización dispoñible para MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Actualización dispoñible para o módulo {MODULE_NAME}.", diff --git a/translations/gu.json b/translations/gu.json index 32ea8ce350..bbd5fb5a5a 100644 --- a/translations/gu.json +++ b/translations/gu.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "વધુ વિગતો માટે લોગ તપાસો.", "NEWSFEED_NO_ITEMS": "હાલમાં કોઈ સમાચાર નથી.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "લેખ અહીં પ્રદર્શિત કરી શકાતો નથી.", "UPDATE_NOTIFICATION": "MagicMirror² અપડેટ ઉપલબ્ધ છે.", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} મોડ્યુલ માટે અપડેટ ઉપલબ્ધ છે.", diff --git a/translations/he.json b/translations/he.json index 998504c2ed..45c440ea26 100644 --- a/translations/he.json +++ b/translations/he.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "בדוק את היומנים לפרטים נוספים.", "NEWSFEED_NO_ITEMS": "אין חדשות כרגע.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "לא ניתן להציג את המאמר כאן.", "UPDATE_NOTIFICATION": "עדכון זמין ל-MagicMirror²", "UPDATE_NOTIFICATION_MODULE": "עדכון זמין ב-{MODULE_NAME} מודול", diff --git a/translations/hi.json b/translations/hi.json index 890b2ebd3b..a488e397b5 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "अधिक जानकारी के लिए लॉग जांचें।", "NEWSFEED_NO_ITEMS": "इस समय कोई समाचार नहीं।", + "NEWSFEED_ARTICLE_UNAVAILABLE": "लेख यहाँ प्रदर्शित नहीं किया जा सकता।", "UPDATE_NOTIFICATION": "MagicMirror² अपडेट उपलब्ध।", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} मॉड्यूल के लिए उपलब्ध अद्यतन।", diff --git a/translations/hr.json b/translations/hr.json index 18c01e24d5..93d59c967e 100644 --- a/translations/hr.json +++ b/translations/hr.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Provjerite dnevnike za više informacija.", "NEWSFEED_NO_ITEMS": "Trenutno nema vijesti.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Članak se ne može prikazati ovdje.", "UPDATE_NOTIFICATION": "Dostupna je aktualizacija MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostupna je aktualizacija modula {MODULE_NAME}.", diff --git a/translations/hu.json b/translations/hu.json index db96e63051..e8b6b12028 100644 --- a/translations/hu.json +++ b/translations/hu.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Ellenőrizze a naplókat további részletekért.", "NEWSFEED_NO_ITEMS": "Jelenleg nincsenek hírek.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "A cikk itt nem jeleníthető meg.", "UPDATE_NOTIFICATION": "MagicMirror²-hoz frissítés érhető el.", "UPDATE_NOTIFICATION_MODULE": "A {MODULE_NAME} modulhoz frissítés érhető el.", diff --git a/translations/id.json b/translations/id.json index c5b4e6a4c3..738bd940da 100644 --- a/translations/id.json +++ b/translations/id.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Silakan periksa log untuk informasi lebih lanjut.", "NEWSFEED_NO_ITEMS": "Saat ini tidak ada berita.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikel tidak dapat ditampilkan di sini.", "UPDATE_NOTIFICATION": "Memperbarui MagicMirror² tersedia.", "UPDATE_NOTIFICATION_MODULE": "Memperbarui tersedia untuk modul {MODULE_NAME}.", diff --git a/translations/is.json b/translations/is.json index 3ca35da4c4..e21d6efb73 100644 --- a/translations/is.json +++ b/translations/is.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Vinsamlegast athugaðu skráningu fyrir frekari upplýsingar.", "NEWSFEED_NO_ITEMS": "Engar fréttir í boði núna.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Grein er ekki hægt að sýna hér.", "UPDATE_NOTIFICATION": "MagicMirror² uppfærsla í boði.", "UPDATE_NOTIFICATION_MODULE": "Uppfærsla í boði fyrir {MODULE_NAME} module.", diff --git a/translations/it.json b/translations/it.json index d8ca1f990f..7c4591e4bf 100644 --- a/translations/it.json +++ b/translations/it.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Si prega di controllare i log per ulteriori dettagli.", "NEWSFEED_NO_ITEMS": "Al momento non ci sono notizie.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "L'articolo non può essere visualizzato qui.", "UPDATE_NOTIFICATION": "E' disponibile un aggiornamento di MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "E' disponibile un aggiornamento del modulo {MODULE_NAME}.", diff --git a/translations/ja.json b/translations/ja.json index 2ec19581c9..22052f014b 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "詳細はログを確認してください。", "NEWSFEED_NO_ITEMS": "現在ニュースはありません。", + "NEWSFEED_ARTICLE_UNAVAILABLE": "この記事はここでは表示できません。", "UPDATE_NOTIFICATION": "MagicMirror² のアップデートが利用可能です。", "UPDATE_NOTIFICATION_MODULE": "モジュール {MODULE_NAME} のアップデートが利用可能です。", diff --git a/translations/ko.json b/translations/ko.json index c5d223e817..9ee81b2edb 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "상세 내용은 로그를 확인하세요.", "NEWSFEED_NO_ITEMS": "현재 뉴스가 없습니다.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "이 기사는 여기에 표시할 수 없습니다.", "UPDATE_NOTIFICATION": "새로운 MagicMirror² 업데이트가 있습니다.", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} 모듈에서 사용 가능한 업데이트 입니다.", diff --git a/translations/lt.json b/translations/lt.json index 75ed4d8979..cfc5353b02 100644 --- a/translations/lt.json +++ b/translations/lt.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Patikrinkite žurnalus, kad gautumėte daugiau informacijos.", "NEWSFEED_NO_ITEMS": "Šiuo metu naujienų nėra.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Straipsnis čia negali būti rodomas.", "UPDATE_NOTIFICATION": "Galimas MagicMirror² naujinimas.", "UPDATE_NOTIFICATION_MODULE": "Galimas {MODULE_NAME} naujinimas.", diff --git a/translations/ms-my.json b/translations/ms-my.json index 54e0bffc52..e93dd8cdf1 100644 --- a/translations/ms-my.json +++ b/translations/ms-my.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Sila semak log untuk maklumat lanjut.", "NEWSFEED_NO_ITEMS": "Tiada berita buat masa ini.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikel tidak dapat dipaparkan di sini.", "UPDATE_NOTIFICATION": "MagicMirror² mempunyai update terkini.", "UPDATE_NOTIFICATION_MODULE": "Modul {MODULE_NAME} mempunyai update terkini.", diff --git a/translations/nb.json b/translations/nb.json index 3dd5f20983..d459ff90ba 100644 --- a/translations/nb.json +++ b/translations/nb.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Vennligst sjekk loggene for mer informasjon.", "NEWSFEED_NO_ITEMS": "Ingen nyheter tilgjengelig for øyeblikket.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikkelen kan ikke vises her.", "UPDATE_NOTIFICATION": "MagicMirror²-oppdatering er tilgjengelig.", "UPDATE_NOTIFICATION_MODULE": "Oppdatering tilgjengelig for modulen {MODULE_NAME}.", diff --git a/translations/nl.json b/translations/nl.json index e4f8a77585..6102c1de54 100644 --- a/translations/nl.json +++ b/translations/nl.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Bekijk de logs voor meer informatie.", "NEWSFEED_NO_ITEMS": "Geen nieuws op dit moment.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikel kan hier niet worden weergegeven.", "UPDATE_NOTIFICATION": "MagicMirror² update beschikbaar.", "UPDATE_NOTIFICATION_MODULE": "Update beschikbaar voor {MODULE_NAME} module.", diff --git a/translations/nn.json b/translations/nn.json index 833f3c3df8..8706cc198b 100644 --- a/translations/nn.json +++ b/translations/nn.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Vennligst sjekk loggfilene for meir informasjon.", "NEWSFEED_NO_ITEMS": "Ingen nyhende tilgjengeleg no.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikkelen kan ikkje visast her.", "UPDATE_NOTIFICATION": "MagicMirror² oppdatering er tilgjengeleg.", "UPDATE_NOTIFICATION_MODULE": "Oppdatering tilgjengeleg for modulen {MODULE_NAME}.", diff --git a/translations/pl.json b/translations/pl.json index 545c8fe9e5..a74143b62c 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Sprawdź logi, aby uzyskać więcej informacji.", "NEWSFEED_NO_ITEMS": "Brak wiadomości w tej chwili.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artykuł nie może być wyświetlony tutaj.", "UPDATE_NOTIFICATION": "Dostępna jest aktualizacja MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostępna jest aktualizacja modułu {MODULE_NAME}.", diff --git a/translations/ps.json b/translations/ps.json index 701c30e82a..d9390dcc0c 100644 --- a/translations/ps.json +++ b/translations/ps.json @@ -34,5 +34,8 @@ "UPDATE_NOTIFICATION": "د MagicMirror² نوې نسخه سته ", "UPDATE_NOTIFICATION_MODULE": "د {MODULE_NAME} نوی نسخه سته", "UPDATE_INFO_SINGLE": "اوسنی برخه {COMMIT_COUNT} د {BRANCH_NAME} څخه وروسته پاته ده", - "UPDATE_INFO_MULTIPLE": "اوسنی برخه {COMMIT_COUNT} د {BRANCH_NAME} څخه وروسته پاته ده" + "UPDATE_INFO_MULTIPLE": "اوسنی برخه {COMMIT_COUNT} د {BRANCH_NAME} څخه وروسته پاته ده", + + "NEWSFEED_NO_ITEMS": "مقاله شتون نلري.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "مقاله دلته نه شي ښودل کیدی." } diff --git a/translations/pt-br.json b/translations/pt-br.json index 6c59fec9ab..4fdf6044e7 100644 --- a/translations/pt-br.json +++ b/translations/pt-br.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Verifique os logs para mais detalhes.", "NEWSFEED_NO_ITEMS": "Atualmente não há notícias.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "O artigo não pode ser exibido aqui.", "UPDATE_NOTIFICATION": "Nova atualização para MagicMirror² disponível.", "UPDATE_NOTIFICATION_MODULE": "Atualização para o módulo {MODULE_NAME} disponível.", diff --git a/translations/pt.json b/translations/pt.json index 3c1f26bde4..44770c7133 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -43,6 +43,7 @@ "MODULE_ERROR_UNSPECIFIED": "Consulta os registos para mais detalhes.", "NEWSFEED_NO_ITEMS": "Sem notícias de momento.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "O artigo não pode ser apresentado aqui.", "UPDATE_NOTIFICATION": "Está disponível uma atualização do MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Atualização disponível para o módulo {MODULE_NAME}.", diff --git a/translations/ro.json b/translations/ro.json index 4d0422f1f2..5119fecefb 100644 --- a/translations/ro.json +++ b/translations/ro.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Verificați jurnalele pentru mai multe detalii.", "NEWSFEED_NO_ITEMS": "Nu există știri în acest moment.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Articolul nu poate fi afișat aici.", "UPDATE_NOTIFICATION": "Un update este disponibil pentru MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Un update este disponibil pentru modulul {MODULE_NAME}.", diff --git a/translations/ru.json b/translations/ru.json index 6620f1bcde..bf5c969a04 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Пожалуйста, проверьте логи для получения дополнительной информации.", "NEWSFEED_NO_ITEMS": "В данный момент нет новостей.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Статья не может быть отображена здесь.", "UPDATE_NOTIFICATION": "Есть обновление для MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Есть обновление для {MODULE_NAME} модуля.", diff --git a/translations/sk.json b/translations/sk.json index 2407126eb8..a420a45bbf 100644 --- a/translations/sk.json +++ b/translations/sk.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Skontrolujte protokoly pre viac informácií.", "NEWSFEED_NO_ITEMS": "Momentálne žiadne správy.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Článok sa tu nedá zobraziť.", "UPDATE_NOTIFICATION": "Dostupná aktualizácia pre MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Dostupná aktualizácia pre modul {MODULE_NAME}.", diff --git a/translations/sv.json b/translations/sv.json index 0add5c4360..a05c1b7275 100644 --- a/translations/sv.json +++ b/translations/sv.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Vänligen kontrollera loggarna för mer information.", "NEWSFEED_NO_ITEMS": "Inga nyheter för tillfället.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Artikeln kan inte visas här.", "UPDATE_NOTIFICATION": "MagicMirror² uppdatering finns tillgänglig.", "UPDATE_NOTIFICATION_MODULE": "Uppdatering finns tillgänglig av {MODULE_NAME} modulen.", diff --git a/translations/th.json b/translations/th.json index dfa120f33f..1a2bfd40bb 100644 --- a/translations/th.json +++ b/translations/th.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "ตรวจสอบบันทึกสำหรับรายละเอียดเพิ่มเติม", "NEWSFEED_NO_ITEMS": "ไม่มีข่าวในขณะนี้", + "NEWSFEED_ARTICLE_UNAVAILABLE": "ไม่สามารถแสดงบทความที่นี่ได้", "UPDATE_NOTIFICATION": "MagicMirror² มีการอัปเดต", "UPDATE_NOTIFICATION_MODULE": "มีการอัปเดตสำหรับโมดูล {MODULE_NAME}", diff --git a/translations/tlh.json b/translations/tlh.json index b7a70a4368..295d40d411 100644 --- a/translations/tlh.json +++ b/translations/tlh.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "logmeyDaq yImev.", "NEWSFEED_NO_ITEMS": "DaHghachmey ghobe' yImev.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "QIngheb cha' tu'be'lu'.", "UPDATE_NOTIFICATION": " De'chu' MagicMirror² lI'laH.", "UPDATE_NOTIFICATION_MODULE": "bobcho' {MODULE_NAME} lI'laH De'chu.", diff --git a/translations/tr.json b/translations/tr.json index 6e0d3ad249..6688addabe 100644 --- a/translations/tr.json +++ b/translations/tr.json @@ -41,6 +41,7 @@ "MODULE_ERROR_UNSPECIFIED": "Daha fazla ayrıntı için günlükleri kontrol edin.", "NEWSFEED_NO_ITEMS": "Şu anda haber yok.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Makale burada görüntülenemiyor.", "UPDATE_NOTIFICATION": "MagicMirror² güncellemesi mevcut.", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} modulü için güncelleme mevcut.", diff --git a/translations/uk.json b/translations/uk.json index ffc308226a..1aad1ba6f9 100644 --- a/translations/uk.json +++ b/translations/uk.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "Перевірте журнали для отримання додаткової інформації.", "NEWSFEED_NO_ITEMS": "Немає новин на даний момент.", + "NEWSFEED_ARTICLE_UNAVAILABLE": "Статтю неможливо відобразити тут.", "UPDATE_NOTIFICATION": "Є оновлення для MagicMirror².", "UPDATE_NOTIFICATION_MODULE": "Є оновлення для модуля {MODULE_NAME}.", diff --git a/translations/zh-cn.json b/translations/zh-cn.json index 7e1cf7ca65..146a8a0881 100644 --- a/translations/zh-cn.json +++ b/translations/zh-cn.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "请查看日志以获取更多详细信息。", "NEWSFEED_NO_ITEMS": "目前没有新闻。", + "NEWSFEED_ARTICLE_UNAVAILABLE": "文章无法在此处显示。", "UPDATE_NOTIFICATION": "MagicMirror²有新的版本。", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME}模块可更新。", diff --git a/translations/zh-tw.json b/translations/zh-tw.json index 13c4edab90..1c21632bba 100644 --- a/translations/zh-tw.json +++ b/translations/zh-tw.json @@ -42,6 +42,7 @@ "MODULE_ERROR_UNSPECIFIED": "查看日誌以了解詳情。", "NEWSFEED_NO_ITEMS": "目前沒有新聞。", + "NEWSFEED_ARTICLE_UNAVAILABLE": "文章無法在此處顯示。", "UPDATE_NOTIFICATION": "MagicMirror² 有可用更新。", "UPDATE_NOTIFICATION_MODULE": "{MODULE_NAME} 模組有可用更新。", From 083953fff5b481267ed870e9498b80d48fe1f178 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:30:24 +0100 Subject: [PATCH 371/418] chore: update dependencies + add exports, files, and sideEffects fields to package.json (#4040) This updates all dependencies to their latest versions - except two packages: - eslint: Some plugins we use here aren't compatible yet to ESLint v10. - node-ical: The new version has revealed an issue in our calendar logic. I would prefer to address this in a separate PR. After updating the dependencies, eslint-plugin-package-json rules complained about missing fields in the package.json. I added them in the second commit. --- package-lock.json | 2033 +++++++++++++++++++++------------------------ package.json | 52 +- 2 files changed, 970 insertions(+), 1115 deletions(-) diff --git a/package-lock.json b/package-lock.json index e815ee3b5a..84eff058f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,14 +10,14 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.2.9", + "@fontsource/roboto": "^5.2.10", "@fontsource/roboto-condensed": "^5.2.8", - "@fortawesome/fontawesome-free": "^7.1.0", - "ajv": "^8.17.1", + "@fortawesome/fontawesome-free": "^7.2.0", + "ajv": "^8.18.0", "animate.css": "^4.1.1", "console-stamp": "^3.1.2", - "croner": "^9.1.0", - "eslint": "^9.39.2", + "croner": "^10.0.1", + "eslint": "^9.39.3", "express": "^5.2.1", "feedme": "^2.0.2", "helmet": "^8.1.0", @@ -31,30 +31,30 @@ "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.30.7", - "undici": "^7.19.2", + "systeminformation": "^5.31.1", + "undici": "^7.22.0", "weathericons": "^2.1.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^5.7.1", + "@stylistic/eslint-plugin": "^5.9.0", "@vitest/coverage-v8": "^4.0.18", - "@vitest/eslint-plugin": "^1.6.6", + "@vitest/eslint-plugin": "^1.6.9", "@vitest/ui": "^4.0.18", - "cspell": "^9.6.2", + "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-jsdoc": "^62.5.0", - "eslint-plugin-package-json": "^0.88.2", - "eslint-plugin-playwright": "^2.5.1", + "eslint-plugin-jsdoc": "^62.7.1", + "eslint-plugin-package-json": "^0.89.2", + "eslint-plugin-playwright": "^2.8.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", - "jsdom": "^27.4.0", - "lint-staged": "^16.2.7", - "markdownlint-cli2": "^0.20.0", - "msw": "^2.12.7", - "playwright": "^1.58.1", + "jsdom": "^28.1.0", + "lint-staged": "^16.3.0", + "markdownlint-cli2": "^0.21.0", + "msw": "^2.12.10", + "playwright": "^1.58.2", "prettier": "^3.8.1", "prettier-plugin-jinja-template": "^2.1.0", - "stylelint": "^17.1.0", + "stylelint": "^17.4.0", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", "vitest": "^4.0.18" @@ -63,7 +63,7 @@ "node": ">=22.21.1 <23 || >=24" }, "optionalDependencies": { - "electron": "^40.1.0" + "electron": "^40.6.1" } }, "node_modules/@acemir/cssom": { @@ -81,23 +81,26 @@ "license": "ISC" }, "node_modules/@asamuzakjp/css-color": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.1.tgz", - "integrity": "sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.0.1.tgz", + "integrity": "sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.4", - "@csstools/css-color-parser": "^3.1.0", - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4", - "lru-cache": "^11.2.4" + "@csstools/css-calc": "^3.1.1", + "@csstools/css-color-parser": "^4.0.2", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "lru-cache": "^11.2.6" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/@asamuzakjp/dom-selector": { - "version": "6.7.6", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.6.tgz", - "integrity": "sha512-hBaJER6A9MpdG3WgdlOolHmbOYvSk46y7IQN/1+iqiCuUu6iWdQrs9DGKF8ocqsEqWujWf/V7b7vaDgiUmIvUg==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", + "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -105,7 +108,7 @@ "bidi-js": "^1.0.3", "css-tree": "^3.1.0", "is-potential-custom-element-name": "^1.0.1", - "lru-cache": "^11.2.4" + "lru-cache": "^11.2.6" } }, "node_modules/@asamuzakjp/nwsapi": { @@ -116,9 +119,9 @@ "license": "MIT" }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { @@ -158,13 +161,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -174,9 +177,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { @@ -197,17 +200,30 @@ "node": ">=18" } }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, "node_modules/@cacheable/memory": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.7.tgz", - "integrity": "sha512-RbxnxAMf89Tp1dLhXMS7ceft/PGsDl1Ip7T20z5nZ+pwIAsQ1p2izPjVG69oCLv/jfQ7HDPHTWK0c9rcAWXN3A==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.8.tgz", + "integrity": "sha512-FvEb29x5wVwu/Kf93IWwsOOEuhHh6dYCJF3vcKLzXc0KXIW181AOzv6ceT4ZpBHDvAfG60eqb+ekmrnLHIy+jw==", "dev": true, "license": "MIT", "dependencies": { - "@cacheable/utils": "^2.3.3", - "@keyv/bigmap": "^1.3.0", - "hookified": "^1.14.0", - "keyv": "^5.5.5" + "@cacheable/utils": "^2.4.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" } }, "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { @@ -238,14 +254,14 @@ } }, "node_modules/@cacheable/utils": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.3.3.tgz", - "integrity": "sha512-JsXDL70gQ+1Vc2W/KUFfkAJzgb4puKwwKehNLuB+HrNKWf91O736kGfxn4KujXCCSuh6mRRL4XEB0PkAFjWS0A==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.4.0.tgz", + "integrity": "sha512-PeMMsqjVq+bF0WBsxFBxr/WozBJiZKY0rUojuaCoIaKnEl3Ju1wfEwS+SV1DU/cSe8fqHIPiYJFif8T3MVt4cQ==", "dev": true, "license": "MIT", "dependencies": { - "hashery": "^1.3.0", - "keyv": "^5.5.5" + "hashery": "^1.5.0", + "keyv": "^5.6.0" } }, "node_modules/@cacheable/utils/node_modules/keyv": { @@ -259,9 +275,9 @@ } }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.6.2.tgz", - "integrity": "sha512-s5u/3nhQUftKibPIbRLLAf4M5JG1NykqkPCxS0STMmri0hzVMZbAOCyHjdLoOCqPUn0xZzLA8fgeYg3b7QuHpg==", + "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==", "dev": true, "license": "MIT", "dependencies": { @@ -278,11 +294,11 @@ "@cspell/dict-data-science": "^2.0.13", "@cspell/dict-django": "^4.1.6", "@cspell/dict-docker": "^1.1.17", - "@cspell/dict-dotnet": "^5.0.11", + "@cspell/dict-dotnet": "^5.0.12", "@cspell/dict-elixir": "^4.0.8", - "@cspell/dict-en_us": "^4.4.27", + "@cspell/dict-en_us": "^4.4.29", "@cspell/dict-en-common-misspellings": "^2.1.12", - "@cspell/dict-en-gb-mit": "^3.1.16", + "@cspell/dict-en-gb-mit": "^3.1.18", "@cspell/dict-filetypes": "^3.0.15", "@cspell/dict-flutter": "^1.1.1", "@cspell/dict-fonts": "^4.0.5", @@ -306,17 +322,17 @@ "@cspell/dict-markdown": "^2.0.14", "@cspell/dict-monkeyc": "^1.0.12", "@cspell/dict-node": "^5.0.9", - "@cspell/dict-npm": "^5.2.31", + "@cspell/dict-npm": "^5.2.34", "@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-r": "^2.1.1", "@cspell/dict-ruby": "^5.1.0", - "@cspell/dict-rust": "^4.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.20", + "@cspell/dict-software-terms": "^5.1.21", "@cspell/dict-sql": "^2.2.1", "@cspell/dict-svelte": "^1.0.7", "@cspell/dict-swift": "^2.0.6", @@ -330,22 +346,22 @@ } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.6.2.tgz", - "integrity": "sha512-8TCD7KOG9ppo5BoJOe2diACfB6I6UpJmYmjLOxMy0o8y3ruWFoDKaDEsf5tIi4T7cdVb8MjGbHjw9ksCwRRMjA==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.6.2" + "@cspell/cspell-types": "9.7.0" }, "engines": { "node": ">=20" } }, "node_modules/@cspell/cspell-performance-monitor": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-performance-monitor/-/cspell-performance-monitor-9.6.2.tgz", - "integrity": "sha512-MZuhYy59zFCVsX3PzW02/3TqPsPw87MELOJuZfpWDcGgxrweTrVjMdmJ0/w7COJ6zEAqtgGjNMAEmK4xJnrQjQ==", + "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==", "dev": true, "license": "MIT", "engines": { @@ -353,9 +369,9 @@ } }, "node_modules/@cspell/cspell-pipe": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.6.2.tgz", - "integrity": "sha512-Wt6Cf4b/E0QJ/TkbOMjXSGrccASgbc8xZq3c+8+kCXM5JT92NP2Lx67m3UA1g+BDv7E4DNPuwm1fM7o/2zum5w==", + "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==", "dev": true, "license": "MIT", "engines": { @@ -363,22 +379,22 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.6.2.tgz", - "integrity": "sha512-u7P4ErApEcSP+Si2HaeotFQXjuCopAa+wPF1fDzuJzpotPxsDwNDanGGn2qUMjOyVI4UiI84MPI6ZuGLj5EDyQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.7.0.tgz", + "integrity": "sha512-uiEgS238mdabDnwavo6HXt8K98jlh/jpm7NONroM9NTr9rzck2VZKD2kXEj85wDNMtRsRXNoywTjwQ8WTB6/+w==", "dev": true, "license": "MIT", "dependencies": { - "global-directory": "^4.0.1" + "global-directory": "^5.0.0" }, "engines": { "node": ">=20" } }, "node_modules/@cspell/cspell-service-bus": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.6.2.tgz", - "integrity": "sha512-T4LBWe3NYpKPD/fIkYAL56z5pr8Cgh//UZDl4afDTJNuTkdE6ZL93MBAUXggONHqY8B9dRXlQKrD4PD+kHabtw==", + "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==", "dev": true, "license": "MIT", "engines": { @@ -386,9 +402,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.6.2.tgz", - "integrity": "sha512-RsUFrSB0oQHEBnR8yarKIReUPwSu2ROpbjhdVKi4T/nQhMaS+TnIQPBwkMtb2r8A1KS2Hijw4D/4bV/XHoFQWw==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.7.0.tgz", + "integrity": "sha512-Tdfx4eH2uS+gv9V9NCr3Rz+c7RSS6ntXp3Blliud18ibRUlRxO9dTaOjG4iv4x0nAmMeedP1ORkEpeXSkh2QiQ==", "dev": true, "license": "MIT", "engines": { @@ -396,13 +412,13 @@ } }, "node_modules/@cspell/cspell-worker": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-worker/-/cspell-worker-9.6.2.tgz", - "integrity": "sha512-1xq8jmt6YZ7MVPESydjYJ3p67vi+YWgi5qow1xyZzeQWFXVCCFi9pQSxC0bzGQwWrYGNWSAIbYZB3Sq5ntYz4w==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@cspell/cspell-worker/-/cspell-worker-9.7.0.tgz", + "integrity": "sha512-cjEApFF0aOAa1vTUk+e7xP8ofK7iC7hsRzj1FmvvVQz8PoLWPRaq+1bT89ypPsZQvavqm5sIgb97S60/aW4TVg==", "dev": true, "license": "MIT", "dependencies": { - "cspell-lib": "9.6.2" + "cspell-lib": "9.7.0" }, "engines": { "node": ">=20.18" @@ -503,9 +519,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-dotnet": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.11.tgz", - "integrity": "sha512-LSVKhpFf/ASTWJcfYeS0Sykcl1gVMsv2Z5Eo0TnTMSTLV3738HH+66pIsjUTChqU6SF3gKPuCe6EOaRYqb/evA==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.12.tgz", + "integrity": "sha512-FiV934kNieIjGTkiApu/WKvLYi/KBpvfWB2TSqpDQtmXZlt3uSa5blwblO1ZC8OvjH8RCq/31H5IdEYmTaZS7A==", "dev": true, "license": "MIT" }, @@ -517,9 +533,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.4.27", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.27.tgz", - "integrity": "sha512-0y4vH2i5cFmi8sxkc4OlD2IlnqDznOtKczm4h6jA288g5VVrm3bhkYK6vcB8b0CoRKtYWKet4VEmHBP1yI+Qfw==", + "version": "4.4.29", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.29.tgz", + "integrity": "sha512-G3B27++9ziRdgbrY/G/QZdFAnMzzx17u8nCb2Xyd4q6luLpzViRM/CW3jA+Mb/cGT5zR/9N+Yz9SrGu1s0bq7g==", "dev": true, "license": "MIT" }, @@ -531,16 +547,16 @@ "license": "CC BY-SA 4.0" }, "node_modules/@cspell/dict-en-gb-mit": { - "version": "3.1.16", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.16.tgz", - "integrity": "sha512-4PPdapCJslytxAVJu35Mv97qDyGmAQxtDE790T2bWNhcqN6gvRVAc/eTRaXkUIf21q1xCxxNNqpH4VfMup69rQ==", + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.18.tgz", + "integrity": "sha512-AXaMzbaxhSc32MSzKX0cpwT+Thv1vPfxQz1nTly1VHw3wQcwPqVFSqrLOYwa8VNqAPR45583nnhD6iqJ9YESoQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.15.tgz", - "integrity": "sha512-uDMeqYlLlK476w/muEFQGBy9BdQWS0mQ7BJiy/iQv5XUWZxE2O54ZQd9nW8GyQMzAgoyg5SG4hf9l039Qt66oA==", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.16.tgz", + "integrity": "sha512-SyrtuK2/sx+cr94jOp2/uOAb43ngZEVISUTRj4SR6SfoGULVV1iJS7Drqn7Ul9HJ731QDttwWlOUgcQ+yMRblg==", "dev": true, "license": "MIT" }, @@ -650,9 +666,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-latex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-5.0.0.tgz", - "integrity": "sha512-HUrIqUVohM6P0+5b7BsdAdb0STIv0aaFBvguI7pLcreljlcX3FSPUxea7ticzNlCNeVrEaiEn/ws9m6rYUeuNw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-5.1.0.tgz", + "integrity": "sha512-qxT4guhysyBt0gzoliXYEBYinkAdEtR2M7goRaUH0a7ltCsoqqAeEV8aXYRIdZGcV77gYSobvu3jJL038tlPAw==", "dev": true, "license": "MIT" }, @@ -705,9 +721,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.31", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.31.tgz", - "integrity": "sha512-+HoFoFe53pL0wDuSHRs5L+CcDMaG5sLfjKLPT4H0VdwNzho3HLOohTCZr6cYt7OEbXf3xi4YXBkamCy38xOpjA==", + "version": "5.2.35", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.35.tgz", + "integrity": "sha512-w0VIDUvzHSTt4S9pfvSatApxtCesLMFrDUYD0Wjtw91EBRkB2wVw/RV3q1Ni9Nzpx6pCFpcB7c1xBY8l22cyiQ==", "dev": true, "license": "MIT" }, @@ -726,9 +742,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-public-licenses": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.15.tgz", - "integrity": "sha512-cJEOs901H13Pfy0fl4dCD1U+xpWIMaEPq8MeYU83FfDZvellAuSo4GqWCripfIqlhns/L6+UZEIJSOZnjgy7Wg==", + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.16.tgz", + "integrity": "sha512-EQRrPvEOmwhwWezV+W7LjXbIBjiy6y/shrET6Qcpnk3XANTzfvWflf9PnJ5kId/oKWvihFy0za0AV1JHd03pSQ==", "dev": true, "license": "MIT" }, @@ -757,9 +773,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-rust": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.1.1.tgz", - "integrity": "sha512-fXiXnZH0wOaEVTKFRNaz6TsUGhuB8dAT0ubYkDNzRQCaV5JGSOebGb1v2x5ZrOSVp+moxWM/vdBfiNU6KOEaFQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.1.2.tgz", + "integrity": "sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg==", "dev": true, "license": "MIT" }, @@ -778,9 +794,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "5.1.20", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.1.20.tgz", - "integrity": "sha512-TEk1xHvetTI4pv7Vzje1D322m6QEjaH2P6ucOOf6q7EJCppQIdC0lZSXkgHJAFU5HGSvEXSzvnVeW2RHW86ziQ==", + "version": "5.1.23", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.1.23.tgz", + "integrity": "sha512-YzxBeqP1j8+hg/+pmw7XHvYrQLO5ttDpZ0rqZiS7y2vnku3Cv1OQZgt9y/3SsTgcUPSCWSRHGgWfrMGqEGNB6g==", "dev": true, "license": "MIT" }, @@ -834,13 +850,13 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.6.2.tgz", - "integrity": "sha512-DY/X6lsdK4aeJ4erPVZoU1ccEXqtnYqWCMUXZOsMeIsZlXwZz/ocNNd09A4ga9IzGj1lYsB13UG4GVe8lSMAXQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.7.0.tgz", + "integrity": "sha512-Ws36IYvtS/8IN3x6K9dPLvTmaArodRJmzTn2Rkf2NaTnIYWhRuFzsP3SVVO59NN3fXswAEbmz5DSbVUe8bPZHg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.6.2", + "@cspell/url": "9.7.0", "import-meta-resolve": "^4.2.0" }, "engines": { @@ -848,19 +864,29 @@ } }, "node_modules/@cspell/filetypes": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.6.2.tgz", - "integrity": "sha512-XYAuGZoRCUf4Y12YP+K0BpU3QUMj4Z4SkKpi08Dwx/bQlq/NqycHKkUWYhlViHLav1+MJbWxcvDIHxGNv0UIaA==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.7.0.tgz", + "integrity": "sha512-Ln9e/8wGOyTeL3DCCs6kwd18TSpTw3kxsANjTrzLDASrX4cNmAdvc9J5dcIuBHPaqOAnRQxuZbzUlpRh73Y24w==", "dev": true, "license": "MIT", "engines": { "node": ">=20" } }, + "node_modules/@cspell/rpc": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@cspell/rpc/-/rpc-9.7.0.tgz", + "integrity": "sha512-VnZ4ABgQeoS4RwofcePkDP7L6tf3Kh5D7LQKoyRM4R6XtfSsYefym6XKaRl3saGtthH5YyjgNJ0Tgdjen4wAAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18" + } + }, "node_modules/@cspell/strong-weak-map": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.6.2.tgz", - "integrity": "sha512-7zpnLkpT91wsH4aU3oAprnzrURvBWKq97j5i/SWXGuNKf36XNEO4HaeaPp6L2oVq4OzdUOdm0tUK1gB0HhMWSg==", + "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==", "dev": true, "license": "MIT", "engines": { @@ -868,9 +894,9 @@ } }, "node_modules/@cspell/url": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.6.2.tgz", - "integrity": "sha512-625EiP1jUOQZ6UQuTUV1XB8Bxa18z3EtC1qA6PJyM3TqUD8PD8Tz183j9av6d/Dq52+7w0F4ovuqjUcTXTfD6g==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.7.0.tgz", + "integrity": "sha512-ZaaBr0pTvNxmyUbIn+nVPXPr383VqJzfUDMWicgTjJIeo2+T2hOq2kNpgpvTIrWtZrsZnSP8oXms1+sKTjcvkw==", "dev": true, "license": "MIT", "engines": { @@ -878,9 +904,9 @@ } }, "node_modules/@csstools/color-helpers": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", - "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", "dev": true, "funding": [ { @@ -894,13 +920,13 @@ ], "license": "MIT-0", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, "node_modules/@csstools/css-calc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", - "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz", + "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==", "dev": true, "funding": [ { @@ -914,17 +940,17 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-color-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", - "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "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==", "dev": true, "funding": [ { @@ -938,21 +964,21 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.1.0", - "@csstools/css-calc": "^2.1.4" + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.1.1" }, "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", "dev": true, "funding": [ { @@ -966,16 +992,16 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.26", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.26.tgz", - "integrity": "sha512-6boXK0KkzT5u5xOgF6TKB+CLq9SOpEGmkZw0g5n9/7yg85wab3UzSxB8TxhLJ31L4SGJ6BCFRw/iftTha1CJXA==", + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.28.tgz", + "integrity": "sha512-1NRf1CUBjnr3K7hu8BLxjQrKCxEe8FP/xmPTenAxCRZWVLbmGotkFvG9mfNpjA6k7Bw1bw4BilZq9cu19RA5pg==", "dev": true, "funding": [ { @@ -990,9 +1016,9 @@ "license": "MIT-0" }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", "dev": true, "funding": [ { @@ -1006,7 +1032,31 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-5.0.0.tgz", + "integrity": "sha512-T9lXmZOfnam3eMERPsszjY5NK0jX8RmThmmm99FZ8b7z8yMaFZWKwLWGZuTwdO3ddRY5fy13GmmEYZXB4I98Eg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/selector-resolve-nested": { @@ -1156,17 +1206,17 @@ "optional": true }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.83.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.83.0.tgz", - "integrity": "sha512-e1MHSEPJ4m35zkBvNT6kcdeH1SvMaJDsPC3Xhfseg3hvF50FUE3f46Yn36jgbrPYYXezlWUQnevv23c+lx2MCA==", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.84.0.tgz", + "integrity": "sha512-0xew1CxOam0gV5OMjh2KjFQZsKL2bByX1+q4j3E73MpYIdyUxcZb/xQct9ccUb+ve5KGUYbCUxyPnYB7RbuP+w==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.8", - "@typescript-eslint/types": "^8.53.1", + "@typescript-eslint/types": "^8.54.0", "comment-parser": "1.4.5", "esquery": "^1.7.0", - "jsdoc-type-pratt-parser": "~7.1.0" + "jsdoc-type-pratt-parser": "~7.1.1" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -1183,9 +1233,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", "cpu": [ "ppc64" ], @@ -1200,9 +1250,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", "cpu": [ "arm" ], @@ -1217,9 +1267,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", "cpu": [ "arm64" ], @@ -1234,9 +1284,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", "cpu": [ "x64" ], @@ -1251,9 +1301,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", "cpu": [ "arm64" ], @@ -1268,9 +1318,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", "cpu": [ "x64" ], @@ -1285,9 +1335,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", "cpu": [ "arm64" ], @@ -1302,9 +1352,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", "cpu": [ "x64" ], @@ -1319,9 +1369,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", "cpu": [ "arm" ], @@ -1336,9 +1386,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", "cpu": [ "arm64" ], @@ -1353,9 +1403,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", "cpu": [ "ia32" ], @@ -1370,9 +1420,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", "cpu": [ "loong64" ], @@ -1387,9 +1437,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", "cpu": [ "mips64el" ], @@ -1404,9 +1454,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", "cpu": [ "ppc64" ], @@ -1421,9 +1471,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", "cpu": [ "riscv64" ], @@ -1438,9 +1488,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", "cpu": [ "s390x" ], @@ -1455,9 +1505,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", "cpu": [ "x64" ], @@ -1472,9 +1522,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", "cpu": [ "arm64" ], @@ -1489,9 +1539,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", "cpu": [ "x64" ], @@ -1506,9 +1556,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", "cpu": [ "arm64" ], @@ -1523,9 +1573,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", "cpu": [ "x64" ], @@ -1540,9 +1590,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", "cpu": [ "arm64" ], @@ -1557,9 +1607,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", "cpu": [ "x64" ], @@ -1574,9 +1624,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", "cpu": [ "arm64" ], @@ -1591,9 +1641,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", "cpu": [ "ia32" ], @@ -1608,9 +1658,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", "cpu": [ "x64" ], @@ -1677,6 +1727,12 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -1688,9 +1744,9 @@ } }, "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -1724,19 +1780,19 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", + "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", + "minimatch": "^3.1.3", "strip-json-comments": "^3.1.1" }, "engines": { @@ -1747,9 +1803,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -1762,6 +1818,12 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -1779,9 +1841,9 @@ "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -1791,9 +1853,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", + "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1825,9 +1887,9 @@ } }, "node_modules/@exodus/bytes": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.10.0.tgz", - "integrity": "sha512-tf8YdcbirXdPnJ+Nd4UN1EXnz+IP2DI45YVEr3vvzcVTOyrApkmIB4zvOQVd3XPr7RXnfBtAx+PXImXOIU0Ajg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.1.tgz", + "integrity": "sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==", "dev": true, "license": "MIT", "engines": { @@ -1843,9 +1905,9 @@ } }, "node_modules/@fontsource/roboto": { - "version": "5.2.9", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.9.tgz", - "integrity": "sha512-ZTkyHiPk74B/aj8BZWbsxD5Yu+Lq+nR64eV4wirlrac2qXR7jYk2h6JlLYuOuoruTkGQWNw2fMuKNavw7/rg0w==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.10.tgz", + "integrity": "sha512-8HlA5FtSfz//oFSr2eL7GFXAiE7eIkcGOtx7tjsLKq+as702x9+GU7K95iDeWFapHC4M2hv9RrpXKRTGGBI8Zg==", "license": "OFL-1.1", "funding": { "url": "https://github.com/sponsors/ayuhito" @@ -1861,9 +1923,9 @@ } }, "node_modules/@fortawesome/fontawesome-free": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-7.1.0.tgz", - "integrity": "sha512-+WxNld5ZCJHvPQCr/GnzCTVREyStrAJjisUPtUxG5ngDA8TMlPnKp6dddlTpai4+1GNmltAeuk1hJEkBohwZYA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-7.2.0.tgz", + "integrity": "sha512-3DguDv/oUE+7vjMeTSOjCSG+KeawgVQOHrKRnvUuqYh1mfArrh7s+s8hXW3e4RerBA1+Wh+hBqf8sJNpqNrBWg==", "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", "engines": { "node": ">=6" @@ -2116,9 +2178,9 @@ "license": "MIT" }, "node_modules/@mswjs/interceptors": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.40.0.tgz", - "integrity": "sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==", + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.3.tgz", + "integrity": "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==", "dev": true, "license": "MIT", "dependencies": { @@ -2292,27 +2354,6 @@ "node": ">=10" } }, - "node_modules/@pm2/agent/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/@pm2/blessed": { "version": "0.1.81", "resolved": "https://registry.npmjs.org/@pm2/blessed/-/blessed-0.1.81.tgz", @@ -2457,27 +2498,6 @@ "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==", "license": "MIT" }, - "node_modules/@pm2/js-api/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/@pm2/pm2-version-check": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz", @@ -2495,9 +2515,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.0.tgz", - "integrity": "sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", "cpu": [ "arm" ], @@ -2509,9 +2529,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.0.tgz", - "integrity": "sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", "cpu": [ "arm64" ], @@ -2523,9 +2543,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.0.tgz", - "integrity": "sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", "cpu": [ "arm64" ], @@ -2537,9 +2557,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.0.tgz", - "integrity": "sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", "cpu": [ "x64" ], @@ -2551,9 +2571,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.0.tgz", - "integrity": "sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", "cpu": [ "arm64" ], @@ -2565,9 +2585,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.0.tgz", - "integrity": "sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", "cpu": [ "x64" ], @@ -2579,9 +2599,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.0.tgz", - "integrity": "sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", "cpu": [ "arm" ], @@ -2593,9 +2613,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.0.tgz", - "integrity": "sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", "cpu": [ "arm" ], @@ -2607,9 +2627,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.0.tgz", - "integrity": "sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", "cpu": [ "arm64" ], @@ -2621,9 +2641,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.0.tgz", - "integrity": "sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", "cpu": [ "arm64" ], @@ -2635,9 +2655,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.0.tgz", - "integrity": "sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", "cpu": [ "loong64" ], @@ -2649,9 +2669,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.0.tgz", - "integrity": "sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", "cpu": [ "loong64" ], @@ -2663,9 +2683,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.0.tgz", - "integrity": "sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", "cpu": [ "ppc64" ], @@ -2677,9 +2697,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.0.tgz", - "integrity": "sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", "cpu": [ "ppc64" ], @@ -2691,9 +2711,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.0.tgz", - "integrity": "sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", "cpu": [ "riscv64" ], @@ -2705,9 +2725,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.0.tgz", - "integrity": "sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", "cpu": [ "riscv64" ], @@ -2719,9 +2739,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.0.tgz", - "integrity": "sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", "cpu": [ "s390x" ], @@ -2733,9 +2753,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.0.tgz", - "integrity": "sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", "cpu": [ "x64" ], @@ -2747,9 +2767,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.0.tgz", - "integrity": "sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", "cpu": [ "x64" ], @@ -2761,9 +2781,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.0.tgz", - "integrity": "sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", "cpu": [ "x64" ], @@ -2775,9 +2795,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.0.tgz", - "integrity": "sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", "cpu": [ "arm64" ], @@ -2789,9 +2809,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.0.tgz", - "integrity": "sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", "cpu": [ "arm64" ], @@ -2803,9 +2823,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.0.tgz", - "integrity": "sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", "cpu": [ "ia32" ], @@ -2817,9 +2837,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.0.tgz", - "integrity": "sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", "cpu": [ "x64" ], @@ -2831,9 +2851,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.0.tgz", - "integrity": "sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", "cpu": [ "x64" ], @@ -2910,14 +2930,14 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.7.1.tgz", - "integrity": "sha512-zjTUwIsEfT+k9BmXwq1QEFYsb4afBlsI1AXFyWQBgggMzwBFOuu92pGrE5OFx90IOjNl+lUbQoTG7f8S0PkOdg==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.9.0.tgz", + "integrity": "sha512-FqqSkvDMYJReydrMhlugc71M76yLLQWNfmGq+SIlLa7N3kHp8Qq8i2PyWrVNAfjOyOIY+xv9XaaYwvVW7vroMA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/types": "^8.53.1", + "@typescript-eslint/types": "^8.56.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "estraverse": "^5.3.0", @@ -2927,7 +2947,7 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": ">=9.0.0" + "eslint": "^9.0.0 || ^10.0.0" } }, "node_modules/@szmarczak/http-timer": { @@ -3062,9 +3082,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz", - "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==", + "version": "24.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.11.0.tgz", + "integrity": "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==", "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -3105,14 +3125,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz", - "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", + "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.54.0", - "@typescript-eslint/types": "^8.54.0", + "@typescript-eslint/tsconfig-utils": "^8.56.1", + "@typescript-eslint/types": "^8.56.1", "debug": "^4.4.3" }, "engines": { @@ -3127,14 +3147,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz", - "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", + "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0" + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3145,9 +3165,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz", - "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", + "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", "dev": true, "license": "MIT", "engines": { @@ -3162,9 +3182,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz", - "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", + "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", "dev": true, "license": "MIT", "engines": { @@ -3176,18 +3196,18 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz", - "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", + "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.54.0", - "@typescript-eslint/tsconfig-utils": "8.54.0", - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0", + "@typescript-eslint/project-service": "8.56.1", + "@typescript-eslint/tsconfig-utils": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3", - "minimatch": "^9.0.5", + "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" @@ -3204,16 +3224,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz", - "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", + "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.54.0", - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/typescript-estree": "8.54.0" + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3223,19 +3243,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz", - "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", + "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.54.0", - "eslint-visitor-keys": "^4.2.1" + "@typescript-eslint/types": "8.56.1", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3245,6 +3265,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", @@ -3546,14 +3579,14 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.6.tgz", - "integrity": "sha512-bwgQxQWRtnTVzsUHK824tBmHzjV0iTx3tZaiQIYDjX3SA7TsQS8CuDVqxXrRY3FaOUMgbGavesCxI9MOfFLm7Q==", + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.9.tgz", + "integrity": "sha512-9WfPx1OwJ19QLCSRLkqVO7//1WcWnK3fE/3fJhKMAmDe8+9G4rB47xCNIIeCq3FdEzkIoLTfDlwDlPBaUTMhow==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "^8.51.0", - "@typescript-eslint/utils": "^8.51.0" + "@typescript-eslint/scope-manager": "^8.55.0", + "@typescript-eslint/utils": "^8.55.0" }, "engines": { "node": ">=18" @@ -3725,9 +3758,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3755,9 +3788,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -3801,9 +3834,9 @@ } }, "node_modules/ansi-escapes": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", - "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", "dev": true, "license": "MIT", "dependencies": { @@ -3936,15 +3969,15 @@ "license": "0BSD" }, "node_modules/ast-v8-to-istanbul": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.10.tgz", - "integrity": "sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.12.tgz", + "integrity": "sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", - "js-tokens": "^9.0.1" + "js-tokens": "^10.0.0" } }, "node_modules/astral-regex": { @@ -3964,10 +3997,14 @@ "license": "MIT" }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/base64id": { "version": "2.0.0", @@ -3992,9 +4029,9 @@ } }, "node_modules/basic-ftp": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.1.0.tgz", - "integrity": "sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz", + "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -4061,13 +4098,16 @@ "optional": true }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { @@ -4108,16 +4148,16 @@ } }, "node_modules/cacheable": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.2.tgz", - "integrity": "sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.3.tgz", + "integrity": "sha512-iffYMX4zxKp54evOH27fm92hs+DeC1DhXmNVN8Tr94M/iZIV42dqTHSR2Ik4TOSPyOAwKr7Yu3rN9ALoLkbWyQ==", "dev": true, "license": "MIT", "dependencies": { - "@cacheable/memory": "^2.0.7", - "@cacheable/utils": "^2.3.3", + "@cacheable/memory": "^2.0.8", + "@cacheable/utils": "^2.4.0", "hookified": "^1.15.0", - "keyv": "^5.5.5", + "keyv": "^5.6.0", "qified": "^0.6.0" } }, @@ -4557,9 +4597,9 @@ "license": "MIT" }, "node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "dev": true, "license": "MIT", "engines": { @@ -4712,9 +4752,19 @@ } }, "node_modules/croner": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/croner/-/croner-9.1.0.tgz", - "integrity": "sha512-p9nwwR4qyT5W996vBZhdvBCnMhicY5ytZkR4D1Xj0wuTDEiMnjwR57Q3RXYY/s0EpX6Ay3vgIcfaR+ewGHsi+g==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/croner/-/croner-10.0.1.tgz", + "integrity": "sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g==", + "funding": [ + { + "type": "other", + "url": "https://paypal.me/hexagonpp" + }, + { + "type": "github", + "url": "https://github.com/sponsors/hexagon" + } + ], "license": "MIT", "engines": { "node": ">=18.0" @@ -4735,32 +4785,32 @@ } }, "node_modules/cspell": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.6.2.tgz", - "integrity": "sha512-EmkSGhStMbSh2BcyMqbVDOF48fSPWL3adjqajUVCwfnlZD7mzUWPx9pR8pt2dOQaFEE47rlOQGXdd3wTqL5dnQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.7.0.tgz", + "integrity": "sha512-ftxOnkd+scAI7RZ1/ksgBZRr0ouC7QRKtPQhD/PbLTKwAM62sSvRhE1bFsuW3VKBn/GilWzTjkJ40WmnDqH5iQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "9.6.2", - "@cspell/cspell-performance-monitor": "9.6.2", - "@cspell/cspell-pipe": "9.6.2", - "@cspell/cspell-types": "9.6.2", - "@cspell/cspell-worker": "9.6.2", - "@cspell/dynamic-import": "9.6.2", - "@cspell/url": "9.6.2", + "@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", "ansi-regex": "^6.2.2", "chalk": "^5.6.2", "chalk-template": "^1.1.2", - "commander": "^14.0.2", - "cspell-config-lib": "9.6.2", - "cspell-dictionary": "9.6.2", - "cspell-gitignore": "9.6.2", - "cspell-glob": "9.6.2", - "cspell-io": "9.6.2", - "cspell-lib": "9.6.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", "fast-json-stable-stringify": "^2.1.0", "flatted": "^3.3.3", - "semver": "^7.7.3", + "semver": "^7.7.4", "tinyglobby": "^0.2.15" }, "bin": { @@ -4775,13 +4825,13 @@ } }, "node_modules/cspell-config-lib": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.6.2.tgz", - "integrity": "sha512-VQB+xmqGqCJrt5k/o0rRG9v0X0CA96CEd9FsmBAm5+9DvNiRzXOqewZSdsOM2Y0SX7YKcvG82PfRsujhYltcfQ==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.6.2", + "@cspell/cspell-types": "9.7.0", "comment-json": "^4.5.1", "smol-toml": "^1.6.0", "yaml": "^2.8.2" @@ -4791,16 +4841,16 @@ } }, "node_modules/cspell-dictionary": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.6.2.tgz", - "integrity": "sha512-J55/9+AtkRzfSVn+KaqoWxsS4O66szKP6LrDW0O2qWnuvVvO1BoAMsINynD845IIzrd1n1yTOHS/DbjmHd4//A==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.7.0.tgz", + "integrity": "sha512-k/Wz0so32+0QEqQe21V9m4BNXM5ZN6lz3Ix/jLCbMxFIPl6wT711ftjOWIEMFhvUOP0TWXsbzcuE9mKtS5mTig==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-performance-monitor": "9.6.2", - "@cspell/cspell-pipe": "9.6.2", - "@cspell/cspell-types": "9.6.2", - "cspell-trie-lib": "9.6.2", + "@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", "fast-equals": "^6.0.0" }, "engines": { @@ -4808,15 +4858,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.6.2.tgz", - "integrity": "sha512-vtwc9AAA9m3aZPtbvPPRTLXIqwryljxEgQTkpr92mFZaGftvnLfNVb2z++NvWbXq9azGKN/7oiLjecb9dhYnfA==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.7.0.tgz", + "integrity": "sha512-MtoYuH4ah4K6RrmaF834npMcRsTKw0658mC6yvmBacUQOmwB/olqyuxF3fxtbb55HDb7cXDQ35t1XuwwGEQeZw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.6.2", - "cspell-glob": "9.6.2", - "cspell-io": "9.6.2" + "@cspell/url": "9.7.0", + "cspell-glob": "9.7.0", + "cspell-io": "9.7.0" }, "bin": { "cspell-gitignore": "bin.mjs" @@ -4826,13 +4876,13 @@ } }, "node_modules/cspell-glob": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.6.2.tgz", - "integrity": "sha512-5j+g4JzcWjW16ZAtcPHpG138CEfpp1YmuYJoYtze3lIZLgttt+k2gXJsqyWaP/6MdVknI0Q1afGSKYRtH8mLRA==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.7.0.tgz", + "integrity": "sha512-LUeAoEsoCJ+7E3TnUmWBscpVQOmdwBejMlFn0JkXy6LQzxrybxXBKf65RSdIv1o5QtrhQIMa358xXYQG0sv/tA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.6.2", + "@cspell/url": "9.7.0", "picomatch": "^4.0.3" }, "engines": { @@ -4840,14 +4890,14 @@ } }, "node_modules/cspell-grammar": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.6.2.tgz", - "integrity": "sha512-JTH92+1VGFPb3UsDT+Ezur/ouR8t+XOZkETUkk8eoSBzli9hWgPHW7kl2T8Chcn+Dq/6FLlvezYbBvhSauqJRw==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.7.0.tgz", + "integrity": "sha512-oEYME+7MJztfVY1C06aGcJgEYyqBS/v/ETkQGPzf/c6ObSAPRcUbVtsXZgnR72Gru9aBckc70xJcD6bELdoWCA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.6.2", - "@cspell/cspell-types": "9.6.2" + "@cspell/cspell-pipe": "9.7.0", + "@cspell/cspell-types": "9.7.0" }, "bin": { "cspell-grammar": "bin.mjs" @@ -4857,43 +4907,44 @@ } }, "node_modules/cspell-io": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.6.2.tgz", - "integrity": "sha512-VRBkAfUdbaq5yDYoVMvodQF3bIdBL6Gy4tiMvf+UI9C16am47AuThg1gGXRzwi5hCEXnCfevAmuVdaQP3onkow==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.7.0.tgz", + "integrity": "sha512-V7x0JHAUCcJPRCH8c0MQkkaKmZD2yotxVyrNEx2SZTpvnKrYscLEnUUTWnGJIIf9znzISqw116PLnYu2c+zd6Q==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "9.6.2", - "@cspell/url": "9.6.2" + "@cspell/cspell-service-bus": "9.7.0", + "@cspell/url": "9.7.0" }, "engines": { "node": ">=20" } }, "node_modules/cspell-lib": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.6.2.tgz", - "integrity": "sha512-LvValIwqDAwVp2Www+7PPJ7UbVurYtKGPddpGH7GN+0u+UWzR4oUXR80gY8lHgSrIQ3EkdLhFAItPcyMjGjzIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-bundled-dicts": "9.6.2", - "@cspell/cspell-performance-monitor": "9.6.2", - "@cspell/cspell-pipe": "9.6.2", - "@cspell/cspell-resolver": "9.6.2", - "@cspell/cspell-types": "9.6.2", - "@cspell/dynamic-import": "9.6.2", - "@cspell/filetypes": "9.6.2", - "@cspell/strong-weak-map": "9.6.2", - "@cspell/url": "9.6.2", + "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.6.2", - "cspell-dictionary": "9.6.2", - "cspell-glob": "9.6.2", - "cspell-grammar": "9.6.2", - "cspell-io": "9.6.2", - "cspell-trie-lib": "9.6.2", - "env-paths": "^3.0.0", + "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", + "env-paths": "^4.0.0", "gensequence": "^8.0.8", "import-fresh": "^3.3.1", "resolve-from": "^5.0.0", @@ -4906,16 +4957,16 @@ } }, "node_modules/cspell-trie-lib": { - "version": "9.6.2", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.6.2.tgz", - "integrity": "sha512-JpCHpMdxo680yEkb6U1y3wrhZGHltgCnaQ8Zj6yKE8KE0BTLVl9UQGisP5De1wlFn4GtpPCf7WtQ8+M5aqq3YQ==", + "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==", "dev": true, "license": "MIT", "engines": { "node": ">=20" }, "peerDependencies": { - "@cspell/cspell-types": "9.6.2" + "@cspell/cspell-types": "9.7.0" } }, "node_modules/cspell/node_modules/chalk": { @@ -4932,13 +4983,13 @@ } }, "node_modules/css-functions-list": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", - "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", + "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", "dev": true, "license": "MIT", "engines": { - "node": ">=12 || >=16" + "node": ">=12" } }, "node_modules/css-tree": { @@ -4969,16 +5020,16 @@ } }, "node_modules/cssstyle": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz", - "integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.1.0.tgz", + "integrity": "sha512-Ml4fP2UT2K3CUBQnVlbdV/8aFDdlY69E+YnwJM+3VUWl08S3J8c8aRuJqCkD9Py8DHZ7zNNvsfKl8psocHZEFg==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^4.1.1", - "@csstools/css-syntax-patches-for-csstree": "^1.0.21", + "@asamuzakjp/css-color": "^5.0.0", + "@csstools/css-syntax-patches-for-csstree": "^1.0.28", "css-tree": "^3.1.0", - "lru-cache": "^11.2.4" + "lru-cache": "^11.2.6" }, "engines": { "node": ">=20" @@ -5000,27 +5051,17 @@ } }, "node_modules/data-urls": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.1.tgz", - "integrity": "sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", "dev": true, "license": "MIT", "dependencies": { "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^15.1.0" + "whatwg-url": "^16.0.0" }, "engines": { - "node": ">=20" - } - }, - "node_modules/data-urls/node_modules/whatwg-mimetype": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", - "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/dateformat": { @@ -5322,9 +5363,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "40.1.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-40.1.0.tgz", - "integrity": "sha512-2j/kvw7uF0H1PnzYBzw2k2Q6q16J8ToKrtQzZfsAoXbbMY0l5gQi2DLOauIZLzwp4O01n8Wt/74JhSRwG0yj9A==", + "version": "40.6.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-40.6.1.tgz", + "integrity": "sha512-u9YfoixttdauciHV9Ut9Zf3YipJoU093kR1GSYTTXTAXqhiXI0G1A0NnL/f0O2m2UULCXaXMf2W71PloR6V9pQ==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5484,13 +5525,16 @@ } }, "node_modules/env-paths": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", - "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-4.0.0.tgz", + "integrity": "sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==", "dev": true, "license": "MIT", + "dependencies": { + "is-safe-filename": "^0.1.0" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5564,9 +5608,9 @@ "optional": true }, "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -5577,32 +5621,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" } }, "node_modules/escalade": { @@ -5655,9 +5699,9 @@ } }, "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "version": "9.39.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", + "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", @@ -5666,7 +5710,7 @@ "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", + "@eslint/js": "9.39.3", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5714,13 +5758,13 @@ } }, "node_modules/eslint-fix-utils": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/eslint-fix-utils/-/eslint-fix-utils-0.4.0.tgz", - "integrity": "sha512-nCEciwqByGxsKiWqZjqK7xfL+7dUX9Pi0UL3J0tOwfxVN9e6Y59UxEt1ZYsc3XH0ce6T1WQM/QU2DbKK/6IG7g==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/eslint-fix-utils/-/eslint-fix-utils-0.4.1.tgz", + "integrity": "sha512-1xPtnB7RYRHKrFGll3kRv5gOodHm3/jkk76jrKMZ2yk/G8HU9XoN1I9iHgh1ToAqmGG0/FFrybZMqmqUWp4asA==", "dev": true, "license": "MIT", "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { "@types/estree": ">=1", @@ -5795,13 +5839,13 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "62.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.5.0.tgz", - "integrity": "sha512-D+1haMVDzW/ZMoPwOnsbXCK07rJtsq98Z1v+ApvDKxSzYTTcPgmFc/nyUDCGmxm2cP7g7hszyjYHO7Zodl/43w==", + "version": "62.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.7.1.tgz", + "integrity": "sha512-4Zvx99Q7d1uggYBUX/AIjvoyqXhluGbbKrRmG8SQTLprPFg6fa293tVJH1o1GQwNe3lUydd8ZHzn37OaSncgSQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.83.0", + "@es-joy/jsdoccomment": "~0.84.0", "@es-joy/resolve.exports": "1.2.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.5", @@ -5812,7 +5856,7 @@ "html-entities": "^2.6.0", "object-deep-merge": "^2.0.0", "parse-imports-exports": "^0.2.4", - "semver": "^7.7.3", + "semver": "^7.7.4", "spdx-expression-parse": "^4.0.0", "to-valid-identifier": "^1.0.0" }, @@ -5820,13 +5864,13 @@ "node": "^20.19.0 || ^22.13.0 || >=24" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" } }, "node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz", - "integrity": "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5837,15 +5881,15 @@ } }, "node_modules/eslint-plugin-jsdoc/node_modules/espree": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.0.tgz", - "integrity": "sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.1.tgz", + "integrity": "sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^5.0.0" + "eslint-visitor-keys": "^5.0.1" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -5855,9 +5899,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.88.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.88.2.tgz", - "integrity": "sha512-KCpzuc0sI/7Kzt+QBsSbq+e8ClpoiTuoID7D2WxQe2r3XB+2SSPkqqr9M9oLfUjQDsn3oROAnb5lP2yh+oBfVg==", + "version": "0.89.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.89.2.tgz", + "integrity": "sha512-1w9V/IwkkFzXJegbKHacbrOcupkIIp2F4ISB2JYfNl3g/NBiVbU8Db4IptVYVghcfJZlpVji2Us0cGCQPRCMVQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5865,8 +5909,8 @@ "change-case": "^5.4.4", "detect-indent": "^7.0.2", "detect-newline": "^4.0.1", - "eslint-fix-utils": "~0.4.0", - "package-json-validator": "~0.60.0", + "eslint-fix-utils": "~0.4.1", + "package-json-validator": "^1.0.1", "semver": "^7.7.3", "sort-object-keys": "^2.0.0", "sort-package-json": "^3.4.0", @@ -5877,17 +5921,17 @@ }, "peerDependencies": { "eslint": ">=8.0.0", - "jsonc-eslint-parser": "^2.0.0" + "jsonc-eslint-parser": ">=2.0.0" } }, "node_modules/eslint-plugin-playwright": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.5.1.tgz", - "integrity": "sha512-q7oqVQTTfa3VXJQ8E+ln0QttPGrs/XmSO1FjOMzQYBMYF3btih4FIrhEYh34JF184GYDmq3lJ/n7CMa49OHBvA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.8.0.tgz", + "integrity": "sha512-BRCXbnX20l/ZPOOi1jEqNvqU/UjXpkZRJaghQxSM2kjAvsDph8+osn9u1iMmvoa9Cegbp9d0Skh7vro7242t+Q==", "dev": true, "license": "MIT", "dependencies": { - "globals": "^16.4.0" + "globals": "^17.3.0" }, "engines": { "node": ">=16.9.0" @@ -5897,9 +5941,9 @@ } }, "node_modules/eslint-plugin-playwright/node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.3.0.tgz", + "integrity": "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==", "dev": true, "license": "MIT", "engines": { @@ -5938,9 +5982,9 @@ } }, "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -5953,6 +5997,12 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -5970,9 +6020,9 @@ "license": "MIT" }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -6516,9 +6566,9 @@ } }, "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", "dev": true, "license": "MIT", "engines": { @@ -6582,9 +6632,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "version": "4.13.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", "dev": true, "license": "MIT", "dependencies": { @@ -6661,16 +6711,16 @@ } }, "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-5.0.0.tgz", + "integrity": "sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==", "dev": true, "license": "MIT", "dependencies": { - "ini": "4.1.1" + "ini": "6.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6754,18 +6804,18 @@ } }, "node_modules/globby": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-15.0.0.tgz", - "integrity": "sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-16.1.0.tgz", + "integrity": "sha512-+A4Hq7m7Ze592k9gZRy4gJ27DrXRNnC1vPjxTt1qQxEY8RxagBkBxivkCwg7FxSTG0iLLEMaUx13oOr0R2/qcQ==", "dev": true, "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "fast-glob": "^3.3.3", "ignore": "^7.0.5", - "path-type": "^6.0.0", + "is-path-inside": "^4.0.0", "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" + "unicorn-magic": "^0.4.0" }, "engines": { "node": ">=20" @@ -6837,9 +6887,9 @@ "optional": true }, "node_modules/graphql": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", - "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", + "version": "16.13.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.0.tgz", + "integrity": "sha512-uSisMYERbaB9bkA9M4/4dnqyktaEkf1kMHNKq/7DHyxVeWqHQ2mBmVqm5u6/FVHwF3iCNalKcg82Zfl+tffWoA==", "dev": true, "license": "MIT", "engines": { @@ -6881,9 +6931,9 @@ } }, "node_modules/hashery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.4.0.tgz", - "integrity": "sha512-Wn2i1In6XFxl8Az55kkgnFRiAlIAushzh26PTjL2AKtQcEfXrcLa7Hn5QOWGZEf3LU057P9TwwZjFyxfS1VuvQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.0.tgz", + "integrity": "sha512-nhQ6ExaOIqti2FDWoEMWARUqIKyjr2VcZzXShrI+A3zpeiuPWzx6iPftt44LhP74E5sW36B75N6VHbvRtpvO6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6922,9 +6972,9 @@ } }, "node_modules/hookified": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.0.tgz", - "integrity": "sha512-51w+ZZGt7Zw5q7rM3nC4t3aLn/xvKDETsXqMczndvwyVQhAHfUmUuFBRFcos8Iyebtk7OAE9dL26wFNzZVVOkw==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", "dev": true, "license": "MIT" }, @@ -7185,13 +7235,13 @@ "license": "ISC" }, "node_modules/ini": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/ip-address": { @@ -7396,6 +7446,19 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/is-safe-filename": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-safe-filename/-/is-safe-filename-0.1.1.tgz", + "integrity": "sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -7454,9 +7517,9 @@ } }, "node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", "dev": true, "license": "MIT" }, @@ -7479,9 +7542,9 @@ "license": "Apache-2.0" }, "node_modules/jsdoc-type-pratt-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.1.0.tgz", - "integrity": "sha512-SX7q7XyCwzM/MEDCYz0l8GgGbJAACGFII9+WfNYr5SLEKukHWRy2Jk3iWRe7P+lpYJNs7oQ+OSei4JtKGUjd7A==", + "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==", "dev": true, "license": "MIT", "engines": { @@ -7489,17 +7552,18 @@ } }, "node_modules/jsdom": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.4.0.tgz", - "integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==", + "version": "28.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz", + "integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==", "dev": true, "license": "MIT", "dependencies": { - "@acemir/cssom": "^0.9.28", - "@asamuzakjp/dom-selector": "^6.7.6", - "@exodus/bytes": "^1.6.0", - "cssstyle": "^5.3.4", - "data-urls": "^6.0.0", + "@acemir/cssom": "^0.9.31", + "@asamuzakjp/dom-selector": "^6.8.1", + "@bramus/specificity": "^2.4.2", + "@exodus/bytes": "^1.11.0", + "cssstyle": "^6.0.1", + "data-urls": "^7.0.0", "decimal.js": "^10.6.0", "html-encoding-sniffer": "^6.0.0", "http-proxy-agent": "^7.0.2", @@ -7509,11 +7573,11 @@ "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^6.0.0", + "undici": "^7.21.0", "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^8.0.0", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^15.1.0", - "ws": "^8.18.3", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0", "xml-name-validator": "^5.0.0" }, "engines": { @@ -7561,53 +7625,33 @@ "optional": true }, "node_modules/jsonc-eslint-parser": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.2.tgz", - "integrity": "sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-3.1.0.tgz", + "integrity": "sha512-75EA7EWZExL/j+MDKQrRbdzcRI2HOkRlmUw8fZJc1ioqFEOvBsq7Rt+A6yCxOt9w/TYNpkt52gC6nm/g5tFIng==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "acorn": "^8.5.0", - "eslint-visitor-keys": "^3.0.0", - "espree": "^9.0.0", + "eslint-visitor-keys": "^5.0.0", "semver": "^7.3.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://github.com/sponsors/ota-meshi" } }, "node_modules/jsonc-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "peer": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/jsonc-eslint-parser/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -7631,9 +7675,9 @@ } }, "node_modules/katex": { - "version": "0.16.28", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.28.tgz", - "integrity": "sha512-YHzO7721WbmAL6Ov1uzN/l5mY5WWWhJBSW+jq4tkfZfsxmo1hu6frS0EOswvjBUnWE6NtjEs48SFn5CQESRLZg==", + "version": "0.16.33", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.33.tgz", + "integrity": "sha512-q3N5u+1sY9Bu7T4nlXoiRBXWfwSefNGoKeOwekV+gw0cAXQlz2Ww6BLcmBxVDeXBMUDQv6fK5bcNaJLxob3ZQA==", "dev": true, "funding": [ "https://opencollective.com/katex", @@ -7676,13 +7720,6 @@ "node": ">=0.10.0" } }, - "node_modules/known-css-properties": { - "version": "0.37.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", - "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", - "dev": true, - "license": "MIT" - }, "node_modules/leac": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz", @@ -7723,19 +7760,19 @@ } }, "node_modules/lint-staged": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.7.tgz", - "integrity": "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.3.0.tgz", + "integrity": "sha512-YVHHy/p6U4/No9Af+35JLh3umJ9dPQnGTvNCbfO/T5fC60us0jFnc+vw33cqveI+kqxIFJQakcMVTO2KM+653A==", "dev": true, "license": "MIT", "dependencies": { - "commander": "^14.0.2", + "commander": "^14.0.3", "listr2": "^9.0.5", "micromatch": "^4.0.8", "nano-spawn": "^2.0.0", - "pidtree": "^0.6.0", "string-argv": "^0.3.2", - "yaml": "^2.8.1" + "tinyexec": "^1.0.2", + "yaml": "^2.8.2" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -7830,9 +7867,9 @@ } }, "node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -7850,14 +7887,14 @@ } }, "node_modules/magicast": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", - "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, @@ -7878,9 +7915,9 @@ } }, "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", "dev": true, "license": "MIT", "dependencies": { @@ -7920,16 +7957,16 @@ } }, "node_modules/markdownlint-cli2": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.20.0.tgz", - "integrity": "sha512-esPk+8Qvx/f0bzI7YelUeZp+jCtFOk3KjZ7s9iBQZ6HlymSXoTtWGiIRZP05/9Oy2ehIoIjenVwndxGtxOIJYQ==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.21.0.tgz", + "integrity": "sha512-DzzmbqfMW3EzHsunP66x556oZDzjcdjjlL2bHG4PubwnL58ZPAfz07px4GqteZkoCGnBYi779Y2mg7+vgNCwbw==", "dev": true, "license": "MIT", "dependencies": { - "globby": "15.0.0", + "globby": "16.1.0", "js-yaml": "4.1.1", "jsonc-parser": "3.3.1", - "markdown-it": "14.1.0", + "markdown-it": "14.1.1", "markdownlint": "0.40.0", "markdownlint-cli2-formatter-default": "0.0.6", "micromatch": "4.0.8" @@ -7957,6 +7994,23 @@ "markdownlint-cli2": ">=0.0.4" } }, + "node_modules/markdownlint/node_modules/string-width": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -8014,9 +8068,9 @@ } }, "node_modules/meow": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-14.0.0.tgz", - "integrity": "sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-14.1.0.tgz", + "integrity": "sha512-EDYo6VlmtnumlcBCbh1gLJ//9jvM/ndXHfVXIFrZVr6fGcwTUyCTFNTLCKuY3ffbK8L/+3Mzqnd58RojiZqHVw==", "dev": true, "license": "MIT", "engines": { @@ -8660,16 +8714,16 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -8731,15 +8785,15 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.12.7", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.7.tgz", - "integrity": "sha512-retd5i3xCZDVWMYjHEVuKTmhqY8lSsxujjVrZiGbbdoxxIBg5S7rCuYy/YQpfrTYIxpd/o0Kyb/3H+1udBMoYg==", + "version": "2.12.10", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.10.tgz", + "integrity": "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { "@inquirer/confirm": "^5.0.0", - "@mswjs/interceptors": "^0.40.0", + "@mswjs/interceptors": "^0.41.2", "@open-draft/deferred-promise": "^2.2.0", "@types/statuses": "^2.0.6", "cookie": "^1.0.2", @@ -8749,7 +8803,7 @@ "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", - "rettime": "^0.7.0", + "rettime": "^0.10.1", "statuses": "^2.0.2", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", @@ -8910,9 +8964,9 @@ } }, "node_modules/node-ical": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.24.1.tgz", - "integrity": "sha512-49jmPpznMetMY+oEO+8AhZf/ccSdxuQfcOikjMzhls72OigEDtOMGFZumLHdHx6MVvJf1D7wnbbcn3kRHfIALQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.24.2.tgz", + "integrity": "sha512-2wJJZE/X3KKLTBtRHqgzJQkMVpTtvFrdQU2Kq02mCNI4QWshqKSuLRXZl5dPy1gF+7XzpFNxKtxHIwLL2q1BqQ==", "license": "Apache-2.0", "dependencies": { "@js-temporal/polyfill": "^0.5.1", @@ -9161,92 +9215,20 @@ } }, "node_modules/package-json-validator": { - "version": "0.60.0", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.60.0.tgz", - "integrity": "sha512-3BBkeFHm3O1VsazTSIN8+AGAl/eJQvTvWquECchRszIW6SC3aJ/fZHwZkpsmJlt7FMjTMNEgz+EhamVn94wgFw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-1.0.1.tgz", + "integrity": "sha512-1+g91/h2LU/QDtdX1EUFM40XIGxzgn/8TbWFZqzCnRxGRG+eIOW4+spYcjEn3u8IW2iOy6RIq99EIu26APGZfQ==", "dev": true, "license": "MIT", "dependencies": { "semver": "^7.7.2", "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^7.0.0", - "yargs": "~18.0.0" - }, - "bin": { - "pjv": "lib/bin/pjv.mjs" + "validate-npm-package-name": "^7.0.0" }, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/package-json-validator/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/package-json-validator/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, - "node_modules/package-json-validator/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-validator/node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/package-json-validator/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -9401,19 +9383,6 @@ "dev": true, "license": "MIT" }, - "node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -9457,19 +9426,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/pidusage": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz", @@ -9503,13 +9459,13 @@ "license": "MIT" }, "node_modules/playwright": { - "version": "1.58.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.1.tgz", - "integrity": "sha512-+2uTZHxSCcxjvGc5C891LrS1/NlxglGxzrC4seZiVjcYVQfUa87wBL6rTDqzGjuoWNjnBzRqKmF6zRYGMvQUaQ==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.58.1" + "playwright-core": "1.58.2" }, "bin": { "playwright": "cli.js" @@ -9522,9 +9478,9 @@ } }, "node_modules/playwright-core": { - "version": "1.58.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.1.tgz", - "integrity": "sha512-bcWzOaTxcW+VOOGBCQgnaKToLJ65d6AqfLVKEWvexyS3AS6rbXl+xdpYRMGSRBClPvyj44njOWoxjNdL/H9UNg==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -9905,9 +9861,9 @@ "license": "MIT" }, "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "license": "MIT", "optional": true, "dependencies": { @@ -9948,9 +9904,9 @@ } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -10186,9 +10142,9 @@ } }, "node_modules/rettime": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.7.0.tgz", - "integrity": "sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.10.1.tgz", + "integrity": "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==", "dev": true, "license": "MIT" }, @@ -10229,9 +10185,9 @@ } }, "node_modules/rollup": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz", - "integrity": "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", "dependencies": { @@ -10245,31 +10201,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.57.0", - "@rollup/rollup-android-arm64": "4.57.0", - "@rollup/rollup-darwin-arm64": "4.57.0", - "@rollup/rollup-darwin-x64": "4.57.0", - "@rollup/rollup-freebsd-arm64": "4.57.0", - "@rollup/rollup-freebsd-x64": "4.57.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.0", - "@rollup/rollup-linux-arm-musleabihf": "4.57.0", - "@rollup/rollup-linux-arm64-gnu": "4.57.0", - "@rollup/rollup-linux-arm64-musl": "4.57.0", - "@rollup/rollup-linux-loong64-gnu": "4.57.0", - "@rollup/rollup-linux-loong64-musl": "4.57.0", - "@rollup/rollup-linux-ppc64-gnu": "4.57.0", - "@rollup/rollup-linux-ppc64-musl": "4.57.0", - "@rollup/rollup-linux-riscv64-gnu": "4.57.0", - "@rollup/rollup-linux-riscv64-musl": "4.57.0", - "@rollup/rollup-linux-s390x-gnu": "4.57.0", - "@rollup/rollup-linux-x64-gnu": "4.57.0", - "@rollup/rollup-linux-x64-musl": "4.57.0", - "@rollup/rollup-openbsd-x64": "4.57.0", - "@rollup/rollup-openharmony-arm64": "4.57.0", - "@rollup/rollup-win32-arm64-msvc": "4.57.0", - "@rollup/rollup-win32-ia32-msvc": "4.57.0", - "@rollup/rollup-win32-x64-gnu": "4.57.0", - "@rollup/rollup-win32-x64-msvc": "4.57.0", + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" } }, @@ -10300,9 +10256,9 @@ } }, "node_modules/rrule-temporal": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.4.5.tgz", - "integrity": "sha512-g0qDEx7Wk1eaOKyZvBSTAz/DAfPnS+7GZT3vRShue6zIGCjkHWJs6evnGb7Nx2SVGKxOyMDUtKBBI53HMaFDKQ==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.4.6.tgz", + "integrity": "sha512-eRruK01K8uu0VWgn+lvKYXGZCER7eI2EaoAhsh5wwHaYMc4jPJ1cvY+bD0hBbYwCucggMpjtuwH2RpEH9oLfWg==", "license": "MIT", "dependencies": { "@js-temporal/polyfill": "^0.5.1" @@ -10400,9 +10356,9 @@ } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "devOptional": true, "license": "ISC", "bin": { @@ -10931,9 +10887,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, "license": "CC0-1.0" }, @@ -10994,14 +10950,14 @@ } }, "node_modules/string-width": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", - "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", + "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", "dev": true, "license": "MIT", "dependencies": { - "get-east-asian-width": "^1.3.0", - "strip-ansi": "^7.1.0" + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" }, "engines": { "node": ">=20" @@ -11011,13 +10967,13 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -11039,9 +10995,9 @@ } }, "node_modules/stylelint": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.1.0.tgz", - "integrity": "sha512-+cUX1FxkkbLX5qJRAPapUv/+v+YU3pGbWu+pHVqTXpiY0mYh3Dxfxa0bLBtVtYgOC8hIWIyX2H/3Y3LWlAevDg==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.4.0.tgz", + "integrity": "sha512-3kQ2/cHv3Zt8OBg+h2B8XCx9evEABQIrv4hh3uXahGz/ZEHrTR80zxBiK2NfXNaSoyBzxO1pjsz1Vhdzwn5XSw==", "dev": true, "funding": [ { @@ -11055,16 +11011,16 @@ ], "license": "MIT", "dependencies": { + "@csstools/css-calc": "^3.1.1", "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-syntax-patches-for-csstree": "^1.0.25", + "@csstools/css-syntax-patches-for-csstree": "^1.0.27", "@csstools/css-tokenizer": "^4.0.0", "@csstools/media-query-list-parser": "^5.0.0", "@csstools/selector-resolve-nested": "^4.0.0", "@csstools/selector-specificity": "^6.0.0", - "balanced-match": "^3.0.1", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.3", + "css-functions-list": "^3.3.3", "css-tree": "^3.1.0", "debug": "^4.4.3", "fast-glob": "^3.3.3", @@ -11078,7 +11034,6 @@ "import-meta-resolve": "^4.2.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.37.0", "mathml-tag-names": "^4.0.0", "meow": "^14.0.0", "micromatch": "^4.0.8", @@ -11088,7 +11043,7 @@ "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.1.1", "postcss-value-parser": "^4.2.0", - "string-width": "^8.1.0", + "string-width": "^8.1.1", "supports-hyperlinks": "^4.4.0", "svg-tags": "^1.0.0", "table": "^6.9.0", @@ -11167,83 +11122,6 @@ "stylelint": ">=16.0.0" } }, - "node_modules/stylelint/node_modules/@csstools/css-parser-algorithms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", - "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^4.0.0" - } - }, - "node_modules/stylelint/node_modules/@csstools/css-tokenizer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", - "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=20.19.0" - } - }, - "node_modules/stylelint/node_modules/@csstools/media-query-list-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-5.0.0.tgz", - "integrity": "sha512-T9lXmZOfnam3eMERPsszjY5NK0jX8RmThmmm99FZ8b7z8yMaFZWKwLWGZuTwdO3ddRY5fy13GmmEYZXB4I98Eg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0" - } - }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-3.0.1.tgz", - "integrity": "sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, "node_modules/stylelint/node_modules/file-entry-cache": { "version": "11.1.2", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.2.tgz", @@ -11266,27 +11144,6 @@ "hookified": "^1.15.0" } }, - "node_modules/stylelint/node_modules/globby": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-16.1.0.tgz", - "integrity": "sha512-+A4Hq7m7Ze592k9gZRy4gJ27DrXRNnC1vPjxTt1qQxEY8RxagBkBxivkCwg7FxSTG0iLLEMaUx13oOr0R2/qcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.5", - "is-path-inside": "^4.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.4.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/stylelint/node_modules/ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", @@ -11297,19 +11154,6 @@ "node": ">= 4" } }, - "node_modules/stylelint/node_modules/unicorn-magic": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", - "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -11409,9 +11253,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.30.7", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.30.7.tgz", - "integrity": "sha512-33B/cftpaWdpvH+Ho9U1b08ss8GQuLxrWHelbJT1yw4M48Taj8W3ezcPuaLoIHZz5V6tVHuQPr5BprEfnBLBMw==", + "version": "5.31.1", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.1.tgz", + "integrity": "sha512-6pRwxoGeV/roJYpsfcP6tN9mep6pPeCtXbUOCdVa0nme05Brwcwdge/fVNhIZn2wuUitAKZm4IYa7QjnRIa9zA==", "license": "MIT", "os": [ "darwin", @@ -11575,22 +11419,22 @@ } }, "node_modules/tldts": { - "version": "7.0.19", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", - "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz", + "integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.0.19" + "tldts-core": "^7.0.23" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.19", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz", - "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz", + "integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==", "dev": true, "license": "MIT" }, @@ -11728,9 +11572,9 @@ } }, "node_modules/type-fest": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.2.tgz", - "integrity": "sha512-FLEenlVYf7Zcd34ISMLo3ZzRE1gRjY1nMDTp+bQRBiPsaKyIW8K3Zr99ioHDUgA9OGuGGJPyYpNcffGmBhJfGg==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.4.tgz", + "integrity": "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==", "dev": true, "license": "(MIT OR CC0-1.0)", "dependencies": { @@ -11780,9 +11624,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.19.2.tgz", - "integrity": "sha512-4VQSpGEGsWzk0VYxyB/wVX/Q7qf9t5znLRgs0dzszr9w9Fej/8RVNQ+S20vdXSAyra/bJ7ZQfGv6ZMj7UEbzSg==", + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", + "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -11795,13 +11639,13 @@ "license": "MIT" }, "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", + "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12170,27 +12014,28 @@ } }, "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/whatwg-url": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", - "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", "dev": true, "license": "MIT", "dependencies": { + "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", - "webidl-conversions": "^8.0.0" + "webidl-conversions": "^8.0.1" }, "engines": { - "node": ">=20" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/which": { @@ -12297,13 +12142,12 @@ "license": "ISC" }, "node_modules/write-file-atomic": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.0.tgz", - "integrity": "sha512-YnlPC6JqnZl6aO4uRc+dx5PHguiR9S6WeoLtpxNT9wIG+BDya7ZNE1q7KOjVgaA73hKhKLpVPgJ5QA9THQ5BRg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", + "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", "dev": true, "license": "ISC", "dependencies": { - "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" }, "engines": { @@ -12311,17 +12155,16 @@ } }, "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", - "dev": true, + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=8.3.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/package.json b/package.json index 6e969dc425..89d9ae83bd 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,18 @@ } }, "main": "js/electron.js", + "exports": "./js/electron.js", + "files": [ + "clientonly", + "css", + "defaultmodules", + "js", + "serveronly", + "translations", + "favicon.svg", + "index.html" + ], + "sideEffects": true, "scripts": { "config:check": "node js/check_config.js", "postinstall": "git clean -df fonts vendor modules/default", @@ -75,14 +87,14 @@ "*.css": "stylelint --fix" }, "dependencies": { - "@fontsource/roboto": "^5.2.9", + "@fontsource/roboto": "^5.2.10", "@fontsource/roboto-condensed": "^5.2.8", - "@fortawesome/fontawesome-free": "^7.1.0", - "ajv": "^8.17.1", + "@fortawesome/fontawesome-free": "^7.2.0", + "ajv": "^8.18.0", "animate.css": "^4.1.1", "console-stamp": "^3.1.2", - "croner": "^9.1.0", - "eslint": "^9.39.2", + "croner": "^10.0.1", + "eslint": "^9.39.3", "express": "^5.2.1", "feedme": "^2.0.2", "helmet": "^8.1.0", @@ -96,36 +108,36 @@ "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.30.7", - "undici": "^7.19.2", + "systeminformation": "^5.31.1", + "undici": "^7.22.0", "weathericons": "^2.1.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^5.7.1", + "@stylistic/eslint-plugin": "^5.9.0", "@vitest/coverage-v8": "^4.0.18", - "@vitest/eslint-plugin": "^1.6.6", + "@vitest/eslint-plugin": "^1.6.9", "@vitest/ui": "^4.0.18", - "cspell": "^9.6.2", + "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-jsdoc": "^62.5.0", - "eslint-plugin-package-json": "^0.88.2", - "eslint-plugin-playwright": "^2.5.1", + "eslint-plugin-jsdoc": "^62.7.1", + "eslint-plugin-package-json": "^0.89.2", + "eslint-plugin-playwright": "^2.8.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", - "jsdom": "^27.4.0", - "lint-staged": "^16.2.7", - "markdownlint-cli2": "^0.20.0", - "msw": "^2.12.7", - "playwright": "^1.58.1", + "jsdom": "^28.1.0", + "lint-staged": "^16.3.0", + "markdownlint-cli2": "^0.21.0", + "msw": "^2.12.10", + "playwright": "^1.58.2", "prettier": "^3.8.1", "prettier-plugin-jinja-template": "^2.1.0", - "stylelint": "^17.1.0", + "stylelint": "^17.4.0", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", "vitest": "^4.0.18" }, "optionalDependencies": { - "electron": "^40.1.0" + "electron": "^40.6.1" }, "engines": { "node": ">=22.21.1 <23 || >=24" From 587bc2571ea08d1a4ccfe5d521e359e241c19bb6 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 1 Mar 2026 14:12:15 +0100 Subject: [PATCH 372/418] chore: remove obsolete Jest config and unit test global setup (#4044) The files were overlooked during the migration from jest to vitest (#3940). --- jest.config.js | 41 ------------------------------ tests/unit/helpers/global-setup.js | 3 --- 2 files changed, 44 deletions(-) delete mode 100644 jest.config.js delete mode 100644 tests/unit/helpers/global-setup.js diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index bb4942cf4b..0000000000 --- a/jest.config.js +++ /dev/null @@ -1,41 +0,0 @@ -const aliasMapper = { - logger: "/js/logger.js" -}; - -const config = { - verbose: true, - testTimeout: 20000, - testSequencer: "/tests/utils/test_sequencer.js", - projects: [ - { - displayName: "unit", - globalSetup: "/tests/unit/helpers/global-setup.js", - moduleNameMapper: aliasMapper, - testMatch: ["**/tests/unit/**/*.[jt]s?(x)"], - testPathIgnorePatterns: ["/tests/unit/mocks", "/tests/unit/helpers"] - }, - { - displayName: "electron", - testMatch: ["**/tests/electron/**/*.[jt]s?(x)"], - moduleNameMapper: aliasMapper, - testPathIgnorePatterns: ["/tests/electron/helpers"] - }, - { - displayName: "e2e", - testMatch: ["**/tests/e2e/**/*.[jt]s?(x)"], - modulePaths: ["/js/"], - moduleNameMapper: aliasMapper, - testPathIgnorePatterns: ["/tests/e2e/helpers", "/tests/e2e/mocks"] - } - ], - collectCoverageFrom: [ - "/clientonly/**/*.js", - "/js/**/*.js", - "/defaultmodules/**/*.js", - "/serveronly/**/*.js" - ], - coverageReporters: ["lcov", "text"], - coverageProvider: "v8" -}; - -module.exports = config; diff --git a/tests/unit/helpers/global-setup.js b/tests/unit/helpers/global-setup.js deleted file mode 100644 index d4a4977858..0000000000 --- a/tests/unit/helpers/global-setup.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = () => { - process.env.TZ = "UTC"; -}; From 06b136145794e51f3e36b537585d286acb099efa Mon Sep 17 00:00:00 2001 From: Veeck Date: Sun, 1 Mar 2026 15:28:06 +0100 Subject: [PATCH 373/418] Use getDateString in openmeteo (#4046) Fixes #4045 Otherwise the calculation comes to the result that its yesterday... --- defaultmodules/weather/providers/openmeteo.js | 4 +-- .../weather/providers/openmeteo_spec.js | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/defaultmodules/weather/providers/openmeteo.js b/defaultmodules/weather/providers/openmeteo.js index c6cff32a24..daad056e98 100644 --- a/defaultmodules/weather/providers/openmeteo.js +++ b/defaultmodules/weather/providers/openmeteo.js @@ -270,13 +270,13 @@ class OpenMeteoProvider { const endDate = new Date(startDate); endDate.setDate(endDate.getDate() + Math.max(0, Math.min(7, maxNumberOfDays))); - params.start_date = startDate.toISOString().split("T")[0]; + params.start_date = getDateString(startDate); switch (this.config.type) { case "hourly": case "daily": case "forecast": - params.end_date = endDate.toISOString().split("T")[0]; + params.end_date = getDateString(endDate); break; case "current": params.current_weather = true; diff --git a/tests/unit/modules/default/weather/providers/openmeteo_spec.js b/tests/unit/modules/default/weather/providers/openmeteo_spec.js index 7201c293ae..a46bba9aee 100644 --- a/tests/unit/modules/default/weather/providers/openmeteo_spec.js +++ b/tests/unit/modules/default/weather/providers/openmeteo_spec.js @@ -79,6 +79,34 @@ describe("OpenMeteoProvider", () => { await provider.initialize(); expect(provider.locationName).toBe("Munich, BY"); }); + + it("should build query dates from local date, not ISO UTC conversion", async () => { + const toISOStringSpy = vi.spyOn(Date.prototype, "toISOString").mockReturnValue("2000-01-01T00:00:00.000Z"); + try { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "current" + }); + + await provider.initialize(); + + const url = new URL(provider.fetcher.url); + const params = url.searchParams; + const now = new Date(); + const expectedToday = [ + now.getFullYear(), + String(now.getMonth() + 1).padStart(2, "0"), + String(now.getDate()).padStart(2, "0") + ].join("-"); + + expect(params.get("start_date")).toBe(expectedToday); + expect(params.get("end_date")).toBe(expectedToday); + expect(params.get("start_date")).not.toBe("2000-01-01"); + } finally { + toISOStringSpy.mockRestore(); + } + }); }); describe("Current Weather Parsing", () => { From ab3108fc14efd7f7fcc9a380ea2f6c9cc87f52c3 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 2 Mar 2026 21:31:32 +0100 Subject: [PATCH 374/418] [calendar] refactor: delegate event expansion to node-ical's expandRecurringEvent (#4047) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit node-ical 0.25.x added `expandRecurringEvent()` — a proper API for expanding both recurring and non-recurring events, including EXDATE filtering and RECURRENCE-ID overrides. This PR replaces our hand-rolled equivalent with it. `calendarfetcherutils.js` loses ~125 lines of code. What's left only deals with MagicMirror-specific concerns: timezone conversion, config-based filtering, and output formatting. The extra lines in the diff come from new tests. ## What was removed - `getMomentsFromRecurringEvent()` — manual rrule.js wrapping with custom date extraction - `isFullDayEvent()` — heuristic with multiple fallback checks - `isFacebookBirthday` workaround — patched years < 1900 and special-cased `@facebook.com` UIDs - The `if (event.rrule) / else` split — all events now go through a single code path ## Bugs fixed along the way Both were subtle enough to go unnoticed before: - **`[object Object]` in event titles/description/location** — node-ical represents ICS properties with parameters (e.g. `DESCRIPTION;LANGUAGE=de:Text`) as `{val, params}` objects. The old code passed them straight through. Mainly affected multilingual Exchange/O365 setups. Fixed with `unwrapParameterValue()`. - **`excludedEvents` with `until` never worked** — `shouldEventBeExcluded()` returned `{ excluded, until }` but the caller destructured it as `{ excluded, eventFilterUntil }`, so the until date was always `undefined` and events were never hidden. Fixed by correcting the destructuring key. The expansion loop also gets error isolation: a single broken event is logged and skipped instead of aborting the whole feed. ## Other clean-ups - Replaced `this.shouldEventBeExcluded` with `CalendarFetcherUtils.shouldEventBeExcluded` — avoids context-loss bugs when the method is destructured or called indirectly. - Replaced deprecated `substr()` with `slice()`. - Replaced `now < filterUntil` (operator overloading) with `now.isBefore(filterUntil)` — idiomatic Moment.js comparison. - Fixed `@returns` JSDoc: `string[]` → `object[]`. - Moved verbose `Log.debug("Processing entry...")` after the `VEVENT` type guard to reduce log noise from non-event entries. - Replaced `JSON.stringify(event)` debug log with a lightweight summary to avoid unnecessary serialization cost. - Added comment explaining the 0-duration → end-of-day fallback for events without DTEND. ## Tests 24 unit tests, all passing (`npx vitest run tests/unit/modules/default/calendar/`). New coverage: `excludedEvents` with/without `until`, Facebook birthday year expansion, output object shape, no-DTEND fallback, error isolation, `unwrapParameterValue`, `getTitleFromEvent`, ParameterValue properties, RECURRENCE-ID overrides, DURATION (single and recurring). --- .../calendar/calendarfetcherutils.js | 283 ++++-------- eslint.config.mjs | 3 +- package-lock.json | 27 +- package.json | 2 +- .../calendar/calendar_fetcher_utils_spec.js | 402 ++++++++++++++++-- vitest.config.mjs | 2 + 6 files changed, 476 insertions(+), 243 deletions(-) diff --git a/defaultmodules/calendar/calendarfetcherutils.js b/defaultmodules/calendar/calendarfetcherutils.js index e0971f5759..7234514d72 100644 --- a/defaultmodules/calendar/calendarfetcherutils.js +++ b/defaultmodules/calendar/calendarfetcherutils.js @@ -2,6 +2,7 @@ * @external Moment */ const moment = require("moment-timezone"); +const ical = require("node-ical"); const Log = require("logger"); @@ -40,58 +41,15 @@ const CalendarFetcherUtils = { return moment.tz.guess(); }, - /** - * This function returns a list of moments for a recurring event. - * @param {object} event the current event which is a recurring event - * @param {moment.Moment} pastLocalMoment The past date to search for recurring events - * @param {moment.Moment} futureLocalMoment The future date to search for recurring events - * @param {number} durationInMs the duration of the event, this is used to take into account currently running events - * @returns {moment.Moment[]} All moments for the recurring event - */ - getMomentsFromRecurringEvent (event, pastLocalMoment, futureLocalMoment, durationInMs) { - const rule = event.rrule; - const isFullDayEvent = CalendarFetcherUtils.isFullDayEvent(event); - const eventTimezone = event.start.tz || CalendarFetcherUtils.getLocalTimezone(); - - // rrule.js interprets years < 1900 as offsets from 1900, causing issues with some birthday calendars - if (rule.origOptions?.dtstart?.getFullYear() < 1900) { - rule.origOptions.dtstart.setFullYear(1900); - } - if (rule.options?.dtstart?.getFullYear() < 1900) { - rule.options.dtstart.setFullYear(1900); - } - - // Expand search window to include ongoing events - const oneDayInMs = 24 * 60 * 60 * 1000; - const searchFromDate = pastLocalMoment.clone().subtract(Math.max(durationInMs, oneDayInMs), "milliseconds").toDate(); - const searchToDate = futureLocalMoment.clone().add(1, "days").toDate(); - - const dates = rule.between(searchFromDate, searchToDate, true) || []; - - // Convert dates to moments in the event's timezone. - // Full-day events need UTC component extraction to avoid date shifts across timezone boundaries. - return dates.map((date) => { - if (isFullDayEvent) { - return moment.tz([date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()], eventTimezone); - } - return moment.tz(date, eventTimezone); - }); - }, - /** * Filter the events from ical according to the given config * @param {object} data the calendar data from ical * @param {object} config The configuration object - * @returns {string[]} the filtered events + * @returns {object[]} the filtered events */ filterEvents (data, config) { const newEvents = []; - const eventDate = function (event, time) { - const startMoment = event[time].tz ? moment.tz(event[time], event[time].tz) : moment.tz(event[time], CalendarFetcherUtils.getLocalTimezone()); - return CalendarFetcherUtils.isFullDayEvent(event) ? startMoment.startOf("day") : startMoment; - }; - Log.debug(`There are ${Object.entries(data).length} calendar entries.`); const now = moment(); @@ -105,102 +63,60 @@ const CalendarFetcherUtils = { .subtract(1, "seconds"); Object.entries(data).forEach(([key, event]) => { - Log.debug("Processing entry..."); + if (event.type !== "VEVENT") { + return; + } const title = CalendarFetcherUtils.getTitleFromEvent(event); Log.debug(`title: ${title}`); // Return quickly if event should be excluded. - let { excluded, eventFilterUntil } = this.shouldEventBeExcluded(config, title); + const { excluded, until: eventFilterUntil } = CalendarFetcherUtils.shouldEventBeExcluded(config, title); if (excluded) { return; } - // FIXME: Ugly fix to solve the facebook birthday issue. - // Otherwise, the recurring events only show the birthday for next year. - let isFacebookBirthday = false; - if (typeof event.uid !== "undefined") { - if (event.uid.indexOf("@facebook.com") !== -1) { - isFacebookBirthday = true; - } - } + Log.debug(`Event: ${title} | start: ${event.start} | end: ${event.end} | recurring: ${!!event.rrule}`); - if (event.type === "VEVENT") { - Log.debug(`Event:\n${JSON.stringify(event, null, 2)}`); - let eventStartMoment = eventDate(event, "start"); - let eventEndMoment; + const location = CalendarFetcherUtils.unwrapParameterValue(event.location) || false; + const geo = event.geo || false; + const description = CalendarFetcherUtils.unwrapParameterValue(event.description) || false; - if (typeof event.end !== "undefined") { - eventEndMoment = eventDate(event, "end"); - } else if (typeof event.duration !== "undefined") { - eventEndMoment = eventStartMoment.clone().add(moment.duration(event.duration)); - } else { - if (!isFacebookBirthday) { - // make copy of start date, separate storage area - eventEndMoment = eventStartMoment.clone(); - } else { - eventEndMoment = eventStartMoment.clone().add(1, "days"); - } - } - - Log.debug(`start: ${eventStartMoment.toDate()}`); - Log.debug(`end: ${eventEndMoment.toDate()}`); - - // Calculate the duration of the event for use with recurring events. - const durationMs = eventEndMoment.valueOf() - eventStartMoment.valueOf(); - Log.debug(`duration: ${durationMs}`); + let instances; + try { + instances = CalendarFetcherUtils.expandRecurringEvent(event, pastLocalMoment, futureLocalMoment); + } catch (error) { + Log.error(`Could not expand event "${title}": ${error.message}`); + return; + } - const location = event.location || false; - const geo = event.geo || false; - const description = event.description || false; + for (const instance of instances) { + const { event: instanceEvent, startMoment, endMoment, isRecurring, isFullDay } = instance; - let instances = []; - if (event.rrule && typeof event.rrule !== "undefined" && !isFacebookBirthday) { - instances = CalendarFetcherUtils.expandRecurringEvent(event, pastLocalMoment, futureLocalMoment, durationMs); - } else { - const fullDayEvent = isFacebookBirthday ? true : CalendarFetcherUtils.isFullDayEvent(event); - let end = eventEndMoment; - if (fullDayEvent && eventStartMoment.valueOf() === end.valueOf()) { - end = end.endOf("day"); - } - - instances.push({ - event: event, - startMoment: eventStartMoment, - endMoment: end, - isRecurring: false - }); + // Filter logic + if (endMoment.isBefore(pastLocalMoment) || startMoment.isAfter(futureLocalMoment)) { + continue; } - for (const instance of instances) { - const { event: instanceEvent, startMoment, endMoment, isRecurring } = instance; - - // Filter logic - if (endMoment.isBefore(pastLocalMoment) || startMoment.isAfter(futureLocalMoment)) { - continue; - } - - if (CalendarFetcherUtils.timeFilterApplies(now, endMoment, eventFilterUntil)) { - continue; - } - - const title = CalendarFetcherUtils.getTitleFromEvent(instanceEvent); - const fullDay = isFacebookBirthday ? true : CalendarFetcherUtils.isFullDayEvent(event); - - Log.debug(`saving event: ${title}`); - newEvents.push({ - title: title, - startDate: startMoment.format("x"), - endDate: endMoment.format("x"), - fullDayEvent: fullDay, - recurringEvent: isRecurring, - class: event.class, - firstYear: event.start.getFullYear(), - location: instanceEvent.location || location, - geo: instanceEvent.geo || geo, - description: instanceEvent.description || description - }); + if (CalendarFetcherUtils.timeFilterApplies(now, endMoment, eventFilterUntil)) { + continue; } + + const instanceTitle = CalendarFetcherUtils.getTitleFromEvent(instanceEvent); + + Log.debug(`saving event: ${instanceTitle}, start: ${startMoment.toDate()}, end: ${endMoment.toDate()}`); + newEvents.push({ + title: instanceTitle, + startDate: startMoment.format("x"), + endDate: endMoment.format("x"), + fullDayEvent: isFullDay, + recurringEvent: isRecurring, + class: event.class, + firstYear: event.start.getFullYear(), + location: CalendarFetcherUtils.unwrapParameterValue(instanceEvent.location) || location, + geo: instanceEvent.geo || geo, + description: CalendarFetcherUtils.unwrapParameterValue(instanceEvent.description) || description + }); } }); @@ -217,35 +133,21 @@ const CalendarFetcherUtils = { * @returns {string} The title of the event, or "Event" if no title is found. */ getTitleFromEvent (event) { - let title = "Event"; - if (event.summary) { - title = typeof event.summary.val !== "undefined" ? event.summary.val : event.summary; - } else if (event.description) { - title = event.description; - } - - return title; + return CalendarFetcherUtils.unwrapParameterValue(event.summary || event.description) || "Event"; }, /** - * Checks if an event is a fullday event. - * @param {object} event The event object to check. - * @returns {boolean} True if the event is a fullday event, false otherwise + * Extracts the string value from a node-ical ParameterValue object ({val, params}) + * or returns the value as-is if it is already a plain string. + * This handles ICS properties with parameters, e.g. DESCRIPTION;LANGUAGE=de:Text. + * @param {string|object} value The raw value from node-ical + * @returns {string|object} The unwrapped string value, or the original value if not a ParameterValue */ - isFullDayEvent (event) { - if (event.start.length === 8 || event.start.dateOnly || event.datetype === "date") { - return true; - } - - const start = event.start || 0; - const startDate = new Date(start); - const end = event.end || 0; - if ((end - start) % (24 * 60 * 60 * 1000) === 0 && startDate.getHours() === 0 && startDate.getMinutes() === 0) { - // Is 24 hours, and starts on the middle of the night. - return true; + unwrapParameterValue (value) { + if (value && typeof value === "object" && typeof value.val !== "undefined") { + return value.val; } - - return false; + return value; }, /** @@ -262,7 +164,7 @@ const CalendarFetcherUtils = { increment = until[1].slice(-1) === "s" ? until[1] : `${until[1]}s`, // Massage the data for moment js filterUntil = moment(endDate.format()).subtract(value, increment); - return now < filterUntil; + return now.isBefore(filterUntil); } return false; @@ -282,7 +184,7 @@ const CalendarFetcherUtils = { // Assume if leading slash, there is also trailing slash if (filter[0] === "/") { // Strip leading and trailing slashes - regexFilter = filter.substr(1).slice(0, -1); + regexFilter = filter.slice(1, -1); } return new RegExp(regexFilter, regexFlags).test(title); } else { @@ -291,65 +193,38 @@ const CalendarFetcherUtils = { }, /** - * Expands a recurring event into individual event instances. + * Expands a recurring event into individual event instances using node-ical. + * Handles RRULE expansion, EXDATE filtering, RECURRENCE-ID overrides, and ongoing events. * @param {object} event The recurring event object * @param {moment.Moment} pastLocalMoment The past date limit * @param {moment.Moment} futureLocalMoment The future date limit - * @param {number} durationMs The duration of the event in milliseconds - * @returns {object[]} Array of event instances + * @returns {object[]} Array of event instances with startMoment/endMoment in the local timezone */ - expandRecurringEvent (event, pastLocalMoment, futureLocalMoment, durationMs) { - const moments = CalendarFetcherUtils.getMomentsFromRecurringEvent(event, pastLocalMoment, futureLocalMoment, durationMs); - const instances = []; - - for (const startMoment of moments) { - let curEvent = event; - let showRecurrence = true; - let recurringEventStartMoment = startMoment.clone().tz(CalendarFetcherUtils.getLocalTimezone()); - let recurringEventEndMoment = recurringEventStartMoment.clone().add(durationMs, "ms"); - - // For full-day events, use local date components to match node-ical's getDateKey behavior - // For timed events, use UTC to match ISO string slice - const isFullDay = CalendarFetcherUtils.isFullDayEvent(event); - const dateKey = isFullDay - ? recurringEventStartMoment.format("YYYY-MM-DD") - : recurringEventStartMoment.tz("UTC").format("YYYY-MM-DD"); - - // Check for overrides - if (curEvent.recurrences !== undefined) { - if (curEvent.recurrences[dateKey] !== undefined) { - curEvent = curEvent.recurrences[dateKey]; - // Re-calculate start/end based on override - const start = curEvent.start; - const end = curEvent.end; - const localTimezone = CalendarFetcherUtils.getLocalTimezone(); - - recurringEventStartMoment = (start.tz ? moment(start).tz(start.tz) : moment(start)).tz(localTimezone); - recurringEventEndMoment = (end.tz ? moment(end).tz(end.tz) : moment(end)).tz(localTimezone); - } - } - - // Check for exceptions - if (curEvent.exdate !== undefined) { - if (curEvent.exdate[dateKey] !== undefined) { - showRecurrence = false; + expandRecurringEvent (event, pastLocalMoment, futureLocalMoment) { + const localTimezone = CalendarFetcherUtils.getLocalTimezone(); + + return ical + .expandRecurringEvent(event, { + from: pastLocalMoment.toDate(), + to: futureLocalMoment.toDate(), + includeOverrides: true, + excludeExdates: true, + expandOngoing: true + }) + .map((inst) => { + let startMoment, endMoment; + if (inst.isFullDay) { + startMoment = moment.tz([inst.start.getFullYear(), inst.start.getMonth(), inst.start.getDate()], localTimezone); + endMoment = moment.tz([inst.end.getFullYear(), inst.end.getMonth(), inst.end.getDate()], localTimezone); + } else { + startMoment = moment(inst.start).tz(localTimezone); + endMoment = moment(inst.end).tz(localTimezone); } - } - - if (recurringEventStartMoment.valueOf() === recurringEventEndMoment.valueOf()) { - recurringEventEndMoment = recurringEventEndMoment.endOf("day"); - } - - if (showRecurrence) { - instances.push({ - event: curEvent, - startMoment: recurringEventStartMoment, - endMoment: recurringEventEndMoment, - isRecurring: true - }); - } - } - return instances; + // Events without DTEND (e.g. reminders) get start === end from node-ical; + // extend to end-of-day so they remain visible on the calendar. + if (startMoment.valueOf() === endMoment.valueOf()) endMoment = endMoment.endOf("day"); + return { event: inst.event, startMoment, endMoment, isRecurring: inst.isRecurring, isFullDay: inst.isFullDay }; + }); }, /** diff --git a/eslint.config.mjs b/eslint.config.mjs index 8e1ed23c8a..b8f07d7941 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -144,7 +144,8 @@ export default defineConfig([ ], "vitest/max-nested-describe": ["error", { max: 3 }], "vitest/prefer-to-be": "error", - "vitest/prefer-to-have-length": "error" + "vitest/prefer-to-have-length": "error", + "max-lines-per-function": "off" } }, { diff --git a/package-lock.json b/package-lock.json index 84eff058f5..fd92837595 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "ipaddr.js": "^2.3.0", "moment": "^2.30.1", "moment-timezone": "^0.6.0", - "node-ical": "^0.24.1", + "node-ical": "^0.25.4", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", @@ -8964,13 +8964,13 @@ } }, "node_modules/node-ical": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.24.2.tgz", - "integrity": "sha512-2wJJZE/X3KKLTBtRHqgzJQkMVpTtvFrdQU2Kq02mCNI4QWshqKSuLRXZl5dPy1gF+7XzpFNxKtxHIwLL2q1BqQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.25.4.tgz", + "integrity": "sha512-nuKpkcy0f8Qh/H1arBjy8X+iQmpb0gvIlKSFOCsPOkCRDCGnEjsr0aPCHAAUckNTv4yoJmCf4ia9jbookZEHSg==", "license": "Apache-2.0", "dependencies": { - "@js-temporal/polyfill": "^0.5.1", - "rrule-temporal": "^1.4.5" + "rrule-temporal": "^1.4.6", + "temporal-polyfill": "^0.3.0" }, "engines": { "node": ">=18" @@ -11374,6 +11374,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/temporal-polyfill": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.3.0.tgz", + "integrity": "sha512-qNsTkX9K8hi+FHDfHmf22e/OGuXmfBm9RqNismxBrnSmZVJKegQ+HYYXT+R7Ha8F/YSm2Y34vmzD4cxMu2u95g==", + "license": "MIT", + "dependencies": { + "temporal-spec": "0.3.0" + } + }, + "node_modules/temporal-spec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.3.0.tgz", + "integrity": "sha512-n+noVpIqz4hYgFSMOSiINNOUOMFtV5cZQNCmmszA6GiVFVRt3G7AqVyhXjhCSmowvQn+NsGn+jMDMKJYHd3bSQ==", + "license": "ISC" + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", diff --git a/package.json b/package.json index 89d9ae83bd..8bc5c4b30b 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "ipaddr.js": "^2.3.0", "moment": "^2.30.1", "moment-timezone": "^0.6.0", - "node-ical": "^0.24.1", + "node-ical": "^0.25.4", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", diff --git a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js index 31a179a520..20c40efce9 100644 --- a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js +++ b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js @@ -39,12 +39,19 @@ describe("Calendar fetcher utils test", () => { const yesterday = moment().subtract(1, "days").startOf("day").toDate(); const today = moment().startOf("day").toDate(); const tomorrow = moment().add(1, "days").startOf("day").toDate(); + const dayAfterTomorrow = moment().add(2, "days").startOf("day").toDate(); + // Mark as DATE-only (full-day) events per ICS convention + yesterday.dateOnly = true; + today.dateOnly = true; + tomorrow.dateOnly = true; + dayAfterTomorrow.dateOnly = true; + // ICS convention: DTEND for a full-day event is the exclusive next day const filteredEvents = CalendarFetcherUtils.filterEvents( { - pastEvent: { type: "VEVENT", start: yesterday, end: yesterday, summary: "pastEvent" }, - ongoingEvent: { type: "VEVENT", start: today, end: today, summary: "ongoingEvent" }, - upcomingEvent: { type: "VEVENT", start: tomorrow, end: tomorrow, summary: "upcomingEvent" } + pastEvent: { type: "VEVENT", start: yesterday, end: today, summary: "pastEvent" }, + ongoingEvent: { type: "VEVENT", start: today, end: tomorrow, summary: "ongoingEvent" }, + upcomingEvent: { type: "VEVENT", start: tomorrow, end: dayAfterTomorrow, summary: "upcomingEvent" } }, defaultConfig ); @@ -54,6 +61,58 @@ describe("Calendar fetcher utils test", () => { expect(filteredEvents[1].title).toBe("upcomingEvent"); }); + it("should hide excluded event with 'until' when far away and show it when close", () => { + // An event ending in 10 days with until='3 days' should be hidden now + const farStart = moment().add(9, "days").toDate(); + const farEnd = moment().add(10, "days").toDate(); + // An event ending in 1 day with until='3 days' should be shown (within 3 days of end) + const closeStart = moment().add(1, "hours").toDate(); + const closeEnd = moment().add(1, "days").toDate(); + + const config = { + ...defaultConfig, + excludedEvents: [{ filterBy: "Payment", until: "3 days" }] + }; + + const filteredEvents = CalendarFetcherUtils.filterEvents( + { + farPayment: { type: "VEVENT", start: farStart, end: farEnd, summary: "Payment due" }, + closePayment: { type: "VEVENT", start: closeStart, end: closeEnd, summary: "Payment reminder" }, + normalEvent: { type: "VEVENT", start: closeStart, end: closeEnd, summary: "Normal event" } + }, + config + ); + + // farPayment should be hidden (now < endDate - 3 days) + // closePayment should show (now >= endDate - 3 days) + // normalEvent should show (not matched by filter) + const titles = filteredEvents.map((e) => e.title); + expect(titles).not.toContain("Payment due"); + expect(titles).toContain("Payment reminder"); + expect(titles).toContain("Normal event"); + }); + + it("should fully exclude event when excludedEvents has no 'until'", () => { + const start = moment().add(1, "hours").toDate(); + const end = moment().add(2, "hours").toDate(); + + const config = { + ...defaultConfig, + excludedEvents: ["Hidden"] + }; + + const filteredEvents = CalendarFetcherUtils.filterEvents( + { + hidden: { type: "VEVENT", start, end, summary: "Hidden event" }, + visible: { type: "VEVENT", start, end, summary: "Visible event" } + }, + config + ); + + expect(filteredEvents).toHaveLength(1); + expect(filteredEvents[0].title).toBe("Visible event"); + }); + it("should return the correct times when recurring events pass through daylight saving time", () => { const data = ical.parseICS(`BEGIN:VEVENT DTSTART;TZID=Europe/Amsterdam:20250311T090000 @@ -94,24 +153,18 @@ DTSTART;TZID=Europe/Amsterdam:20250311T090000 DTEND;TZID=Europe/Amsterdam:20250311T091500 RRULE:FREQ=WEEKLY;BYDAY=FR,MO,TH,TU,WE,SA,SU DTSTAMP:20250531T091103Z -ORGANIZER;CN=test:mailto:test@test.com UID:67e65a1d-b889-4451-8cab-5518cecb9c66 -CREATED:20230111T114612Z -DESCRIPTION:Test -LAST-MODIFIED:20250528T071312Z -SEQUENCE:1 -STATUS:CONFIRMED SUMMARY:Test -TRANSP:OPAQUE END:VEVENT`); - const moments = CalendarFetcherUtils.getMomentsFromRecurringEvent(data["67e65a1d-b889-4451-8cab-5518cecb9c66"], moment(), moment().add(365, "days")); + const instances = CalendarFetcherUtils.expandRecurringEvent(data["67e65a1d-b889-4451-8cab-5518cecb9c66"], moment(), moment().add(365, "days")); - const januaryFirst = moments.filter((m) => m.format("MM-DD") === "01-01"); - const julyFirst = moments.filter((m) => m.format("MM-DD") === "07-01"); + const januaryFirst = instances.filter((i) => i.startMoment.format("MM-DD") === "01-01"); + const julyFirst = instances.filter((i) => i.startMoment.format("MM-DD") === "07-01"); - expect(januaryFirst[0].toISOString(true)).toContain("09:00:00.000+01:00"); - expect(julyFirst[0].toISOString(true)).toContain("09:00:00.000+02:00"); + // The underlying timestamps must represent 09:00 Amsterdam time, regardless of local timezone + expect(januaryFirst[0].startMoment.clone().tz("Europe/Amsterdam").toISOString(true)).toContain("09:00:00.000+01:00"); + expect(julyFirst[0].startMoment.clone().tz("Europe/Amsterdam").toISOString(true)).toContain("09:00:00.000+02:00"); }); it("should return correct day-of-week for full-day recurring events across DST transitions", () => { @@ -128,32 +181,319 @@ SUMMARY:Weekly Monday Event END:VEVENT END:VCALENDAR`); - const event = data["dst-test@google.com"]; - // Simulate calendar with timezone (e.g., from X-WR-TIMEZONE or user config) // This is how MagicMirror handles full-day events from calendars with timezones - event.start.tz = "America/Chicago"; + data["dst-test@google.com"].start.tz = "America/Chicago"; const pastMoment = moment("2025-10-01"); const futureMoment = moment("2025-11-30"); - - // Get moments for the recurring event - const moments = CalendarFetcherUtils.getMomentsFromRecurringEvent(event, pastMoment, futureMoment, 0); + const instances = CalendarFetcherUtils.expandRecurringEvent(data["dst-test@google.com"], pastMoment, futureMoment); + const startMoments = instances.map((i) => i.startMoment); // All occurrences should be on Monday (day() === 1) at midnight // Oct 27, 2025 - Before DST ends // Nov 3, 2025 - After DST ends (this was showing as Sunday before the fix) // Nov 10, 2025 - After DST ends - expect(moments).toHaveLength(3); - expect(moments[0].day()).toBe(1); // Monday - expect(moments[0].format("YYYY-MM-DD")).toBe("2025-10-27"); - expect(moments[0].hour()).toBe(0); // Midnight - expect(moments[1].day()).toBe(1); // Monday (not Sunday!) - expect(moments[1].format("YYYY-MM-DD")).toBe("2025-11-03"); - expect(moments[1].hour()).toBe(0); // Midnight - expect(moments[2].day()).toBe(1); // Monday - expect(moments[2].format("YYYY-MM-DD")).toBe("2025-11-10"); - expect(moments[2].hour()).toBe(0); // Midnight + expect(startMoments).toHaveLength(3); + expect(startMoments[0].day()).toBe(1); // Monday + expect(startMoments[0].format("YYYY-MM-DD")).toBe("2025-10-27"); + expect(startMoments[0].hour()).toBe(0); // Midnight + expect(startMoments[1].day()).toBe(1); // Monday (not Sunday!) + expect(startMoments[1].format("YYYY-MM-DD")).toBe("2025-11-03"); + expect(startMoments[1].hour()).toBe(0); // Midnight + expect(startMoments[2].day()).toBe(1); // Monday + expect(startMoments[2].format("YYYY-MM-DD")).toBe("2025-11-10"); + expect(startMoments[2].hour()).toBe(0); // Midnight + }); + + it("should show Facebook birthday events in the current year, not in the birth year", () => { + // Facebook birthday calendars use DTSTART with the actual birth year (e.g. 1990), + // which previously caused rrule.js to return the wrong year occurrence. + // With rrule-temporal this works correctly without any special-casing. + const data = ical.parseICS(`BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;VALUE=DATE:19900215 +RRULE:FREQ=YEARLY +DTSTAMP:20260101T000000Z +UID:birthday_123456789@facebook.com +SUMMARY:Jane Doe's Birthday +END:VEVENT +END:VCALENDAR`); + + const thisYear = moment().year(); + + const filteredEvents = CalendarFetcherUtils.filterEvents(data, { + ...defaultConfig, + maximumNumberOfDays: 366 + }); + + const birthdayEvents = filteredEvents.filter((e) => e.title === "Jane Doe's Birthday"); + expect(birthdayEvents.length).toBeGreaterThanOrEqual(1); + + // The event must expand to a recent year — NOT to the birth year 1990. + // It should be the current or next year depending on whether Feb 15 has already passed. + const startYear = moment(birthdayEvents[0].startDate, "x").year(); + expect(startYear).toBeGreaterThanOrEqual(thisYear); + expect(startYear).toBeLessThanOrEqual(thisYear + 1); + }); + + it("should produce a correctly shaped event object with all required fields", () => { + const start = moment("2026-03-10T14:00:00").toDate(); + const end = moment("2026-03-10T15:00:00").toDate(); + + const filteredEvents = CalendarFetcherUtils.filterEvents( + { + event1: { + type: "VEVENT", + start, + end, + summary: "Team Meeting", + description: "Agenda TBD", + location: "Room 42", + geo: { lat: 52.52, lon: 13.4 }, + class: "PUBLIC", + uid: "shaped-event@test" + } + }, + defaultConfig + ); + + expect(filteredEvents).toHaveLength(1); + const ev = filteredEvents[0]; + expect(ev.title).toBe("Team Meeting"); + expect(ev.startDate).toBe(moment(start).format("x")); + expect(ev.endDate).toBe(moment(end).format("x")); + expect(ev.fullDayEvent).toBe(false); + expect(ev.recurringEvent).toBe(false); + expect(ev.class).toBe("PUBLIC"); + expect(ev.firstYear).toBe(2026); + expect(ev.location).toBe("Room 42"); + expect(ev.geo).toEqual({ lat: 52.52, lon: 13.4 }); + expect(ev.description).toBe("Agenda TBD"); + }); + + it("should return correct firstYear for a full-day event on January 1st", () => { + // node-ical creates DATE-only events with the local Date constructor: new Date(year, month, day). + // getFullYear() on a locally-constructed date always returns the correct calendar year + // regardless of the server's UTC offset — guard against regressions that switch to getUTCFullYear(). + const data = ical.parseICS(`BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;VALUE=DATE:19900101 +DTEND;VALUE=DATE:19900102 +RRULE:FREQ=YEARLY +UID:newyear-birthday@test +SUMMARY:New Year Baby +END:VEVENT +END:VCALENDAR`); + + const filteredEvents = CalendarFetcherUtils.filterEvents(data, { + ...defaultConfig, + maximumNumberOfDays: 366 + }); + + const birthday = filteredEvents.find((e) => e.title === "New Year Baby"); + expect(birthday).toBeDefined(); + expect(birthday.firstYear).toBe(1990); + }); + }); + + describe("expandRecurringEvent", () => { + it("should extend end to end-of-day when event has no DTEND", () => { + // node-ical sets end === start when DTEND is absent; our code extends to endOf("day") + const data = ical.parseICS(`BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART:20260222T100000Z +UID:no-end-test@test +SUMMARY:No End Event +END:VEVENT +END:VCALENDAR`); + + const instances = CalendarFetcherUtils.expandRecurringEvent(data["no-end-test@test"], moment("2026-02-20"), moment("2026-02-24")); + + expect(instances).toHaveLength(1); + expect(instances[0].endMoment.format("HH:mm:ss")).toBe("23:59:59"); + }); + + it("should apply RECURRENCE-ID overrides (moved single occurrence)", () => { + // A weekly event on Mondays at 10:00, but the second occurrence is moved to Tuesday 14:00 + const data = ical.parseICS(`BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20260302T100000 +DTEND;TZID=Europe/Berlin:20260302T110000 +RRULE:FREQ=WEEKLY;COUNT=3 +UID:recurrence-override@test +SUMMARY:Weekly Standup +END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20260310T140000 +DTEND;TZID=Europe/Berlin:20260310T150000 +RECURRENCE-ID;TZID=Europe/Berlin:20260309T100000 +UID:recurrence-override@test +SUMMARY:Moved Standup +END:VEVENT +END:VCALENDAR`); + + const instances = CalendarFetcherUtils.expandRecurringEvent( + data["recurrence-override@test"], + moment("2026-03-01"), + moment("2026-03-31") + ); + + expect(instances).toHaveLength(3); + + // First occurrence: Monday March 2, 10:00 (unchanged) + expect(instances[0].startMoment.clone().tz("Europe/Berlin").format("YYYY-MM-DD HH:mm")).toBe("2026-03-02 10:00"); + expect(CalendarFetcherUtils.getTitleFromEvent(instances[0].event)).toBe("Weekly Standup"); + + // Second occurrence: moved to Tuesday March 10, 14:00 + expect(instances[1].startMoment.clone().tz("Europe/Berlin").format("YYYY-MM-DD HH:mm")).toBe("2026-03-10 14:00"); + expect(CalendarFetcherUtils.getTitleFromEvent(instances[1].event)).toBe("Moved Standup"); + + // Third occurrence: Monday March 16, 10:00 (unchanged) + expect(instances[2].startMoment.clone().tz("Europe/Berlin").format("YYYY-MM-DD HH:mm")).toBe("2026-03-16 10:00"); + }); + + it("should handle events with DURATION instead of DTEND", () => { + // RFC 5545 allows DURATION as alternative to DTEND + const data = ical.parseICS(`BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART:20260315T090000Z +DURATION:PT1H30M +UID:duration-test@test +SUMMARY:Duration Event +END:VEVENT +END:VCALENDAR`); + + const instances = CalendarFetcherUtils.expandRecurringEvent( + data["duration-test@test"], + moment("2026-03-14"), + moment("2026-03-16") + ); + + expect(instances).toHaveLength(1); + // End should be 90 minutes after start + const durationMinutes = instances[0].endMoment.diff(instances[0].startMoment, "minutes"); + expect(durationMinutes).toBe(90); + }); + + it("should handle recurring events with DURATION instead of DTEND", () => { + const data = ical.parseICS(`BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20260301T080000 +DURATION:PT45M +RRULE:FREQ=DAILY;COUNT=3 +UID:recurring-duration@test +SUMMARY:Daily Scrum +END:VEVENT +END:VCALENDAR`); + + const instances = CalendarFetcherUtils.expandRecurringEvent( + data["recurring-duration@test"], + moment("2026-02-28"), + moment("2026-03-05") + ); + + expect(instances).toHaveLength(3); + for (const inst of instances) { + const durationMinutes = inst.endMoment.diff(inst.startMoment, "minutes"); + expect(durationMinutes).toBe(45); + } + expect(instances[0].startMoment.clone().tz("Europe/Berlin").format("YYYY-MM-DD")).toBe("2026-03-01"); + expect(instances[1].startMoment.clone().tz("Europe/Berlin").format("YYYY-MM-DD")).toBe("2026-03-02"); + expect(instances[2].startMoment.clone().tz("Europe/Berlin").format("YYYY-MM-DD")).toBe("2026-03-03"); + }); + }); + + describe("filterEvents error handling", () => { + it("should skip a broken event but still return other valid events", () => { + const start = moment().add(1, "hours").toDate(); + const end = moment().add(2, "hours").toDate(); + + vi.spyOn(ical, "expandRecurringEvent").mockImplementationOnce(() => { + throw new TypeError("invalid rrule"); + }); + + const result = CalendarFetcherUtils.filterEvents( + { + brokenEvent: { type: "VEVENT", start, end, summary: "Broken" }, + goodEvent: { type: "VEVENT", start, end, summary: "Good" } + }, + defaultConfig + ); + + expect(result).toHaveLength(1); + expect(result[0].title).toBe("Good"); + }); + + it("should let expandRecurringEvent throw through directly", () => { + vi.spyOn(ical, "expandRecurringEvent").mockImplementationOnce(() => { + throw new TypeError("invalid rrule"); + }); + + const event = { type: "VEVENT", start: new Date(), end: new Date(), summary: "Broken Event" }; + expect(() => CalendarFetcherUtils.expandRecurringEvent(event, moment(), moment().add(1, "days"))).toThrow("invalid rrule"); + }); + }); + + describe("unwrapParameterValue", () => { + it("should return the val of a ParameterValue object", () => { + expect(CalendarFetcherUtils.unwrapParameterValue({ val: "Text", params: { LANGUAGE: "de" } })).toBe("Text"); + }); + + it("should return a plain string unchanged", () => { + expect(CalendarFetcherUtils.unwrapParameterValue("plain")).toBe("plain"); + }); + + it("should return falsy values unchanged", () => { + expect(CalendarFetcherUtils.unwrapParameterValue(undefined)).toBeUndefined(); + expect(CalendarFetcherUtils.unwrapParameterValue(false)).toBe(false); + }); + }); + + describe("getTitleFromEvent", () => { + it("should return summary string directly", () => { + expect(CalendarFetcherUtils.getTitleFromEvent({ summary: "My Event" })).toBe("My Event"); + }); + + it("should unwrap ParameterValue summary", () => { + expect(CalendarFetcherUtils.getTitleFromEvent({ summary: { val: "My Event", params: {} } })).toBe("My Event"); + }); + + it("should fall back to description string", () => { + expect(CalendarFetcherUtils.getTitleFromEvent({ description: "Desc" })).toBe("Desc"); + }); + + it("should unwrap ParameterValue description as fallback title", () => { + expect(CalendarFetcherUtils.getTitleFromEvent({ description: { val: "Desc", params: { LANGUAGE: "de" } } })).toBe("Desc"); + }); + + it("should return 'Event' when neither summary nor description is present", () => { + expect(CalendarFetcherUtils.getTitleFromEvent({})).toBe("Event"); + }); + }); + + describe("filterEvents with ParameterValue properties", () => { + it("should handle DESCRIPTION;LANGUAGE=de and LOCATION;LANGUAGE=de without [object Object]", () => { + const start = moment().add(1, "hours").toDate(); + const end = moment().add(2, "hours").toDate(); + + const filteredEvents = CalendarFetcherUtils.filterEvents( + { + event1: { + type: "VEVENT", + start, + end, + summary: "Test", + description: { val: "Beschreibung", params: { LANGUAGE: "de" } }, + location: { val: "Berlin", params: { LANGUAGE: "de" } } + } + }, + defaultConfig + ); + + expect(filteredEvents).toHaveLength(1); + expect(filteredEvents[0].description).toBe("Beschreibung"); + expect(filteredEvents[0].location).toBe("Berlin"); }); }); }); diff --git a/vitest.config.mjs b/vitest.config.mjs index 75808c82fc..0829d89278 100644 --- a/vitest.config.mjs +++ b/vitest.config.mjs @@ -21,6 +21,8 @@ export default defineConfig({ setupFiles: ["./tests/utils/vitest-setup.js"], // Stop test execution on first failure bail: 3, + // Automatically restore all mocks after each test to prevent leaks + restoreAllMocks: true, // Shared exclude patterns exclude: [ From 3eb3745dd3ccdcf86fe1ff01efd2e8919506add7 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:10:59 +0100 Subject: [PATCH 375/418] Fix Node.js v25 logging prefix and modernize logger (#4049) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Node.js v25, the log prefix in the terminal stopped working - instead of seeing something like: ``` [2026-03-05 23:00:00.000] [LOG] [app] Starting MagicMirror: v2.35.0 ``` the output was: ``` [2026-03-05 23:00:00.000] :pre() Starting MagicMirror: v2.35.0 ``` Reported in #4048. ## Why did it break? The logger used the `console-stamp` package to format log output. One part of that formatting used `styleText("grey", ...)` to color the caller prefix gray. Node.js v25 dropped `"grey"` as a valid color name (only `"gray"` with an "a" is accepted now). This caused `styleText` to throw an error internally - and `console-stamp` silently swallowed that error and fell back to returning its raw `:pre()` format string as the prefix. Not ideal. ## What's in this PR? **1. The actual fix** - `"grey"` → `"gray"`. **2. Cleaner stack trace approach** - the previous code set `Error.prepareStackTrace` *after* creating the `Error`, which is fragile and was starting to behave differently across Node versions. Replaced with straightforward string parsing of `new Error().stack`. **3. Removed the `console-stamp` dependency** - all formatting is now done with plain Node.js built-ins (`node:util` `styleText`). Same visual result, no external dependency. **4. Simplified the module wrapper** - the logger was wrapped in a UMD pattern, which is meant for environments like AMD/RequireJS. MagicMirror only runs in two places: Node.js and the browser. Replaced with a simple check (`typeof module !== "undefined"`), which is much easier to follow. --- js/logger.js | 222 +++++++++++++++++++++------------------------- package-lock.json | 55 ++++++------ package.json | 1 - 3 files changed, 128 insertions(+), 150 deletions(-) diff --git a/js/logger.js b/js/logger.js index a31b22a0ad..ccd74dbb99 100644 --- a/js/logger.js +++ b/js/logger.js @@ -1,131 +1,115 @@ -// This logger is very simple, but needs to be extended. -(function (root, factory) { - if (typeof exports === "object") { +// Logger for MagicMirror² — works both in Node.js (CommonJS) and the browser (global). +(function () { + if (typeof module !== "undefined") { if (process.env.mmTestMode !== "true") { const { styleText } = require("node:util"); - // add timestamps in front of log messages - require("console-stamp")(console, { - format: ":date(yyyy-mm-dd HH:MM:ss.l) :label(7) :pre() :msg", - tokens: { - pre: () => { - const err = new Error(); - Error.prepareStackTrace = (_, stack) => stack; - const stack = err.stack; - Error.prepareStackTrace = undefined; - try { - for (const line of stack) { - const file = line.getFileName(); - if (file && !file.includes("node:") && !file.includes("js/logger.js") && !file.includes("node_modules")) { - const filename = file.replace(/.*\/(.*).js/, "$1"); - const filepath = file.replace(/.*\/(.*)\/.*.js/, "$1"); - if (filepath === "js") { - return styleText("grey", `[${filename}]`); - } else { - return styleText("grey", `[${filepath}]`); - } - } - } - } catch (err) { - return styleText("grey", "[unknown]"); - } - }, - label: (arg) => { - const { method, defaultTokens } = arg; - let label = defaultTokens.label(arg); - switch (method) { - case "error": - label = styleText("red", label); - break; - case "warn": - label = styleText("yellow", label); - break; - case "debug": - label = styleText("bgBlue", label); - break; - case "info": - label = styleText("blue", label); - break; - } - return label; - }, - msg: (arg) => { - const { method, defaultTokens } = arg; - let msg = defaultTokens.msg(arg); - switch (method) { - case "error": - msg = styleText("red", msg); - break; - case "warn": - msg = styleText("yellow", msg); - break; - case "info": - msg = styleText("blue", msg); - break; + const LABEL_COLORS = { error: "red", warn: "yellow", debug: "bgBlue", info: "blue" }; + const MSG_COLORS = { error: "red", warn: "yellow", info: "blue" }; + + const formatTimestamp = () => { + const d = new Date(); + const pad2 = (n) => String(n).padStart(2, "0"); + const pad3 = (n) => String(n).padStart(3, "0"); + const date = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`; + const time = `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}.${pad3(d.getMilliseconds())}`; + return `[${date} ${time}]`; + }; + + const getCallerPrefix = () => { + try { + const lines = new Error().stack.split("\n"); + for (const line of lines) { + if (line.includes("node:") || line.includes("js/logger.js") || line.includes("node_modules")) continue; + const match = line.match(/\((.+?\.js):\d+:\d+\)/) || line.match(/at\s+(.+?\.js):\d+:\d+/); + if (match) { + const file = match[1]; + const baseName = file.replace(/.*\/(.*)\.js/, "$1"); + const parentDir = file.replace(/.*\/(.*)\/.*\.js/, "$1"); + return styleText("gray", parentDir === "js" ? `[${baseName}]` : `[${parentDir}]`); } - return msg; } - } - }); + } catch (err) { /* ignore */ } + return styleText("gray", "[unknown]"); + }; + + // Patch console methods to prepend timestamp, level label, and caller prefix. + for (const method of ["debug", "log", "info", "warn", "error"]) { + const original = console[method].bind(console); + const labelRaw = `[${method.toUpperCase()}]`.padEnd(7); + const label = LABEL_COLORS[method] ? styleText(LABEL_COLORS[method], labelRaw) : labelRaw; + console[method] = (...args) => { + const prefix = `${formatTimestamp()} ${label} ${getCallerPrefix()}`; + const msgColor = MSG_COLORS[method]; + if (msgColor && args.length > 0 && typeof args[0] === "string") { + original(prefix, styleText(msgColor, args[0]), ...args.slice(1)); + } else { + original(prefix, ...args); + } + }; + } } - // Node, CommonJS-like - module.exports = factory(root.config); - } else { - // Browser globals (root is window) - root.Log = factory(root.config); - } -}(this, function (config) { - let logLevel; - let enableLog; - if (typeof exports === "object") { - // in nodejs and not running in test mode - enableLog = process.env.mmTestMode !== "true"; + // Node, CommonJS + module.exports = makeLogger(); } else { - // in browser and not running with jsdom - enableLog = typeof window === "object" && window.name !== "jsdom"; + // Browser globals + window.Log = makeLogger(); } - if (enableLog) { - logLevel = { - debug: Function.prototype.bind.call(console.debug, console), - log: Function.prototype.bind.call(console.log, console), - info: Function.prototype.bind.call(console.info, console), - warn: Function.prototype.bind.call(console.warn, console), - error: Function.prototype.bind.call(console.error, console), - group: Function.prototype.bind.call(console.group, console), - groupCollapsed: Function.prototype.bind.call(console.groupCollapsed, console), - groupEnd: Function.prototype.bind.call(console.groupEnd, console), - time: Function.prototype.bind.call(console.time, console), - timeEnd: Function.prototype.bind.call(console.timeEnd, console), - timeStamp: console.timeStamp ? Function.prototype.bind.call(console.timeStamp, console) : function () {} - }; + /** + * Creates the logger object. Logging is disabled when running in test mode + * (Node.js) or inside jsdom (browser). + * @returns {object} The logger object with log level methods. + */ + function makeLogger () { + const enableLog = typeof module !== "undefined" + ? process.env.mmTestMode !== "true" + : typeof window === "object" && window.name !== "jsdom"; - logLevel.setLogLevel = function (newLevel) { - if (newLevel) { - Object.keys(logLevel).forEach(function (key) { - if (!newLevel.includes(key.toLocaleUpperCase())) { - logLevel[key] = function () {}; - } - }); - } - }; - } else { - logLevel = { - debug () {}, - log () {}, - info () {}, - warn () {}, - error () {}, - group () {}, - groupCollapsed () {}, - groupEnd () {}, - time () {}, - timeEnd () {}, - timeStamp () {} - }; + let logLevel; - logLevel.setLogLevel = function () {}; - } + if (enableLog) { + logLevel = { + debug: Function.prototype.bind.call(console.debug, console), + log: Function.prototype.bind.call(console.log, console), + info: Function.prototype.bind.call(console.info, console), + warn: Function.prototype.bind.call(console.warn, console), + error: Function.prototype.bind.call(console.error, console), + group: Function.prototype.bind.call(console.group, console), + groupCollapsed: Function.prototype.bind.call(console.groupCollapsed, console), + groupEnd: Function.prototype.bind.call(console.groupEnd, console), + time: Function.prototype.bind.call(console.time, console), + timeEnd: Function.prototype.bind.call(console.timeEnd, console), + timeStamp: console.timeStamp ? Function.prototype.bind.call(console.timeStamp, console) : function () {} + }; + + logLevel.setLogLevel = function (newLevel) { + if (newLevel) { + Object.keys(logLevel).forEach(function (key) { + if (!newLevel.includes(key.toLocaleUpperCase())) { + logLevel[key] = function () {}; + } + }); + } + }; + } else { + logLevel = { + debug () {}, + log () {}, + info () {}, + warn () {}, + error () {}, + group () {}, + groupCollapsed () {}, + groupEnd () {}, + time () {}, + timeEnd () {}, + timeStamp () {} + }; - return logLevel; -})); + logLevel.setLogLevel = function () {}; + } + + return logLevel; + } +}()); diff --git a/package-lock.json b/package-lock.json index fd92837595..735a7a6729 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@fortawesome/fontawesome-free": "^7.2.0", "ajv": "^8.18.0", "animate.css": "^4.1.1", - "console-stamp": "^3.1.2", "croner": "^10.0.1", "eslint": "^9.39.3", "express": "^5.2.1", @@ -249,6 +248,7 @@ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -407,6 +407,7 @@ "integrity": "sha512-Tdfx4eH2uS+gv9V9NCr3Rz+c7RSS6ntXp3Blliud18ibRUlRxO9dTaOjG4iv4x0nAmMeedP1ORkEpeXSkh2QiQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=20" } @@ -488,7 +489,8 @@ "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.19.tgz", "integrity": "sha512-VYHtPnZt/Zd/ATbW3rtexWpBnHUohUrQOHff/2JBhsVgxOrksAxJnLAO43Q1ayLJBJUUwNVo+RU0sx0aaysZfg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@cspell/dict-dart": { "version": "2.3.2", @@ -628,14 +630,16 @@ "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.14.tgz", "integrity": "sha512-2bf7n+kS92g+cMKV0wr9o/Oq9n8JzU7CcrB96gIh2GHgnF+0xDOqO2W/1KeFAqOfqosoOVE48t+4dnEMkkoJ2Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@cspell/dict-html-symbol-entities": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.5.tgz", "integrity": "sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@cspell/dict-java": { "version": "5.0.12", @@ -833,7 +837,8 @@ "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.3.tgz", "integrity": "sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@cspell/dict-vue": { "version": "3.0.5", @@ -991,6 +996,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=20.19.0" }, @@ -1031,6 +1037,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=20.19.0" } @@ -3708,6 +3715,7 @@ "integrity": "sha512-CGJ25bc8fRi8Lod/3GHSvXRKi7nBo3kxh0ApW4yCjmrWmRmlT53B5E08XRSZRliygG0aVNxLrBEqPYdz/KcCtQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/utils": "4.0.18", "fflate": "^0.8.2", @@ -3762,6 +3770,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4344,6 +4353,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "license": "MIT", + "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4637,19 +4647,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/console-stamp": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-3.1.2.tgz", - "integrity": "sha512-ab66x3NxOTxPuq71dI6gXEiw2X6ql4Le5gZz0bm7FW3FSCB00eztra/oQUuCoCGlsyKOxtULnHwphzMrRtzMBg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "dateformat": "^4.6.3" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/content-disposition": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", @@ -5064,15 +5061,6 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/dayjs": { "version": "1.11.15", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.15.tgz", @@ -5703,6 +5691,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -7557,6 +7546,7 @@ "integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@acemir/cssom": "^0.9.31", "@asamuzakjp/dom-selector": "^6.8.1", @@ -7630,7 +7620,6 @@ "integrity": "sha512-75EA7EWZExL/j+MDKQrRbdzcRI2HOkRlmUw8fZJc1ioqFEOvBsq7Rt+A6yCxOt9w/TYNpkt52gC6nm/g5tFIng==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "acorn": "^8.5.0", "eslint-visitor-keys": "^5.0.0", @@ -7649,7 +7638,6 @@ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, @@ -7962,6 +7950,7 @@ "integrity": "sha512-DzzmbqfMW3EzHsunP66x556oZDzjcdjjlL2bHG4PubwnL58ZPAfz07px4GqteZkoCGnBYi779Y2mg7+vgNCwbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "globby": "16.1.0", "js-yaml": "4.1.1", @@ -9680,6 +9669,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -9722,6 +9712,7 @@ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9752,6 +9743,7 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -11010,6 +11002,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@csstools/css-calc": "^3.1.1", "@csstools/css-parser-algorithms": "^4.0.0", @@ -11622,7 +11615,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -11692,6 +11684,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -11793,6 +11786,7 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -11883,6 +11877,7 @@ "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", diff --git a/package.json b/package.json index 8bc5c4b30b..17cf13765b 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,6 @@ "@fortawesome/fontawesome-free": "^7.2.0", "ajv": "^8.18.0", "animate.css": "^4.1.1", - "console-stamp": "^3.1.2", "croner": "^10.0.1", "eslint": "^9.39.3", "express": "^5.2.1", From e7503a457b6161736a2cfdf2dbfebb01fbefce8f Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 6 Mar 2026 18:56:16 +0100 Subject: [PATCH 376/418] refactor: further logger clean-up (#4050) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After #4049 here are two small follow-up improvements to `js/logger.js`. **1. Simpler bind syntax** — `Function.prototype.bind.call(console.debug, console)` is an archaic pattern. The equivalent `console.debug.bind(console)` works fine in all supported engines (Node.js ≥ 22, modern browsers) and is much easier to read. Also: `console.timeStamp` exists in all supported environments, so the conditional fallback to an empty function is no longer needed. **2. Simpler `setLogLevel`** — instead of iterating over all keys in the logger object and permanently overwriting them, the method now loops over the five log-level keys explicitly and rebinds from `console[key]`. This makes the filtered set obvious at a glance and ensures utility methods like `group`, `time`, and `timeStamp` are never accidentally silenced — they're structural helpers, not log levels. --- js/logger.js | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/js/logger.js b/js/logger.js index ccd74dbb99..b4b552288b 100644 --- a/js/logger.js +++ b/js/logger.js @@ -70,26 +70,25 @@ if (enableLog) { logLevel = { - debug: Function.prototype.bind.call(console.debug, console), - log: Function.prototype.bind.call(console.log, console), - info: Function.prototype.bind.call(console.info, console), - warn: Function.prototype.bind.call(console.warn, console), - error: Function.prototype.bind.call(console.error, console), - group: Function.prototype.bind.call(console.group, console), - groupCollapsed: Function.prototype.bind.call(console.groupCollapsed, console), - groupEnd: Function.prototype.bind.call(console.groupEnd, console), - time: Function.prototype.bind.call(console.time, console), - timeEnd: Function.prototype.bind.call(console.timeEnd, console), - timeStamp: console.timeStamp ? Function.prototype.bind.call(console.timeStamp, console) : function () {} + debug: console.debug.bind(console), + log: console.log.bind(console), + info: console.info.bind(console), + warn: console.warn.bind(console), + error: console.error.bind(console), + group: console.group.bind(console), + groupCollapsed: console.groupCollapsed.bind(console), + groupEnd: console.groupEnd.bind(console), + time: console.time.bind(console), + timeEnd: console.timeEnd.bind(console), + timeStamp: console.timeStamp.bind(console) }; + // Only these methods are affected by setLogLevel. + // Utility methods (group, time, etc.) are always active. logLevel.setLogLevel = function (newLevel) { - if (newLevel) { - Object.keys(logLevel).forEach(function (key) { - if (!newLevel.includes(key.toLocaleUpperCase())) { - logLevel[key] = function () {}; - } - }); + for (const key of ["debug", "log", "info", "warn", "error"]) { + const disabled = newLevel && !newLevel.includes(key.toUpperCase()); + logLevel[key] = disabled ? function () {} : console[key].bind(console); } }; } else { From cb61aebb5a7e5717c446affacad9b6b731d2b354 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:34:28 +0100 Subject: [PATCH 377/418] chore: update ESLint and plugins, simplify config, apply new rules (#4052) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR updates ESLint and the ESLint plugins to their latest versions and takes advantage of the new versions to simplify the config. The main cleanup: removed all explicit `plugins: {}` registrations from `eslint.config.mjs`. When passing direct config objects like `js.configs.recommended`, the plugin registration is already included – we were just doing it twice. Two lint warnings are also fixed: - A wrong import style for `eslint-plugin-package-json` (named vs. default) - `playwright/no-duplicate-hooks` is disabled for e2e tests – the rule doesn't handle plain `beforeAll()`/`afterAll()` (Vitest style) correctly and produces false positives. I've created an issue for that: https://github.com/mskelton/eslint-plugin-playwright/issues/443. Built-in Node.js imports were manually updated to use the `node:` prefix (e.g. `require("fs")` → `require("node:fs")`). Minor formatting fixes were applied automatically by `eslint --fix`. --- defaultmodules/clock/clock.js | 6 +- defaultmodules/weather/provider-utils.js | 2 +- defaultmodules/weather/providers/smhi.js | 10 +- .../weather/providers/weatherapi.js | 2 +- .../weather/providers/weatherflow.js | 5 +- defaultmodules/weather/providers/yr.js | 12 +- eslint.config.mjs | 39 +- js/alias-resolver.js | 2 +- package-lock.json | 598 ++++++++++-------- package.json | 8 +- serveronly/watcher.js | 10 +- vitest.config.mjs | 2 +- 12 files changed, 397 insertions(+), 299 deletions(-) diff --git a/defaultmodules/clock/clock.js b/defaultmodules/clock/clock.js index fbcbf2c1f1..c3f4e8541a 100644 --- a/defaultmodules/clock/clock.js +++ b/defaultmodules/clock/clock.js @@ -190,7 +190,7 @@ Module.register("clock", { } sunWrapperInnerHTML += ` ${formatTime(this.config, sunTimes.sunrise)}` - + ` ${formatTime(this.config, sunTimes.sunset)}`; + + ` ${formatTime(this.config, sunTimes.sunset)}`; sunWrapper.innerHTML = sunWrapperInnerHTML; digitalWrapper.appendChild(sunWrapper); @@ -218,8 +218,8 @@ Module.register("clock", { moonWrapper.innerHTML = `${image} ${showFraction ? illuminatedFractionString : ""}` - + ` ${moonRise ? formatTime(this.config, moonRise) : "..."}` - + ` ${moonSet ? formatTime(this.config, moonSet) : "..."}`; + + ` ${moonRise ? formatTime(this.config, moonRise) : "..."}` + + ` ${moonSet ? formatTime(this.config, moonSet) : "..."}`; digitalWrapper.appendChild(moonWrapper); } diff --git a/defaultmodules/weather/provider-utils.js b/defaultmodules/weather/provider-utils.js index f29e4396c5..5984926468 100644 --- a/defaultmodules/weather/provider-utils.js +++ b/defaultmodules/weather/provider-utils.js @@ -159,7 +159,7 @@ function cardinalToDegrees (direction) { */ function validateCoordinates (config, maxDecimals = 4) { if (config.lat == null || config.lon == null - || !Number.isFinite(config.lat) || !Number.isFinite(config.lon)) { + || !Number.isFinite(config.lat) || !Number.isFinite(config.lon)) { throw new Error("Latitude and longitude are required"); } diff --git a/defaultmodules/weather/providers/smhi.js b/defaultmodules/weather/providers/smhi.js index 70ffba8f9c..163d5bafde 100644 --- a/defaultmodules/weather/providers/smhi.js +++ b/defaultmodules/weather/providers/smhi.js @@ -275,13 +275,13 @@ class SMHIProvider { #isSamePeriod (date1, date2, groupBy) { if (groupBy === "hour") { return date1.getFullYear() === date2.getFullYear() - && date1.getMonth() === date2.getMonth() - && date1.getDate() === date2.getDate() - && date1.getHours() === date2.getHours(); + && date1.getMonth() === date2.getMonth() + && date1.getDate() === date2.getDate() + && date1.getHours() === date2.getHours(); } else { // day return date1.getFullYear() === date2.getFullYear() - && date1.getMonth() === date2.getMonth() - && date1.getDate() === date2.getDate(); + && date1.getMonth() === date2.getMonth() + && date1.getDate() === date2.getDate(); } } diff --git a/defaultmodules/weather/providers/weatherapi.js b/defaultmodules/weather/providers/weatherapi.js index 93f2f3195a..0ffb1821a2 100644 --- a/defaultmodules/weather/providers/weatherapi.js +++ b/defaultmodules/weather/providers/weatherapi.js @@ -221,7 +221,7 @@ class WeatherAPIProvider { return null; } - const match = /^\s*(\d{1,2}):(\d{2})\s*(AM|PM)\s*$/i.exec(timeValue); + const match = (/^\s*(\d{1,2}):(\d{2})\s*(AM|PM)\s*$/i).exec(timeValue); if (!match) { return null; } diff --git a/defaultmodules/weather/providers/weatherflow.js b/defaultmodules/weather/providers/weatherflow.js index 4797fa02ea..8a4d18daa8 100644 --- a/defaultmodules/weather/providers/weatherflow.js +++ b/defaultmodules/weather/providers/weatherflow.js @@ -8,6 +8,7 @@ const HTTPFetcher = require("#http_fetcher"); * Note that the WeatherFlow API does not provide snowfall. */ class WeatherFlowProvider { + /** * @param {object} config - Provider configuration */ @@ -190,8 +191,8 @@ class WeatherFlowProvider { // Compare year, month, and day to ensure correct matching across month boundaries if (hourDate.getFullYear() === forecastDate.getFullYear() - && hourDate.getMonth() === forecastDate.getMonth() - && hourDate.getDate() === forecastDate.getDate()) { + && hourDate.getMonth() === forecastDate.getMonth() + && hourDate.getDate() === forecastDate.getDate()) { weather.uvIndex = Math.max(weather.uvIndex, hour.uv || 0); weather.precipitationAmount += hour.precip || 0; } else if (hourDate > forecastDate) { diff --git a/defaultmodules/weather/providers/yr.js b/defaultmodules/weather/providers/yr.js index 3a4b4b0697..0de8b51964 100644 --- a/defaultmodules/weather/providers/yr.js +++ b/defaultmodules/weather/providers/yr.js @@ -102,11 +102,13 @@ class YrProvider { const data = await response.json(); // Transform single-day response into array format expected by #getStellarInfoForDate if (data && data.properties) { - this.stellarData = [{ - date: data.when.interval[0], // ISO date string - sunrise: data.properties.sunrise, - sunset: data.properties.sunset - }]; + this.stellarData = [ + { + date: data.when.interval[0], // ISO date string + sunrise: data.properties.sunrise, + sunset: data.properties.sunset + } + ]; } this.stellarDataDate = today; } diff --git a/eslint.config.mjs b/eslint.config.mjs index b8f07d7941..fcde3a6800 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,9 +1,9 @@ -import { defineConfig, globalIgnores } from "eslint/config"; +import {defineConfig, globalIgnores} from "eslint/config"; import globals from "globals"; -import { flatConfigs as importX } from "eslint-plugin-import-x"; +import {flatConfigs as importX} from "eslint-plugin-import-x"; import js from "@eslint/js"; import jsdocPlugin from "eslint-plugin-jsdoc"; -import packageJson from "eslint-plugin-package-json"; +import {configs as packageJsonConfigs} from "eslint-plugin-package-json"; import playwright from "eslint-plugin-playwright"; import stylistic from "@stylistic/eslint-plugin"; import vitest from "@vitest/eslint-plugin"; @@ -24,8 +24,7 @@ export default defineConfig([ moment: "readonly" } }, - plugins: { js, stylistic }, - extends: [importX.recommended, "js/recommended", jsdocPlugin.configs["flat/recommended"], stylistic.configs.customize({ indent: "tab", quotes: "double", semi: true, commaDangle: "never" })], + extends: [importX.recommended, js.configs.recommended, jsdocPlugin.configs["flat/recommended"], stylistic.configs.all], rules: { "@stylistic/array-element-newline": ["error", "consistent"], "@stylistic/arrow-parens": ["error", "always"], @@ -35,14 +34,14 @@ export default defineConfig([ "@stylistic/function-paren-newline": ["error", "consistent"], "@stylistic/implicit-arrow-linebreak": ["error", "beside"], "@stylistic/indent": ["error", "tab"], - "@stylistic/max-statements-per-line": ["error", { max: 2 }], + "@stylistic/max-statements-per-line": ["error", {max: 2}], "@stylistic/multiline-comment-style": "off", "@stylistic/multiline-ternary": ["error", "always-multiline"], - "@stylistic/newline-per-chained-call": ["error", { ignoreChainWithDepth: 4 }], + "@stylistic/newline-per-chained-call": ["error", {ignoreChainWithDepth: 4}], "@stylistic/no-extra-parens": "off", "@stylistic/no-tabs": "off", "@stylistic/object-curly-spacing": ["error", "always"], - "@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }], + "@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}], "@stylistic/operator-linebreak": ["error", "before"], "@stylistic/padded-blocks": "off", "@stylistic/quote-props": ["error", "as-needed"], @@ -51,7 +50,7 @@ export default defineConfig([ "@stylistic/space-before-function-paren": ["error", "always"], "@stylistic/spaced-comment": "off", "dot-notation": "error", - eqeqeq: ["error", "always", { null: "ignore" }], + eqeqeq: ["error", "always", {null: "ignore"}], "id-length": "off", "import-x/extensions": "error", "import-x/newline-after-import": "error", @@ -86,12 +85,11 @@ export default defineConfig([ "js/logger.js", "tests/**/*.js" ], - rules: { "no-console": "error" } + rules: {"no-console": "error"} }, { files: ["**/package.json"], - plugins: { packageJson }, - extends: ["packageJson/recommended"] + extends: [packageJsonConfigs.recommended] }, { files: ["**/*.mjs"], @@ -102,15 +100,14 @@ export default defineConfig([ }, sourceType: "module" }, - plugins: { js, stylistic }, - extends: [importX.recommended, "js/all", stylistic.configs.customize({ indent: "tab", quotes: "double", semi: true, commaDangle: "never" })], + extends: [importX.recommended, js.configs.all, stylistic.configs.all], rules: { "@stylistic/array-element-newline": "off", "@stylistic/indent": ["error", "tab"], - "@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }], + "@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}], "@stylistic/padded-blocks": ["error", "never"], "@stylistic/quote-props": ["error", "as-needed"], - "import-x/no-unresolved": ["error", { ignore: ["eslint/config"] }], + "import-x/no-unresolved": ["error", {ignore: ["eslint/config"]}], "max-lines-per-function": ["error", 100], "no-magic-numbers": "off", "one-var": ["error", "never"], @@ -124,7 +121,6 @@ export default defineConfig([ ...vitest.environments.env.globals } }, - plugins: { vitest }, extends: [vitest.configs.recommended], rules: { "vitest/consistent-test-it": "error", @@ -142,7 +138,7 @@ export default defineConfig([ ] } ], - "vitest/max-nested-describe": ["error", { max: 3 }], + "vitest/max-nested-describe": ["error", {max: 3}], "vitest/prefer-to-be": "error", "vitest/prefer-to-have-length": "error", "max-lines-per-function": "off" @@ -167,6 +163,13 @@ export default defineConfig([ files: ["tests/e2e/**/*.js"], extends: [playwright.configs["flat/recommended"]], rules: { + + /* + * Tests use Vitest-style plain beforeAll()/afterAll() calls, not Playwright's + * test.beforeAll() style. The rule incorrectly treats all plain hook calls + * as the same unnamed type, flagging the second hook as a duplicate. + */ + "playwright/no-duplicate-hooks": "off", "playwright/no-standalone-expect": "off" } } diff --git a/js/alias-resolver.js b/js/alias-resolver.js index 9af170a204..602e06677e 100644 --- a/js/alias-resolver.js +++ b/js/alias-resolver.js @@ -3,7 +3,7 @@ // For a future ESM migration, replace this with a public export/import surface. const path = require("node:path"); -const Module = require("module"); +const Module = require("node:module"); const root = path.join(__dirname, ".."); diff --git a/package-lock.json b/package-lock.json index 735a7a6729..faf2ca426d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "ajv": "^8.18.0", "animate.css": "^4.1.1", "croner": "^10.0.1", - "eslint": "^9.39.3", + "eslint": "^9.39.4", "express": "^5.2.1", "feedme": "^2.0.2", "helmet": "^8.1.0", @@ -35,15 +35,15 @@ "weathericons": "^2.1.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^5.9.0", + "@stylistic/eslint-plugin": "^5.10.0", "@vitest/coverage-v8": "^4.0.18", "@vitest/eslint-plugin": "^1.6.9", "@vitest/ui": "^4.0.18", "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.1", "eslint-plugin-jsdoc": "^62.7.1", - "eslint-plugin-package-json": "^0.89.2", - "eslint-plugin-playwright": "^2.8.0", + "eslint-plugin-package-json": "^0.89.4", + "eslint-plugin-playwright": "^2.9.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jsdom": "^28.1.0", @@ -248,7 +248,6 @@ "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@keyv/serialize": "^1.1.1" } @@ -407,7 +406,6 @@ "integrity": "sha512-Tdfx4eH2uS+gv9V9NCr3Rz+c7RSS6ntXp3Blliud18ibRUlRxO9dTaOjG4iv4x0nAmMeedP1ORkEpeXSkh2QiQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20" } @@ -485,12 +483,11 @@ "license": "MIT" }, "node_modules/@cspell/dict-css": { - "version": "4.0.19", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.19.tgz", - "integrity": "sha512-VYHtPnZt/Zd/ATbW3rtexWpBnHUohUrQOHff/2JBhsVgxOrksAxJnLAO43Q1ayLJBJUUwNVo+RU0sx0aaysZfg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.1.0.tgz", + "integrity": "sha512-bfuvlTeGoK5QgXzzjn+PvqXU5J6mwraIdESNDSvPyplr/EbGFSuvgW3TOuoVNqW4WdDI7eM4tmoP5Dn1ZVgLag==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@cspell/dict-dart": { "version": "2.3.2", @@ -535,9 +532,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.4.29", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.29.tgz", - "integrity": "sha512-G3B27++9ziRdgbrY/G/QZdFAnMzzx17u8nCb2Xyd4q6luLpzViRM/CW3jA+Mb/cGT5zR/9N+Yz9SrGu1s0bq7g==", + "version": "4.4.30", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.30.tgz", + "integrity": "sha512-+eVO/VNw8IzQpDIL/SCj+ytd5WbzbHZdU+GAM8eUY2ZU1KTxRw6BoDO+hEFB4cGkD9x+BXm0OKVGSWHNCSGdVw==", "dev": true, "license": "MIT" }, @@ -549,9 +546,9 @@ "license": "CC BY-SA 4.0" }, "node_modules/@cspell/dict-en-gb-mit": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.18.tgz", - "integrity": "sha512-AXaMzbaxhSc32MSzKX0cpwT+Thv1vPfxQz1nTly1VHw3wQcwPqVFSqrLOYwa8VNqAPR45583nnhD6iqJ9YESoQ==", + "version": "3.1.19", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.19.tgz", + "integrity": "sha512-Ni8eobxohZjVnzpUufMK2oLLRTUwFY4tF7pE2clAmM8ELgBaAheXlm5U52SpWmyhumz/c9fzburEYXKHG4spzQ==", "dev": true, "license": "MIT" }, @@ -630,16 +627,14 @@ "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.14.tgz", "integrity": "sha512-2bf7n+kS92g+cMKV0wr9o/Oq9n8JzU7CcrB96gIh2GHgnF+0xDOqO2W/1KeFAqOfqosoOVE48t+4dnEMkkoJ2Q==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@cspell/dict-html-symbol-entities": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.5.tgz", "integrity": "sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@cspell/dict-java": { "version": "5.0.12", @@ -698,13 +693,13 @@ "license": "MIT" }, "node_modules/@cspell/dict-markdown": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.14.tgz", - "integrity": "sha512-uLKPNJsUcumMQTsZZgAK9RgDLyQhUz/uvbQTEkvF/Q4XfC1i/BnA8XrOrd0+Vp6+tPOKyA+omI5LRWfMu5K/Lw==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.15.tgz", + "integrity": "sha512-xz3LJfFCIJaxHu5Msu9UUSev1R1urVkERb5h1Yc5lJyNOkk/SQTSlNyME0Oma1sXlp6dLnIekL8GyeXJYszQ2w==", "dev": true, "license": "MIT", "peerDependencies": { - "@cspell/dict-css": "^4.0.19", + "@cspell/dict-css": "^4.1.0", "@cspell/dict-html": "^4.0.14", "@cspell/dict-html-symbol-entities": "^4.0.5", "@cspell/dict-typescript": "^3.2.3" @@ -725,9 +720,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.35", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.35.tgz", - "integrity": "sha512-w0VIDUvzHSTt4S9pfvSatApxtCesLMFrDUYD0Wjtw91EBRkB2wVw/RV3q1Ni9Nzpx6pCFpcB7c1xBY8l22cyiQ==", + "version": "5.2.36", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.36.tgz", + "integrity": "sha512-QeoanpVt8QrSxDQVseXn+qk4sy79TAkbgB0G7q3klsZAByr61gXd1yDQ/0wp8xXsyPx+M/BIj5Qd6B8GnozFLA==", "dev": true, "license": "MIT" }, @@ -798,9 +793,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "5.1.23", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.1.23.tgz", - "integrity": "sha512-YzxBeqP1j8+hg/+pmw7XHvYrQLO5ttDpZ0rqZiS7y2vnku3Cv1OQZgt9y/3SsTgcUPSCWSRHGgWfrMGqEGNB6g==", + "version": "5.1.24", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.1.24.tgz", + "integrity": "sha512-Y+5b5mw8lnovcoyuiVJJX5PpNPMbdpNyILR4wJDsUMWPK2ZVcl0yyG2UYJmevY7jq/+LY48Ai9RSp0ARAlDzEQ==", "dev": true, "license": "MIT" }, @@ -837,8 +832,7 @@ "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.3.tgz", "integrity": "sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@cspell/dict-vue": { "version": "3.0.5", @@ -996,7 +990,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -1005,9 +998,9 @@ } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.28.tgz", - "integrity": "sha512-1NRf1CUBjnr3K7hu8BLxjQrKCxEe8FP/xmPTenAxCRZWVLbmGotkFvG9mfNpjA6k7Bw1bw4BilZq9cu19RA5pg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.0.tgz", + "integrity": "sha512-H4tuz2nhWgNKLt1inYpoVCfbJbMwX/lQKp3g69rrrIMIYlFD9+zTykOKhNR8uGrAmbS/kT9n6hTFkmDkxLgeTA==", "dev": true, "funding": [ { @@ -1037,7 +1030,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" } @@ -1721,14 +1713,14 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^3.1.5" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1787,9 +1779,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", - "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "license": "MIT", "dependencies": { "ajv": "^6.14.0", @@ -1799,7 +1791,7 @@ "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.3", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -1860,9 +1852,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.3", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", - "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1894,9 +1886,9 @@ } }, "node_modules/@exodus/bytes": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.1.tgz", - "integrity": "sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", + "integrity": "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==", "dev": true, "license": "MIT", "engines": { @@ -2056,6 +2048,22 @@ "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", @@ -2298,6 +2306,21 @@ "ws": "~7.5.10" } }, + "node_modules/@pm2/agent/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==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@pm2/agent/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -2613,6 +2636,9 @@ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2627,6 +2653,9 @@ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2641,6 +2670,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2655,6 +2687,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2669,6 +2704,9 @@ "loong64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2683,6 +2721,9 @@ "loong64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2697,6 +2738,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2711,6 +2755,9 @@ "ppc64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2725,6 +2772,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2739,6 +2789,9 @@ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2753,6 +2806,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2767,6 +2823,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2781,6 +2840,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2937,9 +2999,9 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.9.0.tgz", - "integrity": "sha512-FqqSkvDMYJReydrMhlugc71M76yLLQWNfmGq+SIlLa7N3kHp8Qq8i2PyWrVNAfjOyOIY+xv9XaaYwvVW7vroMA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.10.0.tgz", + "integrity": "sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3089,9 +3151,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.11.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.11.0.tgz", - "integrity": "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==", + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -3391,6 +3453,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3405,6 +3470,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3419,6 +3487,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3433,6 +3504,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3447,6 +3521,9 @@ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3461,6 +3538,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3475,6 +3555,9 @@ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -3489,6 +3572,9 @@ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -3715,7 +3801,6 @@ "integrity": "sha512-CGJ25bc8fRi8Lod/3GHSvXRKi7nBo3kxh0ApW4yCjmrWmRmlT53B5E08XRSZRliygG0aVNxLrBEqPYdz/KcCtQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "4.0.18", "fflate": "^0.8.2", @@ -3770,7 +3855,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3872,15 +3956,13 @@ } }, "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==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -4258,16 +4340,13 @@ } }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" @@ -4289,19 +4368,6 @@ "url": "https://github.com/chalk/chalk-template?sponsor=1" } }, - "node_modules/chalk-template/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/change-case": { "version": "5.4.4", "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", @@ -4353,7 +4419,6 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "license": "MIT", - "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4440,6 +4505,21 @@ "node": ">=8.10.0" } }, + "node_modules/cli-tableau/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==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/cli-tableau/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -4454,14 +4534,14 @@ } }, "node_modules/cli-truncate": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", - "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", "dev": true, "license": "MIT", "dependencies": { - "slice-ansi": "^7.1.0", - "string-width": "^8.0.0" + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" }, "engines": { "node": ">=20" @@ -4505,6 +4585,22 @@ "node": ">=8" } }, + "node_modules/cliui/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/cliui/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", @@ -4617,14 +4713,13 @@ } }, "node_modules/comment-json": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.5.1.tgz", - "integrity": "sha512-taEtr3ozUmOB7it68Jll7s0Pwm+aoiHyXKrEC8SEodL4rNpdfDLqa7PfBlrgFoCNNdR8ImL+muti5IGvktJAAg==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.6.2.tgz", + "integrity": "sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w==", "dev": true, "license": "MIT", "dependencies": { "array-timsort": "^1.0.3", - "core-util-is": "^1.0.3", "esprima": "^4.0.1" }, "engines": { @@ -4687,13 +4782,6 @@ "node": ">=6.6.0" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, "node_modules/cors": { "version": "2.8.6", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", @@ -4712,9 +4800,9 @@ } }, "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", + "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4966,19 +5054,6 @@ "@cspell/cspell-types": "9.7.0" } }, - "node_modules/cspell/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/css-functions-list": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", @@ -4990,14 +5065,14 @@ } }, "node_modules/css-tree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", - "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, "license": "MIT", "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" @@ -5017,13 +5092,13 @@ } }, "node_modules/cssstyle": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.1.0.tgz", - "integrity": "sha512-Ml4fP2UT2K3CUBQnVlbdV/8aFDdlY69E+YnwJM+3VUWl08S3J8c8aRuJqCkD9Py8DHZ7zNNvsfKl8psocHZEFg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.2.0.tgz", + "integrity": "sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^5.0.0", + "@asamuzakjp/css-color": "^5.0.1", "@csstools/css-syntax-patches-for-csstree": "^1.0.28", "css-tree": "^3.1.0", "lru-cache": "^11.2.6" @@ -5351,9 +5426,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "40.6.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-40.6.1.tgz", - "integrity": "sha512-u9YfoixttdauciHV9Ut9Zf3YipJoU093kR1GSYTTXTAXqhiXI0G1A0NnL/f0O2m2UULCXaXMf2W71PloR6V9pQ==", + "version": "40.8.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-40.8.0.tgz", + "integrity": "sha512-WoPq0Nr9Yx3g7T6VnJXdwa/rr2+VRyH3a+K+ezfMKBlf6WjxE/LmhMQabKbb6yjm9RbZhJBRcYyoLph421O2mQ==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5687,25 +5762,24 @@ } }, "node_modules/eslint": { - "version": "9.39.3", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", - "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", + "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.3", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "ajv": "^6.12.4", + "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", @@ -5724,7 +5798,7 @@ "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -5747,9 +5821,9 @@ } }, "node_modules/eslint-fix-utils": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/eslint-fix-utils/-/eslint-fix-utils-0.4.1.tgz", - "integrity": "sha512-1xPtnB7RYRHKrFGll3kRv5gOodHm3/jkk76jrKMZ2yk/G8HU9XoN1I9iHgh1ToAqmGG0/FFrybZMqmqUWp4asA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/eslint-fix-utils/-/eslint-fix-utils-0.4.2.tgz", + "integrity": "sha512-n7ZTcwwkP5scedlhvWMcqxED+O1NzXcj5Rxn/0kJQMP88k02vRcBfQ1qsk/JHb6Aw8bajFoetFCCBiNIcNCsvA==", "dev": true, "license": "MIT", "engines": { @@ -5870,9 +5944,9 @@ } }, "node_modules/eslint-plugin-jsdoc/node_modules/espree": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.1.tgz", - "integrity": "sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -5888,9 +5962,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.89.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.89.2.tgz", - "integrity": "sha512-1w9V/IwkkFzXJegbKHacbrOcupkIIp2F4ISB2JYfNl3g/NBiVbU8Db4IptVYVghcfJZlpVji2Us0cGCQPRCMVQ==", + "version": "0.89.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.89.4.tgz", + "integrity": "sha512-UyY8HVtsW4AljFVimnWKn04WI7JDBO7d9RIxSWpqwi/i0/1v001OkZhEZutkAATaewBt4l4aL9/EzJTpKWi0MA==", "dev": true, "license": "MIT", "dependencies": { @@ -5914,9 +5988,9 @@ } }, "node_modules/eslint-plugin-playwright": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.8.0.tgz", - "integrity": "sha512-BRCXbnX20l/ZPOOi1jEqNvqU/UjXpkZRJaghQxSM2kjAvsDph8+osn9u1iMmvoa9Cegbp9d0Skh7vro7242t+Q==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.9.0.tgz", + "integrity": "sha512-k3xrG6YzrallWNFMoGUjMNeu3SFFKXN79KJQBD2PkM4PasJegqV2Up+mPY5od2UmPKQGT+MeIhCmWH8r5eYuQQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5930,9 +6004,9 @@ } }, "node_modules/eslint-plugin-playwright/node_modules/globals": { - "version": "17.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.3.0.tgz", - "integrity": "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", + "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", "dev": true, "license": "MIT", "engines": { @@ -5986,6 +6060,21 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/eslint/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==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/eslint/node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -6002,6 +6091,22 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6453,9 +6558,9 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.4.tgz", + "integrity": "sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==", "license": "ISC" }, "node_modules/follow-redirects": { @@ -6876,9 +6981,9 @@ "optional": true }, "node_modules/graphql": { - "version": "16.13.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.0.tgz", - "integrity": "sha512-uSisMYERbaB9bkA9M4/4dnqyktaEkf1kMHNKq/7DHyxVeWqHQ2mBmVqm5u6/FVHwF3iCNalKcg82Zfl+tffWoA==", + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.1.tgz", + "integrity": "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==", "dev": true, "license": "MIT", "engines": { @@ -7546,7 +7651,6 @@ "integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@acemir/cssom": "^0.9.31", "@asamuzakjp/dom-selector": "^6.8.1", @@ -7620,6 +7724,7 @@ "integrity": "sha512-75EA7EWZExL/j+MDKQrRbdzcRI2HOkRlmUw8fZJc1ioqFEOvBsq7Rt+A6yCxOt9w/TYNpkt52gC6nm/g5tFIng==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "acorn": "^8.5.0", "eslint-visitor-keys": "^5.0.0", @@ -7638,6 +7743,7 @@ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", + "peer": true, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, @@ -7663,9 +7769,9 @@ } }, "node_modules/katex": { - "version": "0.16.33", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.33.tgz", - "integrity": "sha512-q3N5u+1sY9Bu7T4nlXoiRBXWfwSefNGoKeOwekV+gw0cAXQlz2Ww6BLcmBxVDeXBMUDQv6fK5bcNaJLxob3ZQA==", + "version": "0.16.37", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.37.tgz", + "integrity": "sha512-TIGjO2cCGYono+uUzgkE7RFF329mLLWGuHUlSr6cwIVj9O8f0VQZ783rsanmJpFUo32vvtj7XT04NGRPh+SZFg==", "dev": true, "funding": [ "https://opencollective.com/katex", @@ -7748,16 +7854,15 @@ } }, "node_modules/lint-staged": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.3.0.tgz", - "integrity": "sha512-YVHHy/p6U4/No9Af+35JLh3umJ9dPQnGTvNCbfO/T5fC60us0jFnc+vw33cqveI+kqxIFJQakcMVTO2KM+653A==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.3.2.tgz", + "integrity": "sha512-xKqhC2AeXLwiAHXguxBjuChoTTWFC6Pees0SHPwOpwlvI3BH7ZADFPddAdN3pgo3aiKgPUx/bxE78JfUnxQnlg==", "dev": true, "license": "MIT", "dependencies": { "commander": "^14.0.3", "listr2": "^9.0.5", "micromatch": "^4.0.8", - "nano-spawn": "^2.0.0", "string-argv": "^0.3.2", "tinyexec": "^1.0.2", "yaml": "^2.8.2" @@ -7844,6 +7949,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -7950,7 +8072,6 @@ "integrity": "sha512-DzzmbqfMW3EzHsunP66x556oZDzjcdjjlL2bHG4PubwnL58ZPAfz07px4GqteZkoCGnBYi779Y2mg7+vgNCwbw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "globby": "16.1.0", "js-yaml": "4.1.1", @@ -8034,9 +8155,9 @@ } }, "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, "license": "CC0-1.0" }, @@ -8842,19 +8963,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/nano-spawn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-2.0.0.tgz", - "integrity": "sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" - } - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -8953,12 +9061,12 @@ } }, "node_modules/node-ical": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.25.4.tgz", - "integrity": "sha512-nuKpkcy0f8Qh/H1arBjy8X+iQmpb0gvIlKSFOCsPOkCRDCGnEjsr0aPCHAAUckNTv4yoJmCf4ia9jbookZEHSg==", + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.25.5.tgz", + "integrity": "sha512-hj1I+kV38EXdhMB9Sh9phtvdzeJML/HvYbiKqBqcET1O2JiFmJnvpEWISNLA5nUeCWQAaTqiDhZH4uwUTG2Vdg==", "license": "Apache-2.0", "dependencies": { - "rrule-temporal": "^1.4.6", + "rrule-temporal": "^1.4.7", "temporal-polyfill": "^0.3.0" }, "engines": { @@ -9204,9 +9312,9 @@ } }, "node_modules/package-json-validator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-1.0.1.tgz", - "integrity": "sha512-1+g91/h2LU/QDtdX1EUFM40XIGxzgn/8TbWFZqzCnRxGRG+eIOW4+spYcjEn3u8IW2iOy6RIq99EIu26APGZfQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-1.0.2.tgz", + "integrity": "sha512-7QMbcpG8YyMkVsvGMohHzDYW9K+LtTvvc3H+BPQ+UxFPsaegsWTk3E3IZAiR3Ipm8tmRfHaCG9SanTbsU3hP2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9650,9 +9758,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dev": true, "funding": [ { @@ -9669,7 +9777,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -9712,7 +9819,6 @@ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9743,7 +9849,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -10248,9 +10353,9 @@ } }, "node_modules/rrule-temporal": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.4.6.tgz", - "integrity": "sha512-eRruK01K8uu0VWgn+lvKYXGZCER7eI2EaoAhsh5wwHaYMc4jPJ1cvY+bD0hBbYwCucggMpjtuwH2RpEH9oLfWg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.5.0.tgz", + "integrity": "sha512-kcANJ15yOav5TrGmSlGKwk4Jfvm5FpjtPL7rcfSkIqTlkEokWFyhx0gmmaYKyub8mJbU0dL/gzx1RvabfS4QgA==", "license": "MIT", "dependencies": { "@js-temporal/polyfill": "^0.5.1" @@ -10314,9 +10419,9 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", + "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" @@ -10595,35 +10700,22 @@ } }, "node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -11002,7 +11094,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@csstools/css-calc": "^3.1.1", "@csstools/css-parser-algorithms": "^4.0.0", @@ -11246,9 +11337,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.31.1", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.1.tgz", - "integrity": "sha512-6pRwxoGeV/roJYpsfcP6tN9mep6pPeCtXbUOCdVa0nme05Brwcwdge/fVNhIZn2wuUitAKZm4IYa7QjnRIa9zA==", + "version": "5.31.3", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.3.tgz", + "integrity": "sha512-vX0eeI7oGIr79NLiJRWnK8SyxDjyiNOEanaQnHRNyb5ep8QcpD8QMDvrukdrxV4pV4AKjwUDfaypXnWHMC/65A==", "license": "MIT", "os": [ "darwin", @@ -11298,6 +11389,22 @@ "node": ">=8" } }, + "node_modules/table/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/table/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", @@ -11427,22 +11534,22 @@ } }, "node_modules/tldts": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz", - "integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==", + "version": "7.0.25", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.25.tgz", + "integrity": "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.0.23" + "tldts-core": "^7.0.25" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz", - "integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==", + "version": "7.0.25", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.25.tgz", + "integrity": "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==", "dev": true, "license": "MIT" }, @@ -11615,6 +11722,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -11684,7 +11792,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -11786,7 +11893,6 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -11877,7 +11983,6 @@ "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", @@ -12107,19 +12212,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrap-ansi/node_modules/emoji-regex": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", diff --git a/package.json b/package.json index 17cf13765b..25ab5dd205 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "ajv": "^8.18.0", "animate.css": "^4.1.1", "croner": "^10.0.1", - "eslint": "^9.39.3", + "eslint": "^9.39.4", "express": "^5.2.1", "feedme": "^2.0.2", "helmet": "^8.1.0", @@ -112,15 +112,15 @@ "weathericons": "^2.1.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^5.9.0", + "@stylistic/eslint-plugin": "^5.10.0", "@vitest/coverage-v8": "^4.0.18", "@vitest/eslint-plugin": "^1.6.9", "@vitest/ui": "^4.0.18", "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.1", "eslint-plugin-jsdoc": "^62.7.1", - "eslint-plugin-package-json": "^0.89.2", - "eslint-plugin-playwright": "^2.8.0", + "eslint-plugin-package-json": "^0.89.4", + "eslint-plugin-playwright": "^2.9.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jsdom": "^28.1.0", diff --git a/serveronly/watcher.js b/serveronly/watcher.js index 95b62c2a12..c73be29415 100644 --- a/serveronly/watcher.js +++ b/serveronly/watcher.js @@ -1,11 +1,11 @@ // Load lightweight internal alias resolver to enable require("logger") require("../js/alias-resolver"); -const { spawn } = require("child_process"); -const fs = require("fs"); -const path = require("path"); -const net = require("net"); -const http = require("http"); +const { spawn } = require("node:child_process"); +const fs = require("node:fs"); +const path = require("node:path"); +const net = require("node:net"); +const http = require("node:http"); const Log = require("logger"); const { getConfigFilePath } = require("#server_functions"); diff --git a/vitest.config.mjs b/vitest.config.mjs index 0829d89278..80c231face 100644 --- a/vitest.config.mjs +++ b/vitest.config.mjs @@ -1,4 +1,4 @@ -import { defineConfig } from "vitest/config"; +import {defineConfig} from "vitest/config"; /* * Sequential execution keeps our shared test server stable: From 35cd4d87595836676ebf78acdc0e4d24d998e36f Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 8 Mar 2026 10:34:14 +0100 Subject: [PATCH 378/418] weather: add possibility to override njk's and css (#4051) This is an approach for #2909 It adds 2 values to the config: ```js themeDir: "./", themeCustomScripts: [] ``` `themeDir` must be specified relative to the weather dir. Example config: ```js { module: "weather", position: "top_center", config: { weatherProvider: "openmeteo", type: "current", lat: 40.776676, lon: -73.971321, themeDir: "../../../modules/MyWeatherTemplate/", themeCustomScripts: [ "skycons.js", "weathertheme.js" ], } }, ``` The `themeDir` must contain the 4 files - current.njk - forecast.njk - hourly.njk - weather.css You can add more files (if needed) and add them to the `themeCustomScripts` so they are loaded as script. There are 2 methods inserted which are called if defined: - initWeatherTheme: For doing special things when starting the module - updateWeatherTheme: For doing special things before updating the dom I see this as a simple approach for overriding the default njk templates and css. I did already convert my [MMM-WeatherBridge](https://gitlab.com/khassel/MMM-WeatherBridge) into a template. --- defaultmodules/weather/weather.js | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/defaultmodules/weather/weather.js b/defaultmodules/weather/weather.js index fc06af3734..ff87000066 100644 --- a/defaultmodules/weather/weather.js +++ b/defaultmodules/weather/weather.js @@ -42,7 +42,9 @@ Module.register("weather", { colored: false, absoluteDates: false, forecastDateFormat: "ddd", // format for forecast date display, e.g., "ddd" = Mon, "dddd" = Monday, "D MMM" = 18 Oct - hourlyForecastIncrements: 1 + hourlyForecastIncrements: 1, + themeDir: "./", + themeCustomScripts: [] }, // Module properties (all providers run server-side) @@ -57,14 +59,18 @@ Module.register("weather", { // Define required scripts. getStyles () { - return ["font-awesome.css", "weather-icons.css", "weather.css"]; + return ["font-awesome.css", "weather-icons.css", `${this.config.themeDir}weather.css`]; }, // Return the scripts that are necessary for the weather module. getScripts () { // Only load client-side dependencies for rendering // All providers run server-side via node_helper - return ["moment.js", "weatherutils.js", "weatherobject.js", "suncalc.js"]; + const resArr = ["moment.js", "weatherutils.js", "weatherobject.js", "suncalc.js"]; + this.config.themeCustomScripts.forEach((element) => { + resArr.push(`${this.config.themeDir}${element}`); + }); + return resArr; }, // Override getHeader method. @@ -98,6 +104,8 @@ Module.register("weather", { // All providers run server-side: generate unique instance ID and initialize via node_helper this.instanceId = `${this.identifier}_${Date.now()}`; + if (window.initWeatherTheme) window.initWeatherTheme(this); + Log.log(`[weather] Initializing server-side provider with instance ID: ${this.instanceId}`); this.sendSocketNotification("INIT_WEATHER", { @@ -211,15 +219,15 @@ Module.register("weather", { getTemplate () { switch (this.config.type.toLowerCase()) { case "current": - return "current.njk"; + return `${this.config.themeDir}current.njk`; case "hourly": - return "hourly.njk"; + return `${this.config.themeDir}hourly.njk`; case "daily": case "forecast": - return "forecast.njk"; + return `${this.config.themeDir}forecast.njk`; //Make the invalid values use the "Loading..." from forecast default: - return "forecast.njk"; + return `${this.config.themeDir}forecast.njk`; } }, @@ -242,7 +250,11 @@ Module.register("weather", { // What to do when the weather provider has new information available? updateAvailable () { Log.log("[weather] New weather information available."); - this.updateDom(300); + if (window.updateWeatherTheme) { + window.updateWeatherTheme(this); + } else { + this.updateDom(300); + } const currentWeather = this.currentWeatherObject; From 0ca91f7292dd68f9905b0ff3919aceb197712f8f Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Mon, 9 Mar 2026 23:29:48 +0100 Subject: [PATCH 379/418] weather: fixes for templates (#4054) Follow up for #4051 - fix loading default weather.css (the construction with `./weather.css` gave a 404) - accept `themeDir` with and without trailing slash --- defaultmodules/weather/weather.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/defaultmodules/weather/weather.js b/defaultmodules/weather/weather.js index ff87000066..cf0170a7b5 100644 --- a/defaultmodules/weather/weather.js +++ b/defaultmodules/weather/weather.js @@ -43,7 +43,7 @@ Module.register("weather", { absoluteDates: false, forecastDateFormat: "ddd", // format for forecast date display, e.g., "ddd" = Mon, "dddd" = Monday, "D MMM" = 18 Oct hourlyForecastIncrements: 1, - themeDir: "./", + themeDir: "", themeCustomScripts: [] }, @@ -57,9 +57,18 @@ Module.register("weather", { // Can be used by the provider to display location of event if nothing else is specified firstEvent: null, + getThemeDir () { + const td = this.config.themeDir.replace(/\/+$/, ""); + if (td.length > 0) { + return `${td}/`; + } else { + return ""; + } + }, + // Define required scripts. getStyles () { - return ["font-awesome.css", "weather-icons.css", `${this.config.themeDir}weather.css`]; + return ["font-awesome.css", "weather-icons.css", `${this.getThemeDir()}weather.css`]; }, // Return the scripts that are necessary for the weather module. @@ -68,7 +77,7 @@ Module.register("weather", { // All providers run server-side via node_helper const resArr = ["moment.js", "weatherutils.js", "weatherobject.js", "suncalc.js"]; this.config.themeCustomScripts.forEach((element) => { - resArr.push(`${this.config.themeDir}${element}`); + resArr.push(`${this.getThemeDir()}${element}`); }); return resArr; }, @@ -219,15 +228,15 @@ Module.register("weather", { getTemplate () { switch (this.config.type.toLowerCase()) { case "current": - return `${this.config.themeDir}current.njk`; + return `${this.getThemeDir()}current.njk`; case "hourly": - return `${this.config.themeDir}hourly.njk`; + return `${this.getThemeDir()}hourly.njk`; case "daily": case "forecast": - return `${this.config.themeDir}forecast.njk`; + return `${this.getThemeDir()}forecast.njk`; //Make the invalid values use the "Loading..." from forecast default: - return `${this.config.themeDir}forecast.njk`; + return `${this.getThemeDir()}forecast.njk`; } }, From 9fe7d1eb750b51a6cb23e9be2b3733b6e7fbec66 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 12 Mar 2026 00:40:23 +0100 Subject: [PATCH 380/418] test(calendar): fix hardcoded date in event shape test (#4055) While looking into #4053 I noticed that one of the calendar tests had stopped working. The cause was simple: the test had `2026-03-10` hardcoded, and since that date is now in the past, the event was silently filtered out by `includePastEvents: false`. Instead of bumping the date to some future value (which would only delay the same problem), I made it relative so it always lies in the future. Command to test: ```bash npx vitest run tests/unit/modules/default/calendar/ ``` --- .../default/calendar/calendar_fetcher_utils_spec.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js index 20c40efce9..bb7c86cac7 100644 --- a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js +++ b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js @@ -238,8 +238,9 @@ END:VCALENDAR`); }); it("should produce a correctly shaped event object with all required fields", () => { - const start = moment("2026-03-10T14:00:00").toDate(); - const end = moment("2026-03-10T15:00:00").toDate(); + const start = moment().add(1, "day").startOf("hour").toDate(); + const end = moment().add(1, "day").startOf("hour").add(1, "hour") + .toDate(); const filteredEvents = CalendarFetcherUtils.filterEvents( { @@ -266,7 +267,7 @@ END:VCALENDAR`); expect(ev.fullDayEvent).toBe(false); expect(ev.recurringEvent).toBe(false); expect(ev.class).toBe("PUBLIC"); - expect(ev.firstYear).toBe(2026); + expect(ev.firstYear).toBe(moment(start).year()); expect(ev.location).toBe("Room 42"); expect(ev.geo).toEqual({ lat: 52.52, lon: 13.4 }); expect(ev.description).toBe("Agenda TBD"); From 21d1e7472a8a0e6c06839e668e8cbccacba0b1f2 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 12 Mar 2026 10:35:42 +0100 Subject: [PATCH 381/418] refactor: simplify internal `require()` calls (#4056) Remove unnecessary `__dirname` template-literal prefix from relative `require()` paths. Node.js resolves relative require() paths correctly without it. While this may look like nitpicking: `require("./server")` is transparent to static analysis tools - IDEs can resolve the path and support go-to-definition. Template literals with `__dirname` are opaque to them. It also removes another usage of `__dirname`, which has no native equivalent in ESM and would need to be replaced there anyway (when we switch to ESM anytime in the future). The import reordering is a side effect: `import-x/order` treats template-literal `require()` calls differently from plain strings, so the previous order was no longer valid. --- js/app.js | 7 ++++--- js/server.js | 7 ++++--- js/utils.js | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/js/app.js b/js/app.js index 3de59c316b..04bda1221e 100644 --- a/js/app.js +++ b/js/app.js @@ -9,11 +9,12 @@ const Log = require("logger"); // global absolute root path global.root_path = path.resolve(`${__dirname}/../`); -const Server = require(`${__dirname}/server`); -const Utils = require(`${__dirname}/utils`); - // used to control fetch timeout for node_helpers const { setGlobalDispatcher, Agent } = require("undici"); + +const Server = require("./server"); +const Utils = require("./utils"); + const { getEnvVarsAsObj } = require("#server_functions"); // common timeout value, provide environment override in case const fetch_timeout = process.env.mmFetchTimeout !== undefined ? process.env.mmFetchTimeout : 30000; diff --git a/js/server.js b/js/server.js index 9eba4f97df..9922958ca9 100644 --- a/js/server.js +++ b/js/server.js @@ -6,11 +6,12 @@ const express = require("express"); const helmet = require("helmet"); const socketio = require("socket.io"); const Log = require("logger"); -const { getHtml, getVersion, getEnvVars, cors } = require("#server_functions"); -const { ipAccessControl } = require(`${__dirname}/ip_access_control`); +const { ipAccessControl } = require("./ip_access_control"); + +const vendor = require("./vendor"); -const vendor = require(`${__dirname}/vendor`); +const { getHtml, getVersion, getEnvVars, cors } = require("#server_functions"); /** * Server diff --git a/js/utils.js b/js/utils.js index ae43840278..f1c80ba2d0 100644 --- a/js/utils.js +++ b/js/utils.js @@ -96,7 +96,7 @@ const checkDeprecatedOptions = (userConfig) => { */ const loadConfig = () => { Log.log("Loading config ..."); - const defaults = require(`${__dirname}/defaults`); + const defaults = require("./defaults"); if (global.mmTestMode) { // if we are running in test mode defaults.address = "0.0.0.0"; From 3ea3f0a605e878c1c19cf32de92b78b28b8e32a6 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 12 Mar 2026 11:58:26 +0100 Subject: [PATCH 382/418] chore: upgrade ESLint to v10 and fix newly surfaced issues (#4057) `eslint-plugin-import-x` was the last thing blocking the ESLint v10 upgrade - it just got v10 support. So here we go. The upgrade itself is tiny. The rest of the diff is cleanup from issues ESLint v10 now catches: a few `let` declarations with initial values that were immediately overwritten anyway (`no-useless-assignment`), and `Translator` listed in `/* global */` in `main.js` and `module.js`. Working through those `no-useless-assignment` warnings also surfaced a dead default in `openmeteo`: `maxEntries: 5` in the constructor, which was never actually doing anything - `openmeteo` never reads `this.config.maxEntries` anywhere. And `weather.js` already sets that default for all providers, so it was just a redundant duplicate. Removed that too. No runtime behavior changes. --- defaultmodules/weather/providers/openmeteo.js | 13 +- .../weather/providers/openweathermap.js | 2 +- .../weather/providers/pirateweather.js | 2 +- .../weather/providers/ukmetofficedatahub.js | 2 +- defaultmodules/weather/weatherutils.js | 2 +- js/http_fetcher.js | 2 +- js/main.js | 2 +- js/module.js | 2 +- package-lock.json | 586 +++++++----------- package.json | 11 +- 10 files changed, 245 insertions(+), 379 deletions(-) diff --git a/defaultmodules/weather/providers/openmeteo.js b/defaultmodules/weather/providers/openmeteo.js index daad056e98..b85418fa6f 100644 --- a/defaultmodules/weather/providers/openmeteo.js +++ b/defaultmodules/weather/providers/openmeteo.js @@ -98,7 +98,6 @@ class OpenMeteoProvider { pastDays: 0, type: "current", maxNumberOfDays: 5, - maxEntries: 5, updateInterval: 10 * 60 * 1000, ...config }; @@ -241,16 +240,14 @@ class OpenMeteoProvider { } #getQueryParameters () { - const maxEntriesLimit = ["daily", "forecast"].includes(this.config.type) ? 7 : this.config.type === "hourly" ? 48 : 0; - let maxEntries = this.config.maxEntries; let maxNumberOfDays = this.config.maxNumberOfDays; if (this.config.maxNumberOfDays !== undefined && !isNaN(parseFloat(this.config.maxNumberOfDays))) { + const maxEntriesLimit = ["daily", "forecast"].includes(this.config.type) ? 7 : this.config.type === "hourly" ? 48 : 0; const daysFactor = ["daily", "forecast"].includes(this.config.type) ? 1 : this.config.type === "hourly" ? 24 : 0; - maxEntries = Math.max(1, Math.min(Math.round(parseFloat(this.config.maxNumberOfDays)) * daysFactor, maxEntriesLimit)); + const maxEntries = Math.max(1, Math.min(Math.round(parseFloat(this.config.maxNumberOfDays)) * daysFactor, maxEntriesLimit)); maxNumberOfDays = Math.ceil(maxEntries / Math.max(1, daysFactor)); } - maxEntries = Math.max(1, Math.min(maxEntries, maxEntriesLimit)); const params = { latitude: this.config.lat, @@ -429,7 +426,7 @@ class OpenMeteoProvider { // Add hourly data if available if (parsedData.hourly) { - let h = 0; + let h; const currentTime = parsedData.current_weather.time; // Handle both data shapes: object with arrays or array of objects (after transpose) @@ -522,8 +519,8 @@ class OpenMeteoProvider { const now = new Date(); parsedData.hourly.forEach((weather, i) => { - // Skip past entries, collect only future hours up to maxEntries - if (weather.time <= now || hours.length >= this.config.maxEntries) { + // Skip past entries + if (weather.time <= now) { return; } diff --git a/defaultmodules/weather/providers/openweathermap.js b/defaultmodules/weather/providers/openweathermap.js index 119df32b36..995855f17e 100644 --- a/defaultmodules/weather/providers/openweathermap.js +++ b/defaultmodules/weather/providers/openweathermap.js @@ -135,7 +135,7 @@ class OpenWeatherMapProvider { } #generateWeatherObjectsFromOnecall (data) { - let precip = false; + let precip; // Get current weather const current = {}; diff --git a/defaultmodules/weather/providers/pirateweather.js b/defaultmodules/weather/providers/pirateweather.js index 539eb877c6..7ea393d516 100644 --- a/defaultmodules/weather/providers/pirateweather.js +++ b/defaultmodules/weather/providers/pirateweather.js @@ -85,7 +85,7 @@ class PirateweatherProvider { return; } - let weatherData = null; + let weatherData; switch (this.config.type) { case "current": diff --git a/defaultmodules/weather/providers/ukmetofficedatahub.js b/defaultmodules/weather/providers/ukmetofficedatahub.js index 715458b0fd..c0f75bc1ca 100644 --- a/defaultmodules/weather/providers/ukmetofficedatahub.js +++ b/defaultmodules/weather/providers/ukmetofficedatahub.js @@ -116,7 +116,7 @@ class UkMetOfficeDataHubProvider { return; } - let weatherData = null; + let weatherData; switch (this.config.type) { case "current": diff --git a/defaultmodules/weather/weatherutils.js b/defaultmodules/weather/weatherutils.js index 365441f0b5..7d1436c394 100644 --- a/defaultmodules/weather/weatherutils.js +++ b/defaultmodules/weather/weatherutils.js @@ -31,7 +31,7 @@ const WeatherUtils = { if (valueUnit === "%") return `${value.toFixed(0)} ${valueUnit}`; let convertedValue = value; - let conversionUnit = valueUnit; + let conversionUnit; if (outputUnit === "imperial") { convertedValue = this.convertPrecipitationToInch(value, valueUnit); conversionUnit = "in"; diff --git a/js/http_fetcher.js b/js/http_fetcher.js index 95a13ba5d2..f72b4a3be9 100644 --- a/js/http_fetcher.js +++ b/js/http_fetcher.js @@ -191,7 +191,7 @@ class HTTPFetcher extends EventEmitter { #getDelayForResponse (response) { const { status } = response; let delay = this.reloadInterval; - let message = ""; + let message; let errorType = "UNKNOWN_ERROR"; if (status === 401 || status === 403) { diff --git a/js/main.js b/js/main.js index f5c9e75e5f..359f71df0e 100644 --- a/js/main.js +++ b/js/main.js @@ -1,4 +1,4 @@ -/* global Loader, defaults, Translator, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut, modulePositions, io */ +/* global Loader, defaults, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut, modulePositions, io */ const MM = (function () { let modules = []; diff --git a/js/module.js b/js/module.js index 176ef98076..f38d808995 100644 --- a/js/module.js +++ b/js/module.js @@ -1,4 +1,4 @@ -/* global Class, cloneObject, Loader, MMSocket, nunjucks, Translator */ +/* global Class, cloneObject, Loader, MMSocket, nunjucks */ /* * Module Blueprint. diff --git a/package-lock.json b/package-lock.json index faf2ca426d..1ad1478111 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "ajv": "^8.18.0", "animate.css": "^4.1.1", "croner": "^10.0.1", - "eslint": "^9.39.4", + "eslint": "^10.0.3", "express": "^5.2.1", "feedme": "^2.0.2", "helmet": "^8.1.0", @@ -35,14 +35,15 @@ "weathericons": "^2.1.0" }, "devDependencies": { + "@eslint/js": "^10.0.1", "@stylistic/eslint-plugin": "^5.10.0", "@vitest/coverage-v8": "^4.0.18", - "@vitest/eslint-plugin": "^1.6.9", + "@vitest/eslint-plugin": "^1.6.10", "@vitest/ui": "^4.0.18", "cspell": "^9.7.0", - "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-jsdoc": "^62.7.1", - "eslint-plugin-package-json": "^0.89.4", + "eslint-plugin-import-x": "^4.16.2", + "eslint-plugin-jsdoc": "^62.8.0", + "eslint-plugin-package-json": "^0.90.1", "eslint-plugin-playwright": "^2.9.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", @@ -455,9 +456,9 @@ } }, "node_modules/@cspell/dict-companies": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.2.10.tgz", - "integrity": "sha512-bJ1qnO1DkTn7JYGXvxp8FRQc4yq6tRXnrII+jbP8hHmq5TX5o1Wu+rdfpoUQaMWTl6balRvcMYiINDesnpR9Bw==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.2.11.tgz", + "integrity": "sha512-0cmafbcz2pTHXLd59eLR1gvDvN6aWAOM0+cIL4LLF9GX9yB2iKDNrKsvs4tJRqutoaTdwNFBbV0FYv+6iCtebQ==", "dev": true, "license": "MIT" }, @@ -483,9 +484,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-css": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.1.0.tgz", - "integrity": "sha512-bfuvlTeGoK5QgXzzjn+PvqXU5J6mwraIdESNDSvPyplr/EbGFSuvgW3TOuoVNqW4WdDI7eM4tmoP5Dn1ZVgLag==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.1.1.tgz", + "integrity": "sha512-y/Vgo6qY08e1t9OqR56qjoFLBCpi4QfWMf2qzD1l9omRZwvSMQGRPz4x0bxkkkU4oocMAeztjzCsmLew//c/8w==", "dev": true, "license": "MIT" }, @@ -532,9 +533,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.4.30", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.30.tgz", - "integrity": "sha512-+eVO/VNw8IzQpDIL/SCj+ytd5WbzbHZdU+GAM8eUY2ZU1KTxRw6BoDO+hEFB4cGkD9x+BXm0OKVGSWHNCSGdVw==", + "version": "4.4.31", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.31.tgz", + "integrity": "sha512-MdV6mbrSkyIqn9+6F5poCyHIPqWB3H/wlDL9LXfjgAxNFBdYRE767xJtIYunzUqhUiJHSJgZajEFdTtMDw441Q==", "dev": true, "license": "MIT" }, @@ -546,16 +547,16 @@ "license": "CC BY-SA 4.0" }, "node_modules/@cspell/dict-en-gb-mit": { - "version": "3.1.19", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.19.tgz", - "integrity": "sha512-Ni8eobxohZjVnzpUufMK2oLLRTUwFY4tF7pE2clAmM8ELgBaAheXlm5U52SpWmyhumz/c9fzburEYXKHG4spzQ==", + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.20.tgz", + "integrity": "sha512-rcWEKb1mwgK13CSHu6GwwFA/sWLRkB0twTzSfPxUOULJkhcUrL93ixohk416SBa0BVxixub+lOpTXKcCTbTXsA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.16.tgz", - "integrity": "sha512-SyrtuK2/sx+cr94jOp2/uOAb43ngZEVISUTRj4SR6SfoGULVV1iJS7Drqn7Ul9HJ731QDttwWlOUgcQ+yMRblg==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.17.tgz", + "integrity": "sha512-6f1gZf9o60fGQXGi/fZaryISUNDRmmJwGyr4QU1UvgUgOdpDHLVJtv/0wSL9q5F0wAkYhbXo/fNG8CcUTaf7Ww==", "dev": true, "license": "MIT" }, @@ -567,9 +568,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-fonts": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.5.tgz", - "integrity": "sha512-BbpkX10DUX/xzHs6lb7yzDf/LPjwYIBJHJlUXSBXDtK/1HaeS+Wqol4Mlm2+NAgZ7ikIE5DQMViTgBUY3ezNoQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.6.tgz", + "integrity": "sha512-aR/0csY01dNb0A1tw/UmN9rKgHruUxsYsvXu6YlSBJFu60s26SKr/k1o4LavpHTQ+lznlYMqAvuxGkE4Flliqw==", "dev": true, "license": "MIT" }, @@ -623,9 +624,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-html": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.14.tgz", - "integrity": "sha512-2bf7n+kS92g+cMKV0wr9o/Oq9n8JzU7CcrB96gIh2GHgnF+0xDOqO2W/1KeFAqOfqosoOVE48t+4dnEMkkoJ2Q==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.15.tgz", + "integrity": "sha512-GJYnYKoD9fmo2OI0aySEGZOjThnx3upSUvV7mmqUu8oG+mGgzqm82P/f7OqsuvTaInZZwZbo+PwJQd/yHcyFIw==", "dev": true, "license": "MIT" }, @@ -693,14 +694,14 @@ "license": "MIT" }, "node_modules/@cspell/dict-markdown": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.15.tgz", - "integrity": "sha512-xz3LJfFCIJaxHu5Msu9UUSev1R1urVkERb5h1Yc5lJyNOkk/SQTSlNyME0Oma1sXlp6dLnIekL8GyeXJYszQ2w==", + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.16.tgz", + "integrity": "sha512-976RRqKv6cwhrxdFCQP2DdnBVB86BF57oQtPHy4Zbf4jF/i2Oy29MCrxirnOBalS1W6KQeto7NdfDXRAwkK4PQ==", "dev": true, "license": "MIT", "peerDependencies": { - "@cspell/dict-css": "^4.1.0", - "@cspell/dict-html": "^4.0.14", + "@cspell/dict-css": "^4.1.1", + "@cspell/dict-html": "^4.0.15", "@cspell/dict-html-symbol-entities": "^4.0.5", "@cspell/dict-typescript": "^3.2.3" } @@ -720,9 +721,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.36", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.36.tgz", - "integrity": "sha512-QeoanpVt8QrSxDQVseXn+qk4sy79TAkbgB0G7q3klsZAByr61gXd1yDQ/0wp8xXsyPx+M/BIj5Qd6B8GnozFLA==", + "version": "5.2.37", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.37.tgz", + "integrity": "sha512-dYKrD0bI08YgebJcbjsIDpTMK6EH0wTkEyQLsaH0T4tmsLJE95coTYb3eE7giRRGJADvBqrjH4fz5+INd85QqQ==", "dev": true, "license": "MIT" }, @@ -765,9 +766,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-ruby": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.1.0.tgz", - "integrity": "sha512-9PJQB3cfkBULrMLp5kSAcFPpzf8oz9vFN+QYZABhQwWkGbuzCIXSorHrmWSASlx4yejt3brjaWS57zZ/YL5ZQQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.1.1.tgz", + "integrity": "sha512-LHrp84oEV6q1ZxPPyj4z+FdKyq1XAKYPtmGptrd+uwHbrF/Ns5+fy6gtSi7pS+uc0zk3JdO9w/tPK+8N1/7WUA==", "dev": true, "license": "MIT" }, @@ -793,9 +794,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "5.1.24", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.1.24.tgz", - "integrity": "sha512-Y+5b5mw8lnovcoyuiVJJX5PpNPMbdpNyILR4wJDsUMWPK2ZVcl0yyG2UYJmevY7jq/+LY48Ai9RSp0ARAlDzEQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.2.0.tgz", + "integrity": "sha512-jyucc8KKxH5ClC4FPICISgcKAZU7UwgFdPkuuuK5nYIw0+l1umnUSn9IKCcOaurvXujvVP6mBfclXpUtmT6Vrw==", "dev": true, "license": "MIT" }, @@ -1713,176 +1714,84 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", - "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "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==", "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.7", + "@eslint/object-schema": "^3.0.3", "debug": "^4.3.1", - "minimatch": "^3.1.5" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" + "minimatch": "^10.2.4" }, "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz", + "integrity": "sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0" + "@eslint/core": "^1.1.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz", + "integrity": "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", - "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", - "license": "MIT", - "dependencies": { - "ajv": "^6.14.0", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.5", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/js": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", - "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz", + "integrity": "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==", "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz", + "integrity": "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0", + "@eslint/core": "^1.1.1", "levn": "^0.4.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@exodus/bytes": { @@ -2286,6 +2195,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@package-json/types": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@package-json/types/-/types-0.0.12.tgz", + "integrity": "sha512-uu43FGU34B5VM9mCNjXCwLaGHYjXdNincqKLaraaCW+7S2+SmiBg1Nv8bPnmschrIfZmfKNY9f3fC376MRrObw==", + "dev": true, + "license": "MIT" + }, "node_modules/@pm2/agent": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.1.1.tgz", @@ -3107,6 +3023,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -3183,6 +3105,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yauzl": { "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", @@ -3194,14 +3125,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", - "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz", + "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.56.1", - "@typescript-eslint/types": "^8.56.1", + "@typescript-eslint/tsconfig-utils": "^8.57.0", + "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "engines": { @@ -3216,14 +3147,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", - "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz", + "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1" + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3234,9 +3165,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", - "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz", + "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==", "dev": true, "license": "MIT", "engines": { @@ -3251,9 +3182,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", - "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz", + "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==", "dev": true, "license": "MIT", "engines": { @@ -3265,16 +3196,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", - "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz", + "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.56.1", - "@typescript-eslint/tsconfig-utils": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/project-service": "8.57.0", + "@typescript-eslint/tsconfig-utils": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -3293,16 +3224,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", - "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz", + "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1" + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3317,13 +3248,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", - "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz", + "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3672,9 +3603,9 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.9.tgz", - "integrity": "sha512-9WfPx1OwJ19QLCSRLkqVO7//1WcWnK3fE/3fJhKMAmDe8+9G4rB47xCNIIeCq3FdEzkIoLTfDlwDlPBaUTMhow==", + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.10.tgz", + "integrity": "sha512-/cOf+mTu4HBJIYHTETo8/OFCSZv3T2p+KfGnouzKfjK063cWLZp0TzvK7EU5B3eFG7ypUNtw6l+jK+SA+p1g8g==", "dev": true, "license": "MIT", "dependencies": { @@ -4091,7 +4022,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" @@ -4192,7 +4122,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -4324,6 +4253,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -4736,12 +4666,6 @@ "node": ">= 12.0.0" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, "node_modules/content-disposition": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", @@ -5471,13 +5395,14 @@ } }, "node_modules/engine.io": { - "version": "6.6.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz", - "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==", + "version": "6.6.6", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.6.tgz", + "integrity": "sha512-U2SN0w3OpjFRVlrc17E6TMDmH58Xl9rai1MblNjAdwWp07Kk+llmzX0hjDpQdrDGzwmvOtgM5yI+meYX6iZ2xA==", "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", + "@types/ws": "^8.5.12", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", @@ -5762,32 +5687,29 @@ } }, "node_modules/eslint": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", - "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.3.tgz", + "integrity": "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==", "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.2", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.5", - "@eslint/js": "9.39.4", - "@eslint/plugin-kit": "^0.4.1", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.3", + "@eslint/config-helpers": "^0.5.2", + "@eslint/core": "^1.1.1", + "@eslint/plugin-kit": "^0.6.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", - "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.1.1", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -5797,8 +5719,7 @@ "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.5", + "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -5806,7 +5727,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" @@ -5865,18 +5786,19 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.16.1.tgz", - "integrity": "sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==", + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.16.2.tgz", + "integrity": "sha512-rM9K8UBHcWKpzQzStn1YRN2T5NvdeIfSVoKu/lKF41znQXHAUcBbYXe5wd6GNjZjTrP7viQ49n1D83x/2gYgIw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.35.0", + "@package-json/types": "^0.0.12", + "@typescript-eslint/types": "^8.56.0", "comment-parser": "^1.4.1", "debug": "^4.4.1", "eslint-import-context": "^0.1.9", "is-glob": "^4.0.3", - "minimatch": "^9.0.3 || ^10.0.1", + "minimatch": "^9.0.3 || ^10.1.2", "semver": "^7.7.2", "stable-hash-x": "^0.2.0", "unrs-resolver": "^1.9.2" @@ -5888,8 +5810,8 @@ "url": "https://opencollective.com/eslint-plugin-import-x" }, "peerDependencies": { - "@typescript-eslint/utils": "^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", + "@typescript-eslint/utils": "^8.56.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "eslint-import-resolver-node": "*" }, "peerDependenciesMeta": { @@ -5902,9 +5824,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "62.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.7.1.tgz", - "integrity": "sha512-4Zvx99Q7d1uggYBUX/AIjvoyqXhluGbbKrRmG8SQTLprPFg6fa293tVJH1o1GQwNe3lUydd8ZHzn37OaSncgSQ==", + "version": "62.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.8.0.tgz", + "integrity": "sha512-hu3r9/6JBmPG6wTcqtYzgZAnjEG2eqRUATfkFscokESg1VDxZM21ZaMire0KjeMwfj+SXvgB4Rvh5LBuesj92w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5962,9 +5884,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.89.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.89.4.tgz", - "integrity": "sha512-UyY8HVtsW4AljFVimnWKn04WI7JDBO7d9RIxSWpqwi/i0/1v001OkZhEZutkAATaewBt4l4aL9/EzJTpKWi0MA==", + "version": "0.90.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.90.1.tgz", + "integrity": "sha512-6GU2nyjGZ+iSLIo1Qxm6O2HcPKshpjIS3B5ZeBTt8spGad5IQ45+hQUDrULYP0vD6SFT8veJfQ/Ha49/g4Cr5w==", "dev": true, "license": "MIT", "dependencies": { @@ -5973,7 +5895,7 @@ "detect-indent": "^7.0.2", "detect-newline": "^4.0.1", "eslint-fix-utils": "~0.4.1", - "package-json-validator": "^1.0.1", + "package-json-validator": "^1.2.1", "semver": "^7.7.3", "sort-object-keys": "^2.0.0", "sort-package-json": "^3.4.0", @@ -6003,30 +5925,19 @@ "eslint": ">=8.40.0" } }, - "node_modules/eslint-plugin-playwright/node_modules/globals": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", - "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "license": "BSD-2-Clause", "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6036,6 +5947,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6060,51 +5972,33 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/eslint/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==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", + "node_modules/eslint/node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "license": "BSD-2-Clause", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": ">=10" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/json-schema-traverse": { @@ -6113,22 +6007,11 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "license": "MIT" }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.15.0", @@ -6558,9 +6441,9 @@ } }, "node_modules/flatted": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.4.tgz", - "integrity": "sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", + "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", "license": "ISC" }, "node_modules/follow-redirects": { @@ -6869,9 +6752,10 @@ } }, "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", + "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -7269,6 +7153,7 @@ "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", @@ -7285,6 +7170,7 @@ "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" @@ -7297,6 +7183,7 @@ "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" @@ -7769,9 +7656,9 @@ } }, "node_modules/katex": { - "version": "0.16.37", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.37.tgz", - "integrity": "sha512-TIGjO2cCGYono+uUzgkE7RFF329mLLWGuHUlSr6cwIVj9O8f0VQZ783rsanmJpFUo32vvtj7XT04NGRPh+SZFg==", + "version": "0.16.38", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.38.tgz", + "integrity": "sha512-cjHooZUmIAUmDsHBN+1n8LaZdpmbj03LtYeYPyuYB7OuloiaeaV6N4LcfjcnHVzGWjVQmKrxxTrpDcmSzEZQwQ==", "dev": true, "funding": [ "https://opencollective.com/katex", @@ -7854,9 +7741,9 @@ } }, "node_modules/lint-staged": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.3.2.tgz", - "integrity": "sha512-xKqhC2AeXLwiAHXguxBjuChoTTWFC6Pees0SHPwOpwlvI3BH7ZADFPddAdN3pgo3aiKgPUx/bxE78JfUnxQnlg==", + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.3.3.tgz", + "integrity": "sha512-RLq2koZ5fGWrx7tcqx2tSTMQj4lRkfNJaebO/li/uunhCJbtZqwTuwPHpgIimAHHi/2nZIiGrkCHDCOeR1onxA==", "dev": true, "license": "MIT", "dependencies": { @@ -7916,12 +7803,6 @@ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "license": "MIT" - }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -8827,7 +8708,6 @@ "version": "10.2.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.2" @@ -9312,9 +9192,9 @@ } }, "node_modules/package-json-validator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-1.0.2.tgz", - "integrity": "sha512-7QMbcpG8YyMkVsvGMohHzDYW9K+LtTvvc3H+BPQ+UxFPsaegsWTk3E3IZAiR3Ipm8tmRfHaCG9SanTbsU3hP2Q==", + "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==", "dev": true, "license": "MIT", "dependencies": { @@ -10353,9 +10233,9 @@ } }, "node_modules/rrule-temporal": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.5.0.tgz", - "integrity": "sha512-kcANJ15yOav5TrGmSlGKwk4Jfvm5FpjtPL7rcfSkIqTlkEokWFyhx0gmmaYKyub8mJbU0dL/gzx1RvabfS4QgA==", + "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==", "license": "MIT", "dependencies": { "@js-temporal/polyfill": "^0.5.1" @@ -11066,18 +10946,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/stylelint": { "version": "17.4.0", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.4.0.tgz", @@ -11337,9 +11205,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.31.3", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.3.tgz", - "integrity": "sha512-vX0eeI7oGIr79NLiJRWnK8SyxDjyiNOEanaQnHRNyb5ep8QcpD8QMDvrukdrxV4pV4AKjwUDfaypXnWHMC/65A==", + "version": "5.31.4", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.4.tgz", + "integrity": "sha512-lZppDyQx91VdS5zJvAyGkmwe+Mq6xY978BDUG2wRkWE+jkmUF5ti8cvOovFQoN5bvSFKCXVkyKEaU5ec3SJiRg==", "license": "MIT", "os": [ "darwin", @@ -11475,18 +11343,18 @@ } }, "node_modules/temporal-polyfill": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.3.0.tgz", - "integrity": "sha512-qNsTkX9K8hi+FHDfHmf22e/OGuXmfBm9RqNismxBrnSmZVJKegQ+HYYXT+R7Ha8F/YSm2Y34vmzD4cxMu2u95g==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.3.2.tgz", + "integrity": "sha512-TzHthD/heRK947GNiSu3Y5gSPpeUDH34+LESnfsq8bqpFhsB79HFBX8+Z834IVX68P3EUyRPZK5bL/1fh437Eg==", "license": "MIT", "dependencies": { - "temporal-spec": "0.3.0" + "temporal-spec": "0.3.1" } }, "node_modules/temporal-spec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.3.0.tgz", - "integrity": "sha512-n+noVpIqz4hYgFSMOSiINNOUOMFtV5cZQNCmmszA6GiVFVRt3G7AqVyhXjhCSmowvQn+NsGn+jMDMKJYHd3bSQ==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.3.1.tgz", + "integrity": "sha512-B4TUhezh9knfSIMwt7RVggApDRJZo73uZdj8AacL2mZ8RP5KtLianh2MXxL06GN9ESYiIsiuoLQhgVfwe55Yhw==", "license": "ISC" }, "node_modules/tinybench": { diff --git a/package.json b/package.json index 25ab5dd205..351b24a934 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "ajv": "^8.18.0", "animate.css": "^4.1.1", "croner": "^10.0.1", - "eslint": "^9.39.4", + "eslint": "^10.0.3", "express": "^5.2.1", "feedme": "^2.0.2", "helmet": "^8.1.0", @@ -112,14 +112,15 @@ "weathericons": "^2.1.0" }, "devDependencies": { + "@eslint/js": "^10.0.1", "@stylistic/eslint-plugin": "^5.10.0", "@vitest/coverage-v8": "^4.0.18", - "@vitest/eslint-plugin": "^1.6.9", + "@vitest/eslint-plugin": "^1.6.10", "@vitest/ui": "^4.0.18", "cspell": "^9.7.0", - "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-jsdoc": "^62.7.1", - "eslint-plugin-package-json": "^0.89.4", + "eslint-plugin-import-x": "^4.16.2", + "eslint-plugin-jsdoc": "^62.8.0", + "eslint-plugin-package-json": "^0.90.1", "eslint-plugin-playwright": "^2.9.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", From d0723457753c9160a7c18038e07b399e3a8484e4 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Thu, 12 Mar 2026 20:18:18 +0100 Subject: [PATCH 383/418] update dependencies incl. electron to v41 (#4058) - update to electron v41 - update other deps - add missing `globals` dep, see https://github.com/MagicMirrorOrg/MagicMirror/pull/4057#issuecomment-4049058107 --- package-lock.json | 1529 +++++++++++++++++++-------------------------- package.json | 19 +- 2 files changed, 641 insertions(+), 907 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ad1478111..93b48d46e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,27 +19,28 @@ "eslint": "^10.0.3", "express": "^5.2.1", "feedme": "^2.0.2", + "globals": "^17.4.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.0", - "node-ical": "^0.25.4", + "node-ical": "^0.25.5", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.31.1", - "undici": "^7.22.0", + "systeminformation": "^5.31.4", + "undici": "^7.23.0", "weathericons": "^2.1.0" }, "devDependencies": { "@eslint/js": "^10.0.1", "@stylistic/eslint-plugin": "^5.10.0", - "@vitest/coverage-v8": "^4.0.18", - "@vitest/eslint-plugin": "^1.6.10", - "@vitest/ui": "^4.0.18", + "@vitest/coverage-v8": "^4.1.0", + "@vitest/eslint-plugin": "^1.6.11", + "@vitest/ui": "^4.1.0", "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.2", "eslint-plugin-jsdoc": "^62.8.0", @@ -48,7 +49,7 @@ "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jsdom": "^28.1.0", - "lint-staged": "^16.3.0", + "lint-staged": "^16.3.3", "markdownlint-cli2": "^0.21.0", "msw": "^2.12.10", "playwright": "^1.58.2", @@ -57,13 +58,13 @@ "stylelint": "^17.4.0", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", - "vitest": "^4.0.18" + "vitest": "^4.1.0" }, "engines": { "node": ">=22.21.1 <23 || >=24" }, "optionalDependencies": { - "electron": "^40.6.1" + "electron": "^41.0.0" } }, "node_modules/@acemir/cssom": { @@ -1148,14 +1149,14 @@ } }, "node_modules/@emnapi/core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", - "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz", + "integrity": "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.1.0", + "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, @@ -1168,9 +1169,9 @@ "optional": true }, "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz", + "integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==", "dev": true, "license": "MIT", "optional": true, @@ -1184,494 +1185,52 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD", - "optional": true - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.8", - "@typescript-eslint/types": "^8.54.0", - "comment-parser": "1.4.5", - "esquery": "^1.7.0", - "jsdoc-type-pratt-parser": "~7.1.1" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - } - }, - "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", - "integrity": "sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } + "optional": true }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], + "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==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], + "node_modules/@emnapi/wasi-threads/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } + "license": "0BSD", + "optional": true }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], + "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==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.54.0", + "comment-parser": "1.4.5", + "esquery": "^1.7.0", + "jsdoc-type-pratt-parser": "~7.1.1" + }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], + "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", + "integrity": "sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=10" } }, "node_modules/@eslint-community/eslint-utils": { @@ -2195,6 +1754,26 @@ "dev": true, "license": "MIT" }, + "node_modules/@oxc-project/runtime": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.115.0.tgz", + "integrity": "sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.115.0.tgz", + "integrity": "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@package-json/types": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/@package-json/types/-/types-0.0.12.tgz", @@ -2460,24 +2039,10 @@ "dev": true, "license": "MIT" }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==", "cpu": [ "arm64" ], @@ -2486,12 +2051,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ==", "cpu": [ "arm64" ], @@ -2500,12 +2068,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.9.tgz", + "integrity": "sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg==", "cpu": [ "x64" ], @@ -2514,26 +2085,15 @@ "optional": true, "os": [ "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.9.tgz", + "integrity": "sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q==", "cpu": [ "x64" ], @@ -2542,84 +2102,36 @@ "optional": true, "os": [ "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], - "dev": true, - "libc": [ - "glibc" ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.9.tgz", + "integrity": "sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ==", "cpu": [ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg==", "cpu": [ "arm64" ], "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" - ], - "dev": true, "libc": [ "glibc" ], @@ -2627,14 +2139,17 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.9.tgz", + "integrity": "sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==", "cpu": [ - "loong64" + "arm64" ], "dev": true, "libc": [ @@ -2644,50 +2159,19 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==", "cpu": [ "ppc64" ], "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], - "dev": true, "libc": [ "glibc" ], @@ -2695,29 +2179,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==", "cpu": [ "s390x" ], @@ -2729,12 +2199,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==", "cpu": [ "x64" ], @@ -2746,12 +2219,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.9.tgz", + "integrity": "sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==", "cpu": [ "x64" ], @@ -2763,26 +2239,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==", "cpu": [ "arm64" ], @@ -2791,54 +2256,66 @@ "optional": true, "os": [ "openharmony" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.9.tgz", + "integrity": "sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g==", "cpu": [ - "arm64" + "wasm32" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", + "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.9.tgz", + "integrity": "sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA==", "cpu": [ - "x64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.9.tgz", + "integrity": "sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ==", "cpu": [ "x64" ], @@ -2847,7 +2324,17 @@ "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.9.tgz", + "integrity": "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==", + "dev": true, + "license": "MIT" }, "node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", @@ -3572,29 +3059,29 @@ ] }, "node_modules/@vitest/coverage-v8": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.18.tgz", - "integrity": "sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.0.tgz", + "integrity": "sha512-nDWulKeik2bL2Va/Wl4x7DLuTKAXa906iRFooIRPR+huHkcvp9QDkPQ2RJdmjOFrqOqvNfoSQLF68deE3xC3CQ==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.0.18", - "ast-v8-to-istanbul": "^0.3.10", + "@vitest/utils": "4.1.0", + "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", - "magicast": "^0.5.1", + "magicast": "^0.5.2", "obug": "^2.1.1", - "std-env": "^3.10.0", + "std-env": "^4.0.0-rc.1", "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.0.18", - "vitest": "4.0.18" + "@vitest/browser": "4.1.0", + "vitest": "4.1.0" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -3603,9 +3090,9 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.6.10", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.10.tgz", - "integrity": "sha512-/cOf+mTu4HBJIYHTETo8/OFCSZv3T2p+KfGnouzKfjK063cWLZp0TzvK7EU5B3eFG7ypUNtw6l+jK+SA+p1g8g==", + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.11.tgz", + "integrity": "sha512-/m7cyD2x/TMJt6SmW6X9ZQWThCROa3AgBXJKVzTDG6MIRQkxBGLlwi4Vi+F5bcKnRKI17b3aeUzOhqBwnsjiHg==", "dev": true, "license": "MIT", "dependencies": { @@ -3630,17 +3117,17 @@ } }, "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz", + "integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==", "dev": true, "license": "MIT", "dependencies": { - "@standard-schema/spec": "^1.0.0", + "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "chai": "^6.2.2", "tinyrainbow": "^3.0.3" }, "funding": { @@ -3648,13 +3135,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz", + "integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.18", + "@vitest/spy": "4.1.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -3663,7 +3150,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "msw": { @@ -3675,9 +3162,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz", + "integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==", "dev": true, "license": "MIT", "dependencies": { @@ -3688,13 +3175,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz", + "integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", + "@vitest/utils": "4.1.0", "pathe": "^2.0.3" }, "funding": { @@ -3702,13 +3189,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz", + "integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.0", + "@vitest/utils": "4.1.0", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -3717,9 +3205,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz", + "integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==", "dev": true, "license": "MIT", "funding": { @@ -3727,15 +3215,15 @@ } }, "node_modules/@vitest/ui": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.0.18.tgz", - "integrity": "sha512-CGJ25bc8fRi8Lod/3GHSvXRKi7nBo3kxh0ApW4yCjmrWmRmlT53B5E08XRSZRliygG0aVNxLrBEqPYdz/KcCtQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.1.0.tgz", + "integrity": "sha512-sTSDtVM1GOevRGsCNhp1mBUHKo9Qlc55+HCreFT4fe99AHxl1QQNXSL3uj4Pkjh5yEuWZIx8E2tVC94nnBZECQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", + "@vitest/utils": "4.1.0", "fflate": "^0.8.2", - "flatted": "^3.3.3", + "flatted": "3.4.0", "pathe": "^2.0.3", "sirv": "^3.0.2", "tinyglobby": "^0.2.15", @@ -3745,17 +3233,18 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.0.18" + "vitest": "4.1.0" } }, "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz", + "integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.0", + "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" }, "funding": { @@ -3991,9 +3480,9 @@ "license": "0BSD" }, "node_modules/ast-v8-to-istanbul": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.12.tgz", - "integrity": "sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", "dev": true, "license": "MIT", "dependencies": { @@ -4688,6 +4177,13 @@ "node": ">= 0.6" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/cookie": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", @@ -5240,6 +4736,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", @@ -5350,9 +4856,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "40.8.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-40.8.0.tgz", - "integrity": "sha512-WoPq0Nr9Yx3g7T6VnJXdwa/rr2+VRyH3a+K+ezfMKBlf6WjxE/LmhMQabKbb6yjm9RbZhJBRcYyoLph421O2mQ==", + "version": "41.0.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-41.0.0.tgz", + "integrity": "sha512-U7QueSj1cFj9QM0Qamgh/MK08662FVK555iMfapqU7mcAmIm4A8bZuZptpjMXrT4JNAMGjgWu9sOeO1+RPCJNw==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5570,9 +5076,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, @@ -5595,48 +5101,6 @@ "license": "MIT", "optional": true }, - "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -6441,9 +5905,9 @@ } }, "node_modules/flatted": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", - "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.0.tgz", + "integrity": "sha512-kC6Bb+ooptOIvWj5B63EQWkF0FEnNjV2ZNkLMLZRDDduIiWeFF4iKnslwhiWxjAdbg4NzTNo6h0qLuvFrcx+Sw==", "license": "ISC" }, "node_modules/follow-redirects": { @@ -6755,7 +6219,6 @@ "version": "17.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -7723,6 +7186,279 @@ "node": ">= 0.8.0" } }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -10161,49 +9897,38 @@ "node": ">=8.0" } }, - "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "node_modules/rolldown": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.9.tgz", + "integrity": "sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@oxc-project/types": "=0.115.0", + "@rolldown/pluginutils": "1.0.0-rc.9" }, "bin": { - "rollup": "dist/bin/rollup" + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" + "@rolldown/binding-android-arm64": "1.0.0-rc.9", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.9", + "@rolldown/binding-darwin-x64": "1.0.0-rc.9", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.9", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.9", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.9", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.9", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.9", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.9", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.9", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.9" } }, "node_modules/router": { @@ -10890,9 +10615,9 @@ } }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, "license": "MIT" }, @@ -11392,9 +11117,9 @@ } }, "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", "engines": { @@ -11470,9 +11195,9 @@ } }, "node_modules/tough-cookie": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", - "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -11607,9 +11332,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", - "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", + "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -11756,17 +11481,17 @@ } }, "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.0.tgz", + "integrity": "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", + "@oxc-project/runtime": "0.115.0", + "lightningcss": "^1.32.0", "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", + "postcss": "^8.5.8", + "rolldown": "1.0.0-rc.9", "tinyglobby": "^0.2.15" }, "bin": { @@ -11783,9 +11508,10 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.0.0-alpha.31", + "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", - "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", @@ -11798,13 +11524,16 @@ "@types/node": { "optional": true }, - "jiti": { + "@vitejs/devtools": { "optional": true }, - "less": { + "esbuild": { + "optional": true + }, + "jiti": { "optional": true }, - "lightningcss": { + "less": { "optional": true }, "sass": { @@ -11846,31 +11575,31 @@ } }, "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", + "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", + "@vitest/expect": "4.1.0", + "@vitest/mocker": "4.1.0", + "@vitest/pretty-format": "4.1.0", + "@vitest/runner": "4.1.0", + "@vitest/snapshot": "4.1.0", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", - "std-env": "^3.10.0", + "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -11886,12 +11615,13 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", + "@vitest/browser-playwright": "4.1.0", + "@vitest/browser-preview": "4.1.0", + "@vitest/browser-webdriverio": "4.1.0", + "@vitest/ui": "4.1.0", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { @@ -11920,6 +11650,9 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, diff --git a/package.json b/package.json index 351b24a934..4c964e6a8a 100644 --- a/package.json +++ b/package.json @@ -96,27 +96,28 @@ "eslint": "^10.0.3", "express": "^5.2.1", "feedme": "^2.0.2", + "globals": "^17.4.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.0", - "node-ical": "^0.25.4", + "node-ical": "^0.25.5", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.31.1", - "undici": "^7.22.0", + "systeminformation": "^5.31.4", + "undici": "^7.23.0", "weathericons": "^2.1.0" }, "devDependencies": { "@eslint/js": "^10.0.1", "@stylistic/eslint-plugin": "^5.10.0", - "@vitest/coverage-v8": "^4.0.18", - "@vitest/eslint-plugin": "^1.6.10", - "@vitest/ui": "^4.0.18", + "@vitest/coverage-v8": "^4.1.0", + "@vitest/eslint-plugin": "^1.6.11", + "@vitest/ui": "^4.1.0", "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.2", "eslint-plugin-jsdoc": "^62.8.0", @@ -125,7 +126,7 @@ "express-basic-auth": "^1.2.1", "husky": "^9.1.7", "jsdom": "^28.1.0", - "lint-staged": "^16.3.0", + "lint-staged": "^16.3.3", "markdownlint-cli2": "^0.21.0", "msw": "^2.12.10", "playwright": "^1.58.2", @@ -134,10 +135,10 @@ "stylelint": "^17.4.0", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", - "vitest": "^4.0.18" + "vitest": "^4.1.0" }, "optionalDependencies": { - "electron": "^40.6.1" + "electron": "^41.0.0" }, "engines": { "node": ">=22.21.1 <23 || >=24" From e1c44a86bb961bbb821de670326e128652c2b68c Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 18 Mar 2026 00:32:55 +0100 Subject: [PATCH 384/418] fix(calendar): make showEnd behavior more consistent across time formats (#4059) Closes #4053 This started as a small fix. After feedback and more debugging, I found more issues and inconsistencies and went a bit down the rabbit hole. The PR is bigger now, but I think the result is better: behavior is more predictable, and the output is more consistent. ## Changes - Multi-day full-day events now show an end date in `relative` and `dateheaders` when `showEnd` is enabled. - With `absolute` + `nextDaysRelative`, full-day events now keep the end date when the start is replaced by TODAY/TOMORROW/etc. - Timed events in `absolute` now also respect `showEndsOnlyWithDuration`. - Tests were expanded and refactored to cover more showEnd cases and keep the setup easier to maintain. - I also refactored parts of the calendar time rendering to reduce duplicate logic. ## Before before ## After after --- defaultmodules/calendar/calendar.js | 348 +++++++++++------ .../calendar/calendarShowEndConfigs.js | 361 ++++++++++++++++++ ...multiple_days_non_repeating_display_end.js | 33 -- ...tiple_days_non_repeating_no_display_end.js | 34 -- tests/electron/modules/calendar_spec.js | 116 +++++- ...nt_with_time_over_multiple_days_yearly.ics | 18 + .../mocks/event_with_time_same_day_yearly.ics | 18 + 7 files changed, 735 insertions(+), 193 deletions(-) create mode 100644 tests/configs/modules/calendar/calendarShowEndConfigs.js delete mode 100644 tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js delete mode 100644 tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js create mode 100644 tests/mocks/event_with_time_over_multiple_days_yearly.ics create mode 100644 tests/mocks/event_with_time_same_day_yearly.ics diff --git a/defaultmodules/calendar/calendar.js b/defaultmodules/calendar/calendar.js index 0d8575c810..cfc625431a 100644 --- a/defaultmodules/calendar/calendar.js +++ b/defaultmodules/calendar/calendar.js @@ -384,32 +384,7 @@ Module.register("calendar", { } if (this.config.timeFormat === "dateheaders") { - if (this.config.flipDateHeaderTitle) eventWrapper.appendChild(titleWrapper); - - if (event.fullDayEvent) { - titleWrapper.colSpan = "2"; - titleWrapper.classList.add("align-left"); - } else { - const timeWrapper = document.createElement("td"); - timeWrapper.className = `time light ${this.config.flipDateHeaderTitle ? "align-right " : "align-left "}${this.timeClassForUrl(event.url)}`; - timeWrapper.style.paddingLeft = "2px"; - timeWrapper.style.textAlign = this.config.flipDateHeaderTitle ? "right" : "left"; - timeWrapper.innerHTML = eventStartDateMoment.format("LT"); - - // Add endDate to dataheaders if showEnd is enabled - if (this.config.showEnd) { - if (this.config.showEndsOnlyWithDuration && event.startDate === event.endDate) { - // no duration here, don't display end - } else { - timeWrapper.innerHTML += ` - ${CalendarUtils.capFirst(eventEndDateMoment.format("LT"))}`; - } - } - - eventWrapper.appendChild(timeWrapper); - - if (!this.config.flipDateHeaderTitle) titleWrapper.classList.add("align-right"); - } - if (!this.config.flipDateHeaderTitle) eventWrapper.appendChild(titleWrapper); + this.renderDateHeadersEventTime(eventWrapper, titleWrapper, event, eventStartDateMoment, eventEndDateMoment); } else { const timeWrapper = document.createElement("td"); @@ -417,106 +392,11 @@ Module.register("calendar", { const now = moment(); if (this.config.timeFormat === "absolute") { - // Use dateFormat - timeWrapper.innerHTML = CalendarUtils.capFirst(eventStartDateMoment.format(this.config.dateFormat)); - // Add end time if showEnd - if (this.config.showEnd) { - // and has a duration - if (event.startDate !== event.endDate) { - timeWrapper.innerHTML += "-"; - timeWrapper.innerHTML += CalendarUtils.capFirst(eventEndDateMoment.format(this.config.dateEndFormat)); - } - } - - // For full day events we use the fullDayEventDateFormat - if (event.fullDayEvent) { - //subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day - eventEndDateMoment.subtract(1, "second"); - timeWrapper.innerHTML = CalendarUtils.capFirst(eventStartDateMoment.format(this.config.fullDayEventDateFormat)); - // only show end if requested and allowed and the dates are different - if (this.config.showEnd && !this.config.showEndsOnlyWithDuration && !eventStartDateMoment.isSame(eventEndDateMoment, "d")) { - timeWrapper.innerHTML += "-"; - timeWrapper.innerHTML += CalendarUtils.capFirst(eventEndDateMoment.format(this.config.fullDayEventDateFormat)); - } else if (!eventStartDateMoment.isSame(eventEndDateMoment, "d") && eventStartDateMoment.isBefore(now)) { - timeWrapper.innerHTML = CalendarUtils.capFirst(now.format(this.config.fullDayEventDateFormat)); - } - } else if (this.config.getRelative > 0 && eventStartDateMoment.isBefore(now)) { - // Ongoing and getRelative is set - timeWrapper.innerHTML = CalendarUtils.capFirst( - this.translate("RUNNING", { - fallback: `${this.translate("RUNNING")} {timeUntilEnd}`, - timeUntilEnd: eventEndDateMoment.fromNow(true) - }) - ); - } else if (this.config.urgency > 0 && eventStartDateMoment.diff(now, "d") < this.config.urgency) { - // Within urgency days - timeWrapper.innerHTML = CalendarUtils.capFirst(eventStartDateMoment.fromNow()); - } - if (event.fullDayEvent && this.config.nextDaysRelative) { - // Full days events within the next two days - if (event.today) { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TODAY")); - } else if (event.yesterday) { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("YESTERDAY")); - } else if (event.tomorrow) { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TOMORROW")); - } else if (event.dayAfterTomorrow) { - if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW")); - } - } - } + timeWrapper.innerHTML = this.buildAbsoluteTimeText(event, eventStartDateMoment, eventEndDateMoment, now); } else { - // Show relative times - if (eventStartDateMoment.isSameOrAfter(now) || (event.fullDayEvent && eventEndDateMoment.diff(now, "days") === 0)) { - // Use relative time - if (!this.config.hideTime && !event.fullDayEvent) { - Log.debug("[calendar] event not hidden and not fullday"); - timeWrapper.innerHTML = `${CalendarUtils.capFirst(eventStartDateMoment.calendar(null, { sameElse: this.config.dateFormat }))}`; - } else { - Log.debug("[calendar] event full day or hidden"); - timeWrapper.innerHTML = `${CalendarUtils.capFirst( - eventStartDateMoment.calendar(null, { - sameDay: this.config.showTimeToday ? "LT" : `[${this.translate("TODAY")}]`, - nextDay: `[${this.translate("TOMORROW")}]`, - nextWeek: "dddd", - sameElse: event.fullDayEvent ? this.config.fullDayEventDateFormat : this.config.dateFormat - }) - )}`; - } - if (event.fullDayEvent) { - // Full days events within the next two days - if (event.today || (event.fullDayEvent && eventEndDateMoment.diff(now, "days") === 0)) { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TODAY")); - } else if (event.dayBeforeYesterday) { - if (this.translate("DAYBEFOREYESTERDAY") !== "DAYBEFOREYESTERDAY") { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYBEFOREYESTERDAY")); - } - } else if (event.yesterday) { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("YESTERDAY")); - } else if (event.tomorrow) { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TOMORROW")); - } else if (event.dayAfterTomorrow) { - if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { - timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW")); - } - } - Log.info("[calendar] event fullday"); - } else if (eventStartDateMoment.diff(now, "h") < this.config.getRelative) { - Log.info("[calendar] not full day but within getRelative size"); - // If event is within getRelative hours, display 'in xxx' time format or moment.fromNow() - timeWrapper.innerHTML = `${CalendarUtils.capFirst(eventStartDateMoment.fromNow())}`; - } - } else { - // Ongoing event - timeWrapper.innerHTML = CalendarUtils.capFirst( - this.translate("RUNNING", { - fallback: `${this.translate("RUNNING")} {timeUntilEnd}`, - timeUntilEnd: eventEndDateMoment.fromNow(true) - }) - ); - } + timeWrapper.innerHTML = this.buildRelativeTimeText(event, eventStartDateMoment, eventEndDateMoment, now); } + timeWrapper.className = `time light ${this.timeClassForUrl(event.url)}`; eventWrapper.appendChild(timeWrapper); } @@ -793,6 +673,226 @@ Module.register("calendar", { ); }, + createDateHeadersTimeWrapper (url) { + const timeWrapper = document.createElement("td"); + timeWrapper.className = `time light ${this.config.flipDateHeaderTitle ? "align-right " : "align-left "}${this.timeClassForUrl(url)}`; + timeWrapper.style.paddingLeft = "2px"; + timeWrapper.style.textAlign = this.config.flipDateHeaderTitle ? "right" : "left"; + return timeWrapper; + }, + + hasEventDuration (event) { + return event.startDate !== event.endDate; + }, + + shouldShowDateHeadersTimedEnd (event) { + return this.config.showEnd && (!this.config.showEndsOnlyWithDuration || this.hasEventDuration(event)); + }, + + shouldShowRelativeTimedEnd (event) { + return !this.config.hideTime && this.config.showEnd && (!this.config.showEndsOnlyWithDuration || this.hasEventDuration(event)); + }, + + getAdjustedFullDayEndMoment (endMoment) { + return endMoment.clone().subtract(1, "second"); + }, + + renderDateHeadersEventTime (eventWrapper, titleWrapper, event, eventStartDateMoment, eventEndDateMoment) { + if (this.config.flipDateHeaderTitle) eventWrapper.appendChild(titleWrapper); + + if (event.fullDayEvent) { + const adjustedEndMoment = this.getAdjustedFullDayEndMoment(eventEndDateMoment); + if (this.config.showEnd && !this.config.showEndsOnlyWithDuration && !eventStartDateMoment.isSame(adjustedEndMoment, "d")) { + const timeWrapper = this.createDateHeadersTimeWrapper(event.url); + timeWrapper.innerHTML = `-${CalendarUtils.capFirst(adjustedEndMoment.format(this.config.fullDayEventDateFormat))}`; + eventWrapper.appendChild(timeWrapper); + if (!this.config.flipDateHeaderTitle) titleWrapper.classList.add("align-right"); + } else { + titleWrapper.colSpan = "2"; + titleWrapper.classList.add("align-left"); + } + } else { + const timeWrapper = this.createDateHeadersTimeWrapper(event.url); + timeWrapper.innerHTML = eventStartDateMoment.format("LT"); + + // In dateheaders mode, keep the end as time-only to avoid redundant date info under a date header. + if (this.shouldShowDateHeadersTimedEnd(event)) { + timeWrapper.innerHTML += `-${CalendarUtils.capFirst(eventEndDateMoment.format("LT"))}`; + } + + eventWrapper.appendChild(timeWrapper); + if (!this.config.flipDateHeaderTitle) titleWrapper.classList.add("align-right"); + } + + if (!this.config.flipDateHeaderTitle) eventWrapper.appendChild(titleWrapper); + }, + + buildAbsoluteTimeText (event, eventStartDateMoment, eventEndDateMoment, now) { + let timeText = CalendarUtils.capFirst(eventStartDateMoment.format(this.config.dateFormat)); + + if (this.config.showEnd && (!this.config.showEndsOnlyWithDuration || this.hasEventDuration(event))) { + const sameDay = this.isSameDay(eventStartDateMoment, eventEndDateMoment); + if (sameDay && !this.dateFormatIncludesTime()) { + timeText += `, ${eventStartDateMoment.format("LT")}`; + } + timeText += `-${this.formatTimedEventEnd(eventStartDateMoment, eventEndDateMoment)}`; + } + + if (event.fullDayEvent) { + const adjustedEndMoment = this.getAdjustedFullDayEndMoment(eventEndDateMoment); + timeText = CalendarUtils.capFirst(eventStartDateMoment.format(this.config.fullDayEventDateFormat)); + + if (this.config.showEnd && !this.config.showEndsOnlyWithDuration && !eventStartDateMoment.isSame(adjustedEndMoment, "d")) { + timeText += `-${CalendarUtils.capFirst(adjustedEndMoment.format(this.config.fullDayEventDateFormat))}`; + } else if (!eventStartDateMoment.isSame(adjustedEndMoment, "d") && eventStartDateMoment.isBefore(now)) { + timeText = CalendarUtils.capFirst(now.format(this.config.fullDayEventDateFormat)); + } + + if (this.config.nextDaysRelative) { + let relativeLabel = false; + if (event.today) { + timeText = CalendarUtils.capFirst(this.translate("TODAY")); + relativeLabel = true; + } else if (event.yesterday) { + timeText = CalendarUtils.capFirst(this.translate("YESTERDAY")); + relativeLabel = true; + } else if (event.tomorrow) { + timeText = CalendarUtils.capFirst(this.translate("TOMORROW")); + relativeLabel = true; + } else if (event.dayAfterTomorrow && this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { + timeText = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW")); + relativeLabel = true; + } + + if (relativeLabel && this.config.showEnd && !this.config.showEndsOnlyWithDuration && !eventStartDateMoment.isSame(adjustedEndMoment, "d")) { + timeText += `-${CalendarUtils.capFirst(adjustedEndMoment.format(this.config.fullDayEventDateFormat))}`; + } + } + + return timeText; + } + + if (this.config.getRelative > 0 && eventStartDateMoment.isBefore(now)) { + return CalendarUtils.capFirst( + this.translate("RUNNING", { + fallback: `${this.translate("RUNNING")} {timeUntilEnd}`, + timeUntilEnd: eventEndDateMoment.fromNow(true) + }) + ); + } + + if (this.config.urgency > 0 && eventStartDateMoment.diff(now, "d") < this.config.urgency) { + return CalendarUtils.capFirst(eventStartDateMoment.fromNow()); + } + + return timeText; + }, + + buildRelativeTimeText (event, eventStartDateMoment, eventEndDateMoment, now) { + if (eventStartDateMoment.isSameOrAfter(now) || (event.fullDayEvent && eventEndDateMoment.diff(now, "days") === 0)) { + let timeText; + + if (!this.config.hideTime && !event.fullDayEvent) { + Log.debug("[calendar] event not hidden and not fullday"); + timeText = `${CalendarUtils.capFirst(eventStartDateMoment.calendar(null, { sameElse: this.config.dateFormat }))}`; + } else { + Log.debug("[calendar] event full day or hidden"); + timeText = `${CalendarUtils.capFirst( + eventStartDateMoment.calendar(null, { + sameDay: this.config.showTimeToday ? "LT" : `[${this.translate("TODAY")}]`, + nextDay: `[${this.translate("TOMORROW")}]`, + nextWeek: "dddd", + sameElse: event.fullDayEvent ? this.config.fullDayEventDateFormat : this.config.dateFormat + }) + )}`; + } + + if (event.fullDayEvent) { + if (event.today || (event.fullDayEvent && eventEndDateMoment.diff(now, "days") === 0)) { + timeText = CalendarUtils.capFirst(this.translate("TODAY")); + } else if (event.dayBeforeYesterday) { + if (this.translate("DAYBEFOREYESTERDAY") !== "DAYBEFOREYESTERDAY") { + timeText = CalendarUtils.capFirst(this.translate("DAYBEFOREYESTERDAY")); + } + } else if (event.yesterday) { + timeText = CalendarUtils.capFirst(this.translate("YESTERDAY")); + } else if (event.tomorrow) { + timeText = CalendarUtils.capFirst(this.translate("TOMORROW")); + } else if (event.dayAfterTomorrow) { + if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") { + timeText = CalendarUtils.capFirst(this.translate("DAYAFTERTOMORROW")); + } + } + + if (this.config.showEnd && !this.config.showEndsOnlyWithDuration) { + const adjustedEndMoment = this.getAdjustedFullDayEndMoment(eventEndDateMoment); + if (!eventStartDateMoment.isSame(adjustedEndMoment, "d")) { + timeText += `-${CalendarUtils.capFirst(adjustedEndMoment.format(this.config.fullDayEventDateFormat))}`; + } + } + + Log.info("[calendar] event fullday"); + } else if (eventStartDateMoment.diff(now, "h") < this.config.getRelative) { + Log.info("[calendar] not full day but within getRelative size"); + timeText = `${CalendarUtils.capFirst(eventStartDateMoment.fromNow())}`; + } else if (this.shouldShowRelativeTimedEnd(event)) { + if (this.isSameDay(eventStartDateMoment, eventEndDateMoment)) { + const sameElseFormat = this.dateFormatIncludesTime() ? this.config.dateFormat : `${this.config.dateFormat}, LT`; + timeText = CalendarUtils.capFirst( + eventStartDateMoment.calendar(null, { sameElse: sameElseFormat }) + ); + } + timeText += `-${this.formatTimedEventEnd(eventStartDateMoment, eventEndDateMoment)}`; + } + + return timeText; + } + + return CalendarUtils.capFirst( + this.translate("RUNNING", { + fallback: `${this.translate("RUNNING")} {timeUntilEnd}`, + timeUntilEnd: eventEndDateMoment.fromNow(true) + }) + ); + }, + + /** + * Determines whether two moments are on the same day. + * @param {moment.Moment} startMoment The start moment. + * @param {moment.Moment} endMoment The end moment. + * @returns {boolean} True when both moments share the same calendar day. + */ + isSameDay (startMoment, endMoment) { + return startMoment.isSame(endMoment, "d"); + }, + + /** + * Checks whether the configured dateFormat already contains time components. + * @returns {boolean} True when dateFormat includes time tokens. + */ + dateFormatIncludesTime () { + const dateFormatWithoutLiterals = this.config.dateFormat.replace(/\[[^\]]*\]/g, ""); + const localeDateFormat = moment.localeData(); + const expandedDateFormat = dateFormatWithoutLiterals.replace( + /LTS|LT|LLLL|LLL|LL|L|llll|lll|ll|l/g, + (token) => localeDateFormat.longDateFormat(token) || token + ); + const expandedDateFormatWithoutLiterals = expandedDateFormat.replace(/\[[^\]]*\]/g, ""); + return (/(H{1,2}|h{1,2}|k{1,2}|m{1,2}|s{1,2}|a|A)/).test(expandedDateFormatWithoutLiterals); + }, + + /** + * Formats a timed event end value. + * Uses time-only for same-day events and dateEndFormat for multi-day events. + * @param {moment.Moment} startMoment The event start moment. + * @param {moment.Moment} endMoment The event end moment. + * @returns {string} The formatted end value. + */ + formatTimedEventEnd (startMoment, endMoment) { + const endFormat = this.isSameDay(startMoment, endMoment) ? "LT" : this.config.dateEndFormat; + return CalendarUtils.capFirst(endMoment.format(endFormat)); + }, + /** * Retrieves the symbolClass for a specific calendar url. * @param {string} url The calendar url diff --git a/tests/configs/modules/calendar/calendarShowEndConfigs.js b/tests/configs/modules/calendar/calendarShowEndConfigs.js new file mode 100644 index 0000000000..129ad97388 --- /dev/null +++ b/tests/configs/modules/calendar/calendarShowEndConfigs.js @@ -0,0 +1,361 @@ +const calendarShowEndConfigs = { + event_with_time_over_multiple_days_non_repeating_display_end: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics" + } + ] + } + } + ] + }, + event_with_time_over_multiple_days_non_repeating_display_end_dateheaders: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "dateheaders", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_yearly.ics" + } + ] + } + } + ] + }, + event_with_time_over_multiple_days_non_repeating_display_end_relative: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "relative", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_yearly.ics" + } + ] + } + } + ] + }, + event_with_time_over_multiple_days_non_repeating_no_display_end: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + showEndsOnlyWithDuration: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics" + } + ] + } + } + ] + }, + event_with_time_same_day_yearly_display_end_absolute: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_same_day_yearly.ics" + } + ] + } + } + ] + }, + event_with_time_same_day_yearly_display_end_absolute_dateformat_lll: { + address: "0.0.0.0", + ipWhitelist: [], + language: "en", + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "LLL", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_same_day_yearly.ics" + } + ] + } + } + ] + }, + event_with_time_same_day_yearly_display_end_absolute_dateformat_with_time: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM, HH:mm", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_same_day_yearly.ics" + } + ] + } + } + ] + }, + event_with_time_same_day_yearly_display_end_dateheaders: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "dateheaders", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_same_day_yearly.ics" + } + ] + } + } + ] + }, + event_with_time_same_day_yearly_display_end_relative: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "relative", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_same_day_yearly.ics" + } + ] + } + } + ] + }, + event_with_time_same_day_yearly_display_end_relative_hide_time: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + dateFormat: "Do.MMM", + dateEndFormat: "Do.MMM, HH:mm", + fullDayEventDateFormat: "Do.MMM", + timeFormat: "relative", + getRelative: 0, + hideTime: true, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/event_with_time_same_day_yearly.ics" + } + ] + } + } + ] + }, + fullday_multiday_showend_dateheaders: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + fullDayEventDateFormat: "Do.MMM", + timeFormat: "dateheaders", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics" + } + ] + } + } + ] + }, + fullday_multiday_showend_nextdaysrelative: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + fullDayEventDateFormat: "Do.MMM", + timeFormat: "absolute", + getRelative: 0, + showEnd: true, + nextDaysRelative: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics" + } + ] + } + } + ] + }, + fullday_multiday_showend_relative: { + address: "0.0.0.0", + ipWhitelist: [], + timeFormat: 24, + modules: [ + { + module: "calendar", + position: "bottom_bar", + config: { + fade: false, + urgency: 0, + fullDayEventDateFormat: "Do.MMM", + timeFormat: "relative", + getRelative: 0, + showEnd: true, + calendars: [ + { + maximumEntries: 100, + url: "http://localhost:8080/tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics" + } + ] + } + } + ] + } +}; + +const defaultScenario = "event_with_time_over_multiple_days_non_repeating_display_end"; +const selectedScenario = process.env.MM_CALENDAR_SHOWEND_SCENARIO || defaultScenario; +const config = calendarShowEndConfigs[selectedScenario]; + +if (!config) { + throw new Error(`Unknown MM_CALENDAR_SHOWEND_SCENARIO: ${selectedScenario}`); +} + +module.exports = config; diff --git a/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js b/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js deleted file mode 100644 index 95989648ca..0000000000 --- a/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js +++ /dev/null @@ -1,33 +0,0 @@ -let config = { - address: "0.0.0.0", - ipWhitelist: [], - - timeFormat: 24, - modules: [ - { - module: "calendar", - position: "bottom_bar", - config: { - fade: false, - urgency: 0, - dateFormat: "Do.MMM, HH:mm", - dateEndFormat: "Do.MMM, HH:mm", - fullDayEventDateFormat: "Do.MMM", - timeFormat: "absolute", - getRelative: 0, - showEnd: true, - calendars: [ - { - maximumEntries: 100, - url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics" - } - ] - } - } - ] -}; - -/*************** DO NOT EDIT THE LINE BELOW ***************/ -if (typeof module !== "undefined") { - module.exports = config; -} diff --git a/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js b/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js deleted file mode 100644 index ef60df4c94..0000000000 --- a/tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js +++ /dev/null @@ -1,34 +0,0 @@ -let config = { - address: "0.0.0.0", - ipWhitelist: [], - - timeFormat: 24, - modules: [ - { - module: "calendar", - position: "bottom_bar", - config: { - fade: false, - urgency: 0, - dateFormat: "Do.MMM, HH:mm", - dateEndFormat: "Do.MMM, HH:mm", - fullDayEventDateFormat: "Do.MMM", - timeFormat: "absolute", - getRelative: 0, - showEnd: true, - showEndsOnlyWithDuration: true, - calendars: [ - { - maximumEntries: 100, - url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics" - } - ] - } - } - ] -}; - -/*************** DO NOT EDIT THE LINE BELOW ***************/ -if (typeof module !== "undefined") { - module.exports = config; -} diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 2a9845ae18..1be60c4d8f 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -50,8 +50,29 @@ describe("Calendar module", () => { return true; }; + const defaultCalendarNow = "08 Oct 2024 12:30:00 GMT-07:00"; + const defaultCalendarTimeZone = "America/Chicago"; + const showEndConfigPath = "tests/configs/modules/calendar/calendarShowEndConfigs.js"; + + const startCalendarShowEndScenario = async (scenario, now = defaultCalendarNow, timeZone = defaultCalendarTimeZone) => { + process.env.MM_CALENDAR_SHOWEND_SCENARIO = scenario; + await helpers.startApplication(showEndConfigPath, now, [], timeZone); + }; + + const expectFirstEventTimeCell = async ({ scenario, expectedTime, now = defaultCalendarNow, timeZone = defaultCalendarTimeZone }) => { + await startCalendarShowEndScenario(scenario, now, timeZone); + await expect(doTestTableContent(".calendar .event", ".time", expectedTime, first)).resolves.toBe(true); + }; + + const getFirstEventTimeText = async () => { + const timeCell = global.page.locator(".calendar .event .time").locator(`nth=${first}`); + await timeCell.waitFor({ state: "visible" }); + return (await timeCell.textContent()) || ""; + }; + afterEach(async () => { await helpers.stopApplication(); + delete process.env.MM_CALENDAR_SHOWEND_SCENARIO; }); describe("Test css classes", () => { @@ -283,7 +304,7 @@ describe("Calendar module", () => { describe("one event no end display", () => { it("don't display end", async () => { - await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Chicago"); + await startCalendarShowEndScenario("event_with_time_over_multiple_days_non_repeating_no_display_end"); // just await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 20:00", first)).resolves.toBe(true); }); @@ -291,12 +312,77 @@ describe("Calendar module", () => { describe("display end display end", () => { it("display end", async () => { - await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Chicago"); + await startCalendarShowEndScenario("event_with_time_over_multiple_days_non_repeating_display_end"); // just await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 20:00-26th.Oct, 06:00", first)).resolves.toBe(true); }); }); + describe("showEnd for timed multi-day events", () => { + const timedMultiDayCases = [ + { + name: "relative timeFormat shows start and end for timed multi-day events", + scenario: "event_with_time_over_multiple_days_non_repeating_display_end_relative", + expectedTime: "25th.Oct, 20:00-26th.Oct, 06:00" + }, + { + name: "dateheaders timeFormat shows end for timed multi-day events", + scenario: "event_with_time_over_multiple_days_non_repeating_display_end_dateheaders", + expectedTime: "20:00-06:00" + } + ]; + + it.each(timedMultiDayCases)("$name", async (testCase) => { + expect.hasAssertions(); + await expectFirstEventTimeCell(testCase); + }); + }); + + describe("showEnd for timed same-day events", () => { + const timedSameDaySimpleCases = [ + { + name: "absolute timeFormat shows start and end time without repeating date", + scenario: "event_with_time_same_day_yearly_display_end_absolute", + expectedTime: "25th.Oct, 20:00-22:00" + }, + { + name: "absolute timeFormat with time in dateFormat does not duplicate start time", + scenario: "event_with_time_same_day_yearly_display_end_absolute_dateformat_with_time", + expectedTime: "25th.Oct, 20:00-22:00" + }, + { + name: "relative timeFormat shows start and end time without repeating date", + scenario: "event_with_time_same_day_yearly_display_end_relative", + expectedTime: "25th.Oct, 20:00-22:00" + }, + { + name: "dateheaders timeFormat shows start and end time only", + scenario: "event_with_time_same_day_yearly_display_end_dateheaders", + expectedTime: "20:00-22:00" + } + ]; + + it.each(timedSameDaySimpleCases)("$name", async (testCase) => { + expect.hasAssertions(); + await expectFirstEventTimeCell(testCase); + }); + + it("absolute timeFormat with dateFormat LLL does not duplicate start time", async () => { + await startCalendarShowEndScenario("event_with_time_same_day_yearly_display_end_absolute_dateformat_lll"); + const timeText = await getFirstEventTimeText(); + const timeTokens = timeText.match(/\d{1,2}:\d{2}(?:\s?[AP]M)?/gi) || []; + expect(timeTokens).toHaveLength(2); + expect(timeText).toContain("-"); + }); + + it("relative timeFormat with hideTime does not show start or end times", async () => { + await startCalendarShowEndScenario("event_with_time_same_day_yearly_display_end_relative_hide_time"); + const timeText = await getFirstEventTimeText(); + expect(timeText).toContain("25th.Oct"); + expect(timeText.match(/\d{1,2}:\d{2}(?:\s?[AP]M)?/gi) || []).toHaveLength(0); + }); + }); + describe("count and check symbols", () => { it("in array", async () => { await helpers.startApplication("tests/configs/modules/calendar/symboltest.js", "08 Oct 2024 12:30:00 GMT-07:00", [], "America/Chicago"); @@ -314,4 +400,30 @@ describe("Calendar module", () => { await expect(doTestTableContent(".testNotification", ".elementCount", "12", first)).resolves.toBe(true); }); }); + + describe("showEnd for multi-day full-day events", () => { + const fullDayShowEndCases = [ + { + name: "relative timeFormat shows start and end date", + scenario: "fullday_multiday_showend_relative", + expectedTime: "25th.Oct-30th.Oct" + }, + { + name: "dateheaders timeFormat shows end date in time cell", + scenario: "fullday_multiday_showend_dateheaders", + expectedTime: "-30th.Oct" + }, + { + name: "absolute timeFormat with nextDaysRelative shows relative label and end date", + scenario: "fullday_multiday_showend_nextdaysrelative", + expectedTime: "Tomorrow-30th.Oct", + now: "24 Oct 2024 12:30:00 GMT-07:00" + } + ]; + + it.each(fullDayShowEndCases)("$name", async (testCase) => { + expect.hasAssertions(); + await expectFirstEventTimeCell(testCase); + }); + }); }); diff --git a/tests/mocks/event_with_time_over_multiple_days_yearly.ics b/tests/mocks/event_with_time_over_multiple_days_yearly.ics new file mode 100644 index 0000000000..00f65b2f1d --- /dev/null +++ b/tests/mocks/event_with_time_over_multiple_days_yearly.ics @@ -0,0 +1,18 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//MagicMirror Test//timed-multiday-yearly//EN +CALSCALE:GREGORIAN +BEGIN:VEVENT +DTSTART:20241026T010000Z +DTEND:20241026T110000Z +DTSTAMP:20241024T153358Z +UID:4maud6s79m41a99pj2g7j5km0a@google.com +CREATED:20241024T153313Z +LAST-MODIFIED:20241024T153330Z +SEQUENCE:0 +STATUS:CONFIRMED +RRULE:FREQ=YEARLY +SUMMARY:Sleep over at Bobs +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR diff --git a/tests/mocks/event_with_time_same_day_yearly.ics b/tests/mocks/event_with_time_same_day_yearly.ics new file mode 100644 index 0000000000..4e0bb85185 --- /dev/null +++ b/tests/mocks/event_with_time_same_day_yearly.ics @@ -0,0 +1,18 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//MagicMirror Test//timed-same-day-yearly//EN +CALSCALE:GREGORIAN +BEGIN:VEVENT +DTSTART:20241025T200000 +DTEND:20241025T220000 +DTSTAMP:20241024T153358Z +UID:timed-same-day-yearly@magicmirror +CREATED:20241024T153313Z +LAST-MODIFIED:20241024T153330Z +SEQUENCE:0 +STATUS:CONFIRMED +RRULE:FREQ=YEARLY +SUMMARY:Same day timed event +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR From ee261939bd6c78436d3cc4212dd5d02c52323765 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 22 Mar 2026 17:31:47 +0100 Subject: [PATCH 385/418] fix(weather): fix weathergov forecast day labels off by one (#4065) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While looking at all weather providers for #4063, I noticed another unrelated bug: The weathergov forecast has been off by one day. This has been since its first commit in 2019 and was not caused by the recent weather refactor. The provider built the days array correctly, but then threw away the first entry (`slice(1)`) because it was considered "incomplete". The problem: the template uses index position to decide what to label "Today" and "Tomorrow" — so dropping today made Monday show up as "Today", Tuesday as "Tomorrow", and one day disappeared entirely. The fix is a one-liner: remove `slice(1)`. Today's entry now shows min/max from the remaining hours of the day, which is the right behaviour anyway. In my understanding it's not a problem at all that the first day is incomplete. ## Before Notice in the screenshot that it is Sunday. So after today and tomorrow, Tuesday should come next, but it says **Wednesday** instead. Ekrankopio de 2026-03-22 14-37-55 ## After Ekrankopio de 2026-03-22 14-38-34 --- .../weather/providers/weathergov.js | 2 +- .../weather/providers/weathergov_spec.js | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/defaultmodules/weather/providers/weathergov.js b/defaultmodules/weather/providers/weathergov.js index 691b81045d..5abd314683 100644 --- a/defaultmodules/weather/providers/weathergov.js +++ b/defaultmodules/weather/providers/weathergov.js @@ -349,7 +349,7 @@ class WeatherGovProvider { days.push(weather); } - return days.slice(1); // Skip first incomplete day + return days; } #generateWeatherObjectsFromHourly (forecasts) { diff --git a/tests/unit/modules/default/weather/providers/weathergov_spec.js b/tests/unit/modules/default/weather/providers/weathergov_spec.js index 81a7edd94f..6326a7fa4b 100644 --- a/tests/unit/modules/default/weather/providers/weathergov_spec.js +++ b/tests/unit/modules/default/weather/providers/weathergov_spec.js @@ -241,6 +241,36 @@ describe("WeatherGovProvider", () => { expect(day).toHaveProperty("weatherType"); expect(day).toHaveProperty("precipitationProbability"); }); + + it("should not skip the first day of forecast data", async () => { + const provider = new WeatherGovProvider({ + lat: 40.71, + lon: -74.0, + type: "forecast" + }); + + const dataPromise = new Promise((resolve) => { + provider.setCallbacks(resolve, vi.fn()); + }); + + server.use( + http.get(WEATHERGOV_FORECAST_URL, () => { + return HttpResponse.json(forecastData); + }) + ); + + await provider.initialize(); + provider.start(); + + const result = await dataPromise; + + // Mock data starts on 2026-02-06 ("This Afternoon"). + // Before the fix, slice(1) dropped today, so result[0] would have been 2026-02-07. + const firstDate = result[0].date; + expect(firstDate.getFullYear()).toBe(2026); + expect(firstDate.getMonth()).toBe(1); // February (0-indexed) + expect(firstDate.getDate()).toBe(6); + }); }); describe("Hourly Parsing", () => { From de78190ed7d1f852c71163fc8e475666ee3ec692 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 23 Mar 2026 09:07:39 +0100 Subject: [PATCH 386/418] fix(weather): fix openmeteo forecast stuck in the past (#4064) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The URL was built once at startup with a hardcoded start_date. Since HTTPFetcher reuses the same URL, the forecast never advanced past day one. Use forecast_days instead — Open-Meteo resolves it relative to today on every request. Other providers are not affected as they don't use dates in their URLs. Fixes #4063 --- defaultmodules/weather/providers/openmeteo.js | 12 +--- .../weather/providers/openmeteo_spec.js | 59 +++++++++++-------- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/defaultmodules/weather/providers/openmeteo.js b/defaultmodules/weather/providers/openmeteo.js index b85418fa6f..7cc5f43995 100644 --- a/defaultmodules/weather/providers/openmeteo.js +++ b/defaultmodules/weather/providers/openmeteo.js @@ -1,5 +1,4 @@ const Log = require("logger"); -const { getDateString } = require("../provider-utils"); const HTTPFetcher = require("#http_fetcher"); // https://www.bigdatacloud.com/docs/api/free-reverse-geocode-to-city-api @@ -262,22 +261,15 @@ class OpenMeteoProvider { precipitation_unit: "mm" }; - const now = new Date(); - const startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate()); - const endDate = new Date(startDate); - endDate.setDate(endDate.getDate() + Math.max(0, Math.min(7, maxNumberOfDays))); - - params.start_date = getDateString(startDate); - switch (this.config.type) { case "hourly": case "daily": case "forecast": - params.end_date = getDateString(endDate); + params.forecast_days = maxNumberOfDays + 1; // Open-Meteo counts today as day 1, so maxNumberOfDays=5 needs forecast_days=6 break; case "current": params.current_weather = true; - params.end_date = params.start_date; + params.forecast_days = 1; break; default: return ""; diff --git a/tests/unit/modules/default/weather/providers/openmeteo_spec.js b/tests/unit/modules/default/weather/providers/openmeteo_spec.js index a46bba9aee..0377a99013 100644 --- a/tests/unit/modules/default/weather/providers/openmeteo_spec.js +++ b/tests/unit/modules/default/weather/providers/openmeteo_spec.js @@ -80,32 +80,39 @@ describe("OpenMeteoProvider", () => { expect(provider.locationName).toBe("Munich, BY"); }); - it("should build query dates from local date, not ISO UTC conversion", async () => { - const toISOStringSpy = vi.spyOn(Date.prototype, "toISOString").mockReturnValue("2000-01-01T00:00:00.000Z"); - try { - const provider = new OpenMeteoProvider({ - lat: 48.14, - lon: 11.58, - type: "current" - }); - - await provider.initialize(); - - const url = new URL(provider.fetcher.url); - const params = url.searchParams; - const now = new Date(); - const expectedToday = [ - now.getFullYear(), - String(now.getMonth() + 1).padStart(2, "0"), - String(now.getDate()).padStart(2, "0") - ].join("-"); - - expect(params.get("start_date")).toBe(expectedToday); - expect(params.get("end_date")).toBe(expectedToday); - expect(params.get("start_date")).not.toBe("2000-01-01"); - } finally { - toISOStringSpy.mockRestore(); - } + it("should use forecast_days instead of static start_date/end_date", async () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "current" + }); + + await provider.initialize(); + + const url = new URL(provider.fetcher.url); + const params = url.searchParams; + + expect(params.get("forecast_days")).toBe("1"); + expect(params.has("start_date")).toBe(false); + expect(params.has("end_date")).toBe(false); + }); + + it("should set forecast_days based on maxNumberOfDays for forecast type", async () => { + const provider = new OpenMeteoProvider({ + lat: 48.14, + lon: 11.58, + type: "forecast", + maxNumberOfDays: 5 + }); + + await provider.initialize(); + + const url = new URL(provider.fetcher.url); + const params = url.searchParams; + + expect(params.get("forecast_days")).toBe("6"); // 5 days + 1 + expect(params.has("start_date")).toBe(false); + expect(params.has("end_date")).toBe(false); }); }); From 51f69278cb7c3b0773efb22772c0a0c50db623f3 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Tue, 31 Mar 2026 23:59:10 +0200 Subject: [PATCH 387/418] update dependencies (#4068) last update before release --- package-lock.json | 944 ++++++++++++++++++++++++---------------------- package.json | 36 +- 2 files changed, 507 insertions(+), 473 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93b48d46e8..5b036636c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "ajv": "^8.18.0", "animate.css": "^4.1.1", "croner": "^10.0.1", - "eslint": "^10.0.3", + "eslint": "^10.1.0", "express": "^5.2.1", "feedme": "^2.0.2", "globals": "^17.4.0", @@ -25,66 +25,59 @@ "iconv-lite": "^0.7.2", "ipaddr.js": "^2.3.0", "moment": "^2.30.1", - "moment-timezone": "^0.6.0", - "node-ical": "^0.25.5", + "moment-timezone": "^0.6.1", + "node-ical": "^0.25.6", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.31.4", - "undici": "^7.23.0", + "systeminformation": "^5.31.5", + "undici": "^7.24.6", "weathericons": "^2.1.0" }, "devDependencies": { "@eslint/js": "^10.0.1", "@stylistic/eslint-plugin": "^5.10.0", - "@vitest/coverage-v8": "^4.1.0", - "@vitest/eslint-plugin": "^1.6.11", - "@vitest/ui": "^4.1.0", + "@vitest/coverage-v8": "^4.1.2", + "@vitest/eslint-plugin": "^1.6.14", + "@vitest/ui": "^4.1.2", "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.2", - "eslint-plugin-jsdoc": "^62.8.0", - "eslint-plugin-package-json": "^0.90.1", - "eslint-plugin-playwright": "^2.9.0", + "eslint-plugin-jsdoc": "^62.8.1", + "eslint-plugin-package-json": "^0.91.1", + "eslint-plugin-playwright": "^2.10.1", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", - "jsdom": "^28.1.0", - "lint-staged": "^16.3.3", - "markdownlint-cli2": "^0.21.0", - "msw": "^2.12.10", + "jsdom": "^29.0.1", + "lint-staged": "^16.4.0", + "markdownlint-cli2": "^0.22.0", + "msw": "^2.12.14", "playwright": "^1.58.2", "prettier": "^3.8.1", "prettier-plugin-jinja-template": "^2.1.0", - "stylelint": "^17.4.0", + "stylelint": "^17.6.0", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", - "vitest": "^4.1.0" + "vitest": "^4.1.2" }, "engines": { "node": ">=22.21.1 <23 || >=24" }, "optionalDependencies": { - "electron": "^41.0.0" + "electron": "^41.1.0" } }, - "node_modules/@acemir/cssom": { - "version": "0.9.31", - "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", - "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", - "dev": true, - "license": "MIT" - }, "node_modules/@altano/repository-tools": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@altano/repository-tools/-/repository-tools-2.0.1.tgz", - "integrity": "sha512-YE/52CkFtb+YtHPgbWPai7oo5N9AKnMuP5LM+i2AG7G1H2jdYBCO1iDnkDE3dZ3C1MIgckaF+d5PNRulgt0bdw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@altano/repository-tools/-/repository-tools-2.0.3.tgz", + "integrity": "sha512-cSR/ZYDF6Wp9OeAJMyLYYN1GenAAhV17W+w38ELP+3c5Ltsy9jkkCymi33nz/qnXyef3n6Fbr1h2yt3dvUN5sQ==", "dev": true, "license": "ISC" }, "node_modules/@asamuzakjp/css-color": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.0.1.tgz", - "integrity": "sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.1.tgz", + "integrity": "sha512-iGWN8E45Ws0XWx3D44Q1t6vX2LqhCKcwfmwBYCDsFrYFS6m4q/Ks61L2veETaLv+ckDC6+dTETJoaAAb7VjLiw==", "dev": true, "license": "MIT", "dependencies": { @@ -92,24 +85,27 @@ "@csstools/css-color-parser": "^4.0.2", "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0", - "lru-cache": "^11.2.6" + "lru-cache": "^11.2.7" }, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/@asamuzakjp/dom-selector": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", - "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", + "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==", "dev": true, "license": "MIT", "dependencies": { "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", - "css-tree": "^3.1.0", + "css-tree": "^3.2.1", "is-potential-custom-element-name": "^1.0.1", - "lru-cache": "^11.2.6" + "lru-cache": "^11.2.7" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/@asamuzakjp/nwsapi": { @@ -162,9 +158,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, "license": "MIT", "dependencies": { @@ -255,13 +251,13 @@ } }, "node_modules/@cacheable/utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.4.0.tgz", - "integrity": "sha512-PeMMsqjVq+bF0WBsxFBxr/WozBJiZKY0rUojuaCoIaKnEl3Ju1wfEwS+SV1DU/cSe8fqHIPiYJFif8T3MVt4cQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.4.1.tgz", + "integrity": "sha512-eiFgzCbIneyMlLOmNG4g9xzF7Hv3Mga4LjxjcSC/ues6VYq2+gUbQI8JqNuw/ZM8tJIeIaBGpswAsqV2V7ApgA==", "dev": true, "license": "MIT", "dependencies": { - "hashery": "^1.5.0", + "hashery": "^1.5.1", "keyv": "^5.6.0" } }, @@ -520,9 +516,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-dotnet": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.12.tgz", - "integrity": "sha512-FiV934kNieIjGTkiApu/WKvLYi/KBpvfWB2TSqpDQtmXZlt3uSa5blwblO1ZC8OvjH8RCq/31H5IdEYmTaZS7A==", + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.13.tgz", + "integrity": "sha512-xPp7jMnFpOri7tzmqmm/dXMolXz1t2bhNqxYkOyMqXhvs08oc7BFs+EsbDY0X7hqiISgeFZGNqn0dOCr+ncPYw==", "dev": true, "license": "MIT" }, @@ -534,9 +530,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.4.31", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.31.tgz", - "integrity": "sha512-MdV6mbrSkyIqn9+6F5poCyHIPqWB3H/wlDL9LXfjgAxNFBdYRE767xJtIYunzUqhUiJHSJgZajEFdTtMDw441Q==", + "version": "4.4.33", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.33.tgz", + "integrity": "sha512-zWftVqfUStDA37wO1ZNDN1qMJOfcxELa8ucHW8W8wBAZY3TK5Nb6deLogCK/IJi/Qljf30dwwuqqv84Qqle9Tw==", "dev": true, "license": "MIT" }, @@ -548,16 +544,16 @@ "license": "CC BY-SA 4.0" }, "node_modules/@cspell/dict-en-gb-mit": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.20.tgz", - "integrity": "sha512-rcWEKb1mwgK13CSHu6GwwFA/sWLRkB0twTzSfPxUOULJkhcUrL93ixohk416SBa0BVxixub+lOpTXKcCTbTXsA==", + "version": "3.1.22", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.22.tgz", + "integrity": "sha512-xE5Vg6gGdMkZ1Ep6z9SJMMioGkkT1GbxS5Mm0U3Ey1/H68P0G7cJcyiVr1CARxFbLqKE4QUpoV1o6jz1Z5Yl9Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.17.tgz", - "integrity": "sha512-6f1gZf9o60fGQXGi/fZaryISUNDRmmJwGyr4QU1UvgUgOdpDHLVJtv/0wSL9q5F0wAkYhbXo/fNG8CcUTaf7Ww==", + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.18.tgz", + "integrity": "sha512-yU7RKD/x1IWmDLzWeiItMwgV+6bUcU/af23uS0+uGiFUbsY1qWV/D4rxlAAO6Z7no3J2z8aZOkYIOvUrJq0Rcw==", "dev": true, "license": "MIT" }, @@ -583,9 +579,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-fullstack": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.8.tgz", - "integrity": "sha512-J6EeoeThvx/DFrcA2rJiCA6vfqwJMbkG0IcXhlsmRZmasIpanmxgt90OEaUazbZahFiuJT8wrhgQ1QgD1MsqBw==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.9.tgz", + "integrity": "sha512-diZX+usW5aZ4/b2T0QM/H/Wl9aNMbdODa1Jq0ReBr/jazmNeWjd+PyqeVgzd1joEaHY+SAnjrf/i9CwKd2ZtWQ==", "dev": true, "license": "MIT" }, @@ -722,9 +718,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.37", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.37.tgz", - "integrity": "sha512-dYKrD0bI08YgebJcbjsIDpTMK6EH0wTkEyQLsaH0T4tmsLJE95coTYb3eE7giRRGJADvBqrjH4fz5+INd85QqQ==", + "version": "5.2.38", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.38.tgz", + "integrity": "sha512-21ucGRPYYhr91C2cDBoMPTrcIOStQv33xOqJB0JLoC5LAs2Sfj9EoPGhGb+gIFVHz6Ia7JQWE2SJsOVFJD1wmg==", "dev": true, "license": "MIT" }, @@ -750,9 +746,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.25", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.25.tgz", - "integrity": "sha512-hDdN0YhKgpbtZVRjQ2c8jk+n0wQdidAKj1Fk8w7KEHb3YlY5uPJ0mAKJk7AJKPNLOlILoUmN+HAVJz+cfSbWYg==", + "version": "4.2.26", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.26.tgz", + "integrity": "sha512-hbjN6BjlSgZOG2dA2DtvYNGBM5Aq0i0dHaZjMOI9K/9vRicVvKbcCiBSSrR3b+jwjhQL5ff7HwG5xFaaci0GQA==", "dev": true, "license": "MIT", "dependencies": { @@ -795,9 +791,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.2.0.tgz", - "integrity": "sha512-jyucc8KKxH5ClC4FPICISgcKAZU7UwgFdPkuuuK5nYIw0+l1umnUSn9IKCcOaurvXujvVP6mBfclXpUtmT6Vrw==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.2.2.tgz", + "integrity": "sha512-0CaYd6TAsKtEoA7tNswm1iptEblTzEe3UG8beG2cpSTHk7afWIVMtJLgXDv0f/Li67Lf3Z1Jf3JeXR7GsJ2TRw==", "dev": true, "license": "MIT" }, @@ -1000,9 +996,9 @@ } }, "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.0.tgz", - "integrity": "sha512-H4tuz2nhWgNKLt1inYpoVCfbJbMwX/lQKp3g69rrrIMIYlFD9+zTykOKhNR8uGrAmbS/kT9n6hTFkmDkxLgeTA==", + "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==", "dev": true, "funding": [ { @@ -1014,7 +1010,15 @@ "url": "https://opencollective.com/csstools" } ], - "license": "MIT-0" + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } }, "node_modules/@csstools/css-tokenizer": { "version": "4.0.0", @@ -1149,9 +1153,9 @@ } }, "node_modules/@emnapi/core": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz", - "integrity": "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", + "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", "dev": true, "license": "MIT", "optional": true, @@ -1169,9 +1173,9 @@ "optional": true }, "node_modules/@emnapi/runtime": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz", - "integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", "dev": true, "license": "MIT", "optional": true, @@ -1223,6 +1227,16 @@ "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", @@ -1754,20 +1768,10 @@ "dev": true, "license": "MIT" }, - "node_modules/@oxc-project/runtime": { - "version": "0.115.0", - "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.115.0.tgz", - "integrity": "sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/@oxc-project/types": { - "version": "0.115.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.115.0.tgz", - "integrity": "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==", + "version": "0.122.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz", + "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==", "dev": true, "license": "MIT", "funding": { @@ -2040,9 +2044,9 @@ "license": "MIT" }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.9.tgz", - "integrity": "sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==", + "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==", "cpu": [ "arm64" ], @@ -2057,9 +2061,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.9.tgz", - "integrity": "sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ==", + "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==", "cpu": [ "arm64" ], @@ -2074,9 +2078,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.9.tgz", - "integrity": "sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg==", + "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==", "cpu": [ "x64" ], @@ -2091,9 +2095,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.9.tgz", - "integrity": "sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q==", + "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==", "cpu": [ "x64" ], @@ -2108,9 +2112,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.9.tgz", - "integrity": "sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ==", + "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==", "cpu": [ "arm" ], @@ -2125,9 +2129,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.9.tgz", - "integrity": "sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg==", + "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==", "cpu": [ "arm64" ], @@ -2145,9 +2149,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.9.tgz", - "integrity": "sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==", + "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==", "cpu": [ "arm64" ], @@ -2165,9 +2169,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.9.tgz", - "integrity": "sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==", + "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==", "cpu": [ "ppc64" ], @@ -2185,9 +2189,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.9.tgz", - "integrity": "sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==", + "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==", "cpu": [ "s390x" ], @@ -2205,9 +2209,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.9.tgz", - "integrity": "sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==", + "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==", "cpu": [ "x64" ], @@ -2225,9 +2229,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.9.tgz", - "integrity": "sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==", + "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==", "cpu": [ "x64" ], @@ -2245,9 +2249,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.9.tgz", - "integrity": "sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==", + "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==", "cpu": [ "arm64" ], @@ -2262,9 +2266,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.9.tgz", - "integrity": "sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g==", + "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==", "cpu": [ "wasm32" ], @@ -2279,26 +2283,28 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", - "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz", + "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.9.tgz", - "integrity": "sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA==", + "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==", "cpu": [ "arm64" ], @@ -2313,9 +2319,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.9.tgz", - "integrity": "sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ==", + "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==", "cpu": [ "x64" ], @@ -2330,9 +2336,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.9.tgz", - "integrity": "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==", + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz", + "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==", "dev": true, "license": "MIT" }, @@ -2494,9 +2500,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", "dev": true, "license": "MIT", "dependencies": { @@ -2612,14 +2618,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz", - "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.57.0", - "@typescript-eslint/types": "^8.57.0", + "@typescript-eslint/tsconfig-utils": "^8.58.0", + "@typescript-eslint/types": "^8.58.0", "debug": "^4.4.3" }, "engines": { @@ -2630,18 +2636,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz", - "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.57.0", - "@typescript-eslint/visitor-keys": "8.57.0" + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2652,9 +2658,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz", - "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==", + "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==", "dev": true, "license": "MIT", "engines": { @@ -2665,13 +2671,13 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz", - "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.0.tgz", + "integrity": "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==", "dev": true, "license": "MIT", "engines": { @@ -2683,21 +2689,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz", - "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.57.0", - "@typescript-eslint/tsconfig-utils": "8.57.0", - "@typescript-eslint/types": "8.57.0", - "@typescript-eslint/visitor-keys": "8.57.0", + "@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", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2707,20 +2713,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz", - "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==", + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.0.tgz", + "integrity": "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.57.0", - "@typescript-eslint/types": "8.57.0", - "@typescript-eslint/typescript-estree": "8.57.0" + "@typescript-eslint/scope-manager": "8.58.0", + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/typescript-estree": "8.58.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2731,17 +2737,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz", - "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3059,14 +3065,14 @@ ] }, "node_modules/@vitest/coverage-v8": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.0.tgz", - "integrity": "sha512-nDWulKeik2bL2Va/Wl4x7DLuTKAXa906iRFooIRPR+huHkcvp9QDkPQ2RJdmjOFrqOqvNfoSQLF68deE3xC3CQ==", + "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==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.1.0", + "@vitest/utils": "4.1.2", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", @@ -3074,14 +3080,14 @@ "magicast": "^0.5.2", "obug": "^2.1.1", "std-env": "^4.0.0-rc.1", - "tinyrainbow": "^3.0.3" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "4.1.0", - "vitest": "4.1.0" + "@vitest/browser": "4.1.2", + "vitest": "4.1.2" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -3090,24 +3096,28 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.11.tgz", - "integrity": "sha512-/m7cyD2x/TMJt6SmW6X9ZQWThCROa3AgBXJKVzTDG6MIRQkxBGLlwi4Vi+F5bcKnRKI17b3aeUzOhqBwnsjiHg==", + "version": "1.6.14", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.14.tgz", + "integrity": "sha512-PXZ5ysw4eHU9h8nDtBvVcGC7Z2C/T9CFdheqSw1NNXFYqViojub0V9bgdYI67iBTOcra2mwD0EYldlY9bGPf2Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "^8.55.0", - "@typescript-eslint/utils": "^8.55.0" + "@typescript-eslint/scope-manager": "^8.58.0", + "@typescript-eslint/utils": "^8.58.0" }, "engines": { "node": ">=18" }, "peerDependencies": { + "@typescript-eslint/eslint-plugin": "*", "eslint": ">=8.57.0", "typescript": ">=5.0.0", "vitest": "*" }, "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, "typescript": { "optional": true }, @@ -3117,31 +3127,31 @@ } }, "node_modules/@vitest/expect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz", - "integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.2.tgz", + "integrity": "sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.0", - "@vitest/utils": "4.1.0", + "@vitest/spy": "4.1.2", + "@vitest/utils": "4.1.2", "chai": "^6.2.2", - "tinyrainbow": "^3.0.3" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz", - "integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.2.tgz", + "integrity": "sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.1.0", + "@vitest/spy": "4.1.2", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -3150,7 +3160,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "msw": { @@ -3162,26 +3172,26 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz", - "integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.2.tgz", + "integrity": "sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^3.0.3" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz", - "integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.2.tgz", + "integrity": "sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.0", + "@vitest/utils": "4.1.2", "pathe": "^2.0.3" }, "funding": { @@ -3189,14 +3199,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz", - "integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.2.tgz", + "integrity": "sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.0", - "@vitest/utils": "4.1.0", + "@vitest/pretty-format": "4.1.2", + "@vitest/utils": "4.1.2", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -3205,9 +3215,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz", - "integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.2.tgz", + "integrity": "sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==", "dev": true, "license": "MIT", "funding": { @@ -3215,37 +3225,37 @@ } }, "node_modules/@vitest/ui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.1.0.tgz", - "integrity": "sha512-sTSDtVM1GOevRGsCNhp1mBUHKo9Qlc55+HCreFT4fe99AHxl1QQNXSL3uj4Pkjh5yEuWZIx8E2tVC94nnBZECQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.1.2.tgz", + "integrity": "sha512-/irhyeAcKS2u6Zokagf9tqZJ0t8S6kMZq4ZG9BHZv7I+fkRrYfQX4w7geYeC2r6obThz39PDxvXQzZX+qXqGeg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.1.0", + "@vitest/utils": "4.1.2", "fflate": "^0.8.2", - "flatted": "3.4.0", + "flatted": "^3.4.2", "pathe": "^2.0.3", "sirv": "^3.0.2", "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "4.1.0" + "vitest": "4.1.2" } }, "node_modules/@vitest/utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz", - "integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.2.tgz", + "integrity": "sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.1.0", + "@vitest/pretty-format": "4.1.2", "convert-source-map": "^2.0.0", - "tinyrainbow": "^3.0.3" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -3411,9 +3421,9 @@ } }, "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -3608,9 +3618,9 @@ "optional": true }, "node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -3657,9 +3667,9 @@ } }, "node_modules/cacheable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.3.tgz", - "integrity": "sha512-iffYMX4zxKp54evOH27fm92hs+DeC1DhXmNVN8Tr94M/iZIV42dqTHSR2Ik4TOSPyOAwKr7Yu3rN9ALoLkbWyQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.4.tgz", + "integrity": "sha512-djgxybDbw9fL/ZWMI3+CE8ZilNxcwFkVtDc1gJ+IlOSSWkSMPQabhV/XCHTQ6pwwN6aivXPZ43omTooZiX06Ew==", "dev": true, "license": "MIT", "dependencies": { @@ -3667,7 +3677,7 @@ "@cacheable/utils": "^2.4.0", "hookified": "^1.15.0", "keyv": "^5.6.0", - "qified": "^0.6.0" + "qified": "^0.9.0" } }, "node_modules/cacheable-lookup": { @@ -4146,9 +4156,9 @@ } }, "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==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.6.tgz", + "integrity": "sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==", "dev": true, "license": "MIT", "engines": { @@ -4511,22 +4521,6 @@ "node": ">=4" } }, - "node_modules/cssstyle": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.2.0.tgz", - "integrity": "sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@asamuzakjp/css-color": "^5.0.1", - "@csstools/css-syntax-patches-for-csstree": "^1.0.28", - "css-tree": "^3.1.0", - "lru-cache": "^11.2.6" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/culvert": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", @@ -4856,9 +4850,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "41.0.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-41.0.0.tgz", - "integrity": "sha512-U7QueSj1cFj9QM0Qamgh/MK08662FVK555iMfapqU7mcAmIm4A8bZuZptpjMXrT4JNAMGjgWu9sOeO1+RPCJNw==", + "version": "41.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-41.1.0.tgz", + "integrity": "sha512-0XRFyxRqetmqtkkBvV++wGbHYJ7bD++f6EgJW8y9kX4pPRagwlmKDtzqXZhKiu0DIQppm3sXxzHWK9GYP91OKQ==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5151,15 +5145,15 @@ } }, "node_modules/eslint": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.3.tgz", - "integrity": "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.1.0.tgz", + "integrity": "sha512-S9jlY/ELKEUwwQnqWDO+f+m6sercqOPSqXM5Go94l7DOmxHVDgmSFGWEzeE/gwgTAr0W103BWt0QLe/7mabIvA==", "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.2", + "@eslint/config-helpers": "^0.5.3", "@eslint/core": "^1.1.1", "@eslint/plugin-kit": "^0.6.1", "@humanfs/node": "^0.16.6", @@ -5172,7 +5166,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", - "espree": "^11.1.1", + "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5288,9 +5282,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "62.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.8.0.tgz", - "integrity": "sha512-hu3r9/6JBmPG6wTcqtYzgZAnjEG2eqRUATfkFscokESg1VDxZM21ZaMire0KjeMwfj+SXvgB4Rvh5LBuesj92w==", + "version": "62.8.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.8.1.tgz", + "integrity": "sha512-e9358PdHgvcMF98foNd3L7hVCw70Lt+YcSL7JzlJebB8eT5oRJtW6bHMQKoAwJtw6q0q0w/fRIr2kwnHdFDI6A==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5316,6 +5310,16 @@ "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", @@ -5348,9 +5352,9 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.90.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.90.1.tgz", - "integrity": "sha512-6GU2nyjGZ+iSLIo1Qxm6O2HcPKshpjIS3B5ZeBTt8spGad5IQ45+hQUDrULYP0vD6SFT8veJfQ/Ha49/g4Cr5w==", + "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==", "dev": true, "license": "MIT", "dependencies": { @@ -5359,7 +5363,7 @@ "detect-indent": "^7.0.2", "detect-newline": "^4.0.1", "eslint-fix-utils": "~0.4.1", - "package-json-validator": "^1.2.1", + "package-json-validator": "^1.3.1", "semver": "^7.7.3", "sort-object-keys": "^2.0.0", "sort-package-json": "^3.4.0", @@ -5374,9 +5378,9 @@ } }, "node_modules/eslint-plugin-playwright": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.9.0.tgz", - "integrity": "sha512-k3xrG6YzrallWNFMoGUjMNeu3SFFKXN79KJQBD2PkM4PasJegqV2Up+mPY5od2UmPKQGT+MeIhCmWH8r5eYuQQ==", + "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==", "dev": true, "license": "MIT", "dependencies": { @@ -5905,9 +5909,9 @@ } }, "node_modules/flatted": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.0.tgz", - "integrity": "sha512-kC6Bb+ooptOIvWj5B63EQWkF0FEnNjV2ZNkLMLZRDDduIiWeFF4iKnslwhiWxjAdbg4NzTNo6h0qLuvFrcx+Sw==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "license": "ISC" }, "node_modules/follow-redirects": { @@ -6073,9 +6077,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.6", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", - "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6245,9 +6249,9 @@ } }, "node_modules/globby": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-16.1.0.tgz", - "integrity": "sha512-+A4Hq7m7Ze592k9gZRy4gJ27DrXRNnC1vPjxTt1qQxEY8RxagBkBxivkCwg7FxSTG0iLLEMaUx13oOr0R2/qcQ==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-16.1.1.tgz", + "integrity": "sha512-dW7vl+yiAJSp6aCekaVnVJxurRv7DCOLyXqEG3RYMYUg7AuJ2jCqPkZTA8ooqC2vtnkaMcV5WfFBMuEnTu1OQg==", "dev": true, "license": "MIT", "dependencies": { @@ -6328,9 +6332,9 @@ "optional": true }, "node_modules/graphql": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.1.tgz", - "integrity": "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==", + "version": "16.13.2", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.2.tgz", + "integrity": "sha512-5bJ+nf/UCpAjHM8i06fl7eLyVC9iuNAjm9qzkiu2ZGhM0VscSvS6WDPfAwkdkBuoXGM9FJSbKl6wylMwP9Ktig==", "dev": true, "license": "MIT", "engines": { @@ -6372,13 +6376,13 @@ } }, "node_modules/hashery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.0.tgz", - "integrity": "sha512-nhQ6ExaOIqti2FDWoEMWARUqIKyjr2VcZzXShrI+A3zpeiuPWzx6iPftt44LhP74E5sW36B75N6VHbvRtpvO6Q==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", + "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.14.0" + "hookified": "^1.15.0" }, "engines": { "node": ">=20" @@ -6996,36 +7000,36 @@ } }, "node_modules/jsdom": { - "version": "28.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz", - "integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==", + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.0.1.tgz", + "integrity": "sha512-z6JOK5gRO7aMybVq/y/MlIpKh8JIi68FBKMUtKkK2KH/wMSRlCxQ682d08LB9fYXplyY/UXG8P4XXTScmdjApg==", "dev": true, "license": "MIT", "dependencies": { - "@acemir/cssom": "^0.9.31", - "@asamuzakjp/dom-selector": "^6.8.1", + "@asamuzakjp/css-color": "^5.0.1", + "@asamuzakjp/dom-selector": "^7.0.3", "@bramus/specificity": "^2.4.2", - "@exodus/bytes": "^1.11.0", - "cssstyle": "^6.0.1", + "@csstools/css-syntax-patches-for-csstree": "^1.1.1", + "@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", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.7", "parse5": "^8.0.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^6.0.0", - "undici": "^7.21.0", + "tough-cookie": "^6.0.1", + "undici": "^7.24.5", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^8.0.1", "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^16.0.0", + "whatwg-url": "^16.0.1", "xml-name-validator": "^5.0.0" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" }, "peerDependencies": { "canvas": "^3.0.0" @@ -7118,10 +7122,20 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/katex": { - "version": "0.16.38", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.38.tgz", - "integrity": "sha512-cjHooZUmIAUmDsHBN+1n8LaZdpmbj03LtYeYPyuYB7OuloiaeaV6N4LcfjcnHVzGWjVQmKrxxTrpDcmSzEZQwQ==", + "version": "0.16.44", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.44.tgz", + "integrity": "sha512-EkxoDTk8ufHqHlf9QxGwcxeLkWRR3iOuYfRpfORgYfqc8s13bgb+YtRY59NK5ZpRaCwq1kqA6a5lpX8C/eLphQ==", "dev": true, "funding": [ "https://opencollective.com/katex", @@ -7477,17 +7491,17 @@ } }, "node_modules/lint-staged": { - "version": "16.3.3", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.3.3.tgz", - "integrity": "sha512-RLq2koZ5fGWrx7tcqx2tSTMQj4lRkfNJaebO/li/uunhCJbtZqwTuwPHpgIimAHHi/2nZIiGrkCHDCOeR1onxA==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.4.0.tgz", + "integrity": "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==", "dev": true, "license": "MIT", "dependencies": { "commander": "^14.0.3", "listr2": "^9.0.5", - "micromatch": "^4.0.8", + "picomatch": "^4.0.3", "string-argv": "^0.3.2", - "tinyexec": "^1.0.2", + "tinyexec": "^1.0.4", "yaml": "^2.8.2" }, "bin": { @@ -7594,9 +7608,9 @@ } }, "node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -7684,19 +7698,21 @@ } }, "node_modules/markdownlint-cli2": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.21.0.tgz", - "integrity": "sha512-DzzmbqfMW3EzHsunP66x556oZDzjcdjjlL2bHG4PubwnL58ZPAfz07px4GqteZkoCGnBYi779Y2mg7+vgNCwbw==", + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.22.0.tgz", + "integrity": "sha512-mOC9BY/XGtdX3M9n3AgERd79F0+S7w18yBBTNIQ453sI87etZfp1z4eajqSMV70CYjbxKe5ktKvT2HCpvcWx9w==", "dev": true, "license": "MIT", "dependencies": { - "globby": "16.1.0", + "globby": "16.1.1", "js-yaml": "4.1.1", "jsonc-parser": "3.3.1", + "jsonpointer": "5.0.1", "markdown-it": "14.1.1", "markdownlint": "0.40.0", "markdownlint-cli2-formatter-default": "0.0.6", - "micromatch": "4.0.8" + "micromatch": "4.0.8", + "smol-toml": "1.6.0" }, "bin": { "markdownlint-cli2": "markdownlint-cli2-bin.mjs" @@ -7721,6 +7737,19 @@ "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", @@ -8380,9 +8409,9 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -8441,12 +8470,12 @@ } }, "node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -8483,9 +8512,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.0.tgz", - "integrity": "sha512-ldA5lRNm3iJCWZcBCab4pnNL3HSZYXVb/3TYr75/1WCTWYuTqYUb5f/S384pncYjJ88lbO8Z4uPDvmoluHJc8Q==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.1.tgz", + "integrity": "sha512-1B9lmAhB9D9/sHaPC1N7wLFEVUoFldxOpOO96lOD1PvJ43vCd0ozDPbu0FEL3++VvawOlDkq8YD373tJmP5JHw==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -8511,9 +8540,9 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.12.10", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.10.tgz", - "integrity": "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw==", + "version": "2.12.14", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.14.tgz", + "integrity": "sha512-4KXa4nVBIBjbDbd7vfQNuQ25eFxug0aropCQFoI0JdOBuJWamkT1yLVIWReFI8SiTRc+H1hKzaNk+cLk2N9rtQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -8677,9 +8706,9 @@ } }, "node_modules/node-ical": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.25.5.tgz", - "integrity": "sha512-hj1I+kV38EXdhMB9Sh9phtvdzeJML/HvYbiKqBqcET1O2JiFmJnvpEWISNLA5nUeCWQAaTqiDhZH4uwUTG2Vdg==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.25.6.tgz", + "integrity": "sha512-Wo3GSBGYUNkcxOjHhevKTGa/+eB7ZwNLCq50h/eTX/YHSDZz1nT4KzXArO455CGHLD68gc5vw3nevqWQpOjjLQ==", "license": "Apache-2.0", "dependencies": { "rrule-temporal": "^1.4.7", @@ -9127,9 +9156,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -9604,18 +9633,25 @@ } }, "node_modules/qified": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/qified/-/qified-0.6.0.tgz", - "integrity": "sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.9.1.tgz", + "integrity": "sha512-n7mar4T0xQ+39dE2vGTAlbxUEpndwPANH0kDef1/MYsB8Bba9wshkybIRx74qgcvKQPEWErf9AqAdYjhzY2Ilg==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.14.0" + "hookified": "^2.1.1" }, "engines": { "node": ">=20" } }, + "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==", + "dev": true, + "license": "MIT" + }, "node_modules/qs": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", @@ -9720,9 +9756,9 @@ } }, "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -9898,14 +9934,14 @@ } }, "node_modules/rolldown": { - "version": "1.0.0-rc.9", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.9.tgz", - "integrity": "sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.115.0", - "@rolldown/pluginutils": "1.0.0-rc.9" + "@oxc-project/types": "=0.122.0", + "@rolldown/pluginutils": "1.0.0-rc.12" }, "bin": { "rolldown": "bin/cli.mjs" @@ -9914,21 +9950,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.9", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.9", - "@rolldown/binding-darwin-x64": "1.0.0-rc.9", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.9", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.9", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.9", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.9", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.9", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.9", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.9", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.9", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.9", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.9", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.9", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.9" + "@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" } }, "node_modules/router": { @@ -9948,9 +9984,9 @@ } }, "node_modules/router/node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "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==", "license": "MIT", "funding": { "type": "opencollective", @@ -10024,9 +10060,9 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", - "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" @@ -10332,9 +10368,9 @@ } }, "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==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", + "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -10394,9 +10430,9 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", - "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", @@ -10672,9 +10708,9 @@ } }, "node_modules/stylelint": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.4.0.tgz", - "integrity": "sha512-3kQ2/cHv3Zt8OBg+h2B8XCx9evEABQIrv4hh3uXahGz/ZEHrTR80zxBiK2NfXNaSoyBzxO1pjsz1Vhdzwn5XSw==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.6.0.tgz", + "integrity": "sha512-tokrsMIVAR9vAQ/q3UVEr7S0dGXCi7zkCezPRnS2kqPUulvUh5Vgfwngrk4EoAoW7wnrThqTdnTFN5Ra7CaxIg==", "dev": true, "funding": [ { @@ -10690,41 +10726,40 @@ "dependencies": { "@csstools/css-calc": "^3.1.1", "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-syntax-patches-for-csstree": "^1.0.27", + "@csstools/css-syntax-patches-for-csstree": "^1.1.1", "@csstools/css-tokenizer": "^4.0.0", "@csstools/media-query-list-parser": "^5.0.0", "@csstools/selector-resolve-nested": "^4.0.0", "@csstools/selector-specificity": "^6.0.0", "colord": "^2.9.3", - "cosmiconfig": "^9.0.0", + "cosmiconfig": "^9.0.1", "css-functions-list": "^3.3.3", - "css-tree": "^3.1.0", + "css-tree": "^3.2.1", "debug": "^4.4.3", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^11.1.2", "global-modules": "^2.0.0", - "globby": "^16.1.0", + "globby": "^16.1.1", "globjoin": "^0.1.4", "html-tags": "^5.1.0", "ignore": "^7.0.5", "import-meta-resolve": "^4.2.0", - "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", "mathml-tag-names": "^4.0.0", - "meow": "^14.0.0", + "meow": "^14.1.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", - "postcss": "^8.5.6", + "postcss": "^8.5.8", "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.1.1", "postcss-value-parser": "^4.2.0", - "string-width": "^8.1.1", + "string-width": "^8.2.0", "supports-hyperlinks": "^4.4.0", "svg-tags": "^1.0.0", "table": "^6.9.0", - "write-file-atomic": "^7.0.0" + "write-file-atomic": "^7.0.1" }, "bin": { "stylelint": "bin/stylelint.mjs" @@ -10810,14 +10845,14 @@ } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.20", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.20.tgz", - "integrity": "sha512-AhHYqwvN62NVLp4lObVXGVluiABTHapoB57EyegZVmazN+hhGhLTn3uZbOofoTw4DSDvVCadzzyChXhOAvy8uQ==", + "version": "6.1.22", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.22.tgz", + "integrity": "sha512-N2dnzVJIphnNsjHcrxGW7DePckJ6haPrSFqpsBUhHYgwtKGVq4JrBGielEGD2fCVnsGm1zlBVZ8wGhkyuetgug==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^2.3.2", - "flatted": "^3.3.3", + "cacheable": "^2.3.4", + "flatted": "^3.4.2", "hookified": "^1.15.0" } }, @@ -10930,9 +10965,9 @@ "license": "MIT" }, "node_modules/systeminformation": { - "version": "5.31.4", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.4.tgz", - "integrity": "sha512-lZppDyQx91VdS5zJvAyGkmwe+Mq6xY978BDUG2wRkWE+jkmUF5ti8cvOovFQoN5bvSFKCXVkyKEaU5ec3SJiRg==", + "version": "5.31.5", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.31.5.tgz", + "integrity": "sha512-5SyLdip4/3alxD4Kh+63bUQTJmu7YMfYQTC+koZy7X73HgNqZSD2P4wOZQWtUncvPvcEmnfIjCoygN4MRoEejQ==", "license": "MIT", "os": [ "darwin", @@ -11090,9 +11125,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", "dev": true, "license": "MIT", "engines": { @@ -11127,22 +11162,22 @@ } }, "node_modules/tldts": { - "version": "7.0.25", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.25.tgz", - "integrity": "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.27.tgz", + "integrity": "sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.0.25" + "tldts-core": "^7.0.27" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.0.25", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.25.tgz", - "integrity": "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==", + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.27.tgz", + "integrity": "sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==", "dev": true, "license": "MIT" }, @@ -11221,9 +11256,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -11280,9 +11315,9 @@ } }, "node_modules/type-fest": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.4.tgz", - "integrity": "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz", + "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==", "dev": true, "license": "(MIT OR CC0-1.0)", "dependencies": { @@ -11310,9 +11345,9 @@ } }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz", + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -11332,9 +11367,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.0.tgz", - "integrity": "sha512-jxytwMHhsbdpBXxLAcuu0fzlQeXCNnWdDyRHpvWsUl8vd98UwYdl9YTyn8/HcpcJPC3pwUveefsa3zTxyD/ERg==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.6.tgz", + "integrity": "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -11481,17 +11516,16 @@ } }, "node_modules/vite": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.0.tgz", - "integrity": "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz", + "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/runtime": "0.115.0", "lightningcss": "^1.32.0", - "picomatch": "^4.0.3", + "picomatch": "^4.0.4", "postcss": "^8.5.8", - "rolldown": "1.0.0-rc.9", + "rolldown": "1.0.0-rc.12", "tinyglobby": "^0.2.15" }, "bin": { @@ -11508,7 +11542,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.0.0-alpha.31", + "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -11575,19 +11609,19 @@ } }, "node_modules/vitest": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", - "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.2.tgz", + "integrity": "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.1.0", - "@vitest/mocker": "4.1.0", - "@vitest/pretty-format": "4.1.0", - "@vitest/runner": "4.1.0", - "@vitest/snapshot": "4.1.0", - "@vitest/spy": "4.1.0", - "@vitest/utils": "4.1.0", + "@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", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", @@ -11598,8 +11632,8 @@ "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -11615,13 +11649,13 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.0", - "@vitest/browser-preview": "4.1.0", - "@vitest/browser-webdriverio": "4.1.0", - "@vitest/ui": "4.1.0", + "@vitest/browser-playwright": "4.1.2", + "@vitest/browser-preview": "4.1.2", + "@vitest/browser-webdriverio": "4.1.2", + "@vitest/ui": "4.1.2", "happy-dom": "*", "jsdom": "*", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { @@ -11925,9 +11959,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 4c964e6a8a..876bb73fb2 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "ajv": "^8.18.0", "animate.css": "^4.1.1", "croner": "^10.0.1", - "eslint": "^10.0.3", + "eslint": "^10.1.0", "express": "^5.2.1", "feedme": "^2.0.2", "globals": "^17.4.0", @@ -102,43 +102,43 @@ "iconv-lite": "^0.7.2", "ipaddr.js": "^2.3.0", "moment": "^2.30.1", - "moment-timezone": "^0.6.0", - "node-ical": "^0.25.5", + "moment-timezone": "^0.6.1", + "node-ical": "^0.25.6", "nunjucks": "^3.2.4", "pm2": "^6.0.14", "socket.io": "^4.8.3", "suncalc": "^1.9.0", - "systeminformation": "^5.31.4", - "undici": "^7.23.0", + "systeminformation": "^5.31.5", + "undici": "^7.24.6", "weathericons": "^2.1.0" }, "devDependencies": { "@eslint/js": "^10.0.1", "@stylistic/eslint-plugin": "^5.10.0", - "@vitest/coverage-v8": "^4.1.0", - "@vitest/eslint-plugin": "^1.6.11", - "@vitest/ui": "^4.1.0", + "@vitest/coverage-v8": "^4.1.2", + "@vitest/eslint-plugin": "^1.6.14", + "@vitest/ui": "^4.1.2", "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.2", - "eslint-plugin-jsdoc": "^62.8.0", - "eslint-plugin-package-json": "^0.90.1", - "eslint-plugin-playwright": "^2.9.0", + "eslint-plugin-jsdoc": "^62.8.1", + "eslint-plugin-package-json": "^0.91.1", + "eslint-plugin-playwright": "^2.10.1", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", - "jsdom": "^28.1.0", - "lint-staged": "^16.3.3", - "markdownlint-cli2": "^0.21.0", - "msw": "^2.12.10", + "jsdom": "^29.0.1", + "lint-staged": "^16.4.0", + "markdownlint-cli2": "^0.22.0", + "msw": "^2.12.14", "playwright": "^1.58.2", "prettier": "^3.8.1", "prettier-plugin-jinja-template": "^2.1.0", - "stylelint": "^17.4.0", + "stylelint": "^17.6.0", "stylelint-config-standard": "^40.0.0", "stylelint-prettier": "^5.0.3", - "vitest": "^4.1.0" + "vitest": "^4.1.2" }, "optionalDependencies": { - "electron": "^41.0.0" + "electron": "^41.1.0" }, "engines": { "node": ">=22.21.1 <23 || >=24" From 946d3226b16d886ffdad383476f403c99342ca41 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 1 Apr 2026 00:09:27 +0200 Subject: [PATCH 388/418] docs: add security policy and vulnerability reporting guidelines (#4069) Adding a SECURITY.md helps us make two things clearer: - MagicMirror is not intended for direct public internet exposure. - There is a clear path to report security concerns responsibly. Related issue: #4067 --- As always, suggestions for improvement are very welcome. --- .github/SECURITY.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/SECURITY.md diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000000..f58390678b --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,31 @@ +# Security Policy + +## Scope and Deployment + +MagicMirror is primarily intended for trusted local/private network environments. +Direct public exposure to the internet or other untrusted networks is not recommended. + +We take security seriously and encourage responsible disclosure of vulnerabilities to help us improve the software. + +## Reporting a Vulnerability + +**Please keep vulnerability details private** — do not post them in public GitHub issues. + +Instead, reach out privately via the MagicMirror forum to one of the core developers: + +- [rejas](https://forum.magicmirror.builders/user/rejas) +- [karsten13](https://forum.magicmirror.builders/user/karsten13) +- [sdetweil](https://forum.magicmirror.builders/user/sdetweil) +- [Kristjan](https://forum.magicmirror.builders/user/kristjanesperanto) + +Please include, if possible: + +- Affected version(s) +- Reproduction steps or proof-of-concept +- What could an attacker do with this? +- Any ideas how to fix it? + +## Coordinated Disclosure + +We will keep reported vulnerabilities private until a fix is available and coordinate the disclosure timeline with you. +We aim to respond as quickly as possible. From 9eaef414d4295040c7c1347a24831eb09507151d Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 1 Apr 2026 11:57:00 +0200 Subject: [PATCH 389/418] Prepare Release 2.35.0 (#4071) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5b036636c8..1234f28d45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.35.0-develop", + "version": "2.35.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.35.0-develop", + "version": "2.35.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 876bb73fb2..5cad85d4a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.35.0-develop", + "version": "2.35.0", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From 751b97fc7e91bdd8519ede2def7f32f7c3944c66 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 1 Apr 2026 12:40:11 +0200 Subject: [PATCH 390/418] update version for develop --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1234f28d45..70164861a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.35.0", + "version": "2.36.0-develop", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.35.0", + "version": "2.36.0-develop", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 5cad85d4a0..99944006ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.35.0", + "version": "2.36.0-develop", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", From d7c4ad178e62442d124b81ffd9ac6b3da01e5573 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 1 Apr 2026 20:09:04 +0200 Subject: [PATCH 391/418] fix(tests): correct import path for git_helper module in updatenotification tests (#4078) This removes a warning which appeared running a test: ```bash $ npx vitest --run tests/unit/functions/updatenotification_spec.js RUN v4.1.2 7:46:46 PM [vite] (ssr) warning: invalid import "../../../${defaults.defaultModulesDir}/updatenotification/git_helper". A file extension must be included in the static part of the import. For example: import(`./foo/${bar}.js`). ``` Related to #4073 --- tests/unit/functions/updatenotification_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/functions/updatenotification_spec.js b/tests/unit/functions/updatenotification_spec.js index f6617e4bf7..e5c9654fa4 100644 --- a/tests/unit/functions/updatenotification_spec.js +++ b/tests/unit/functions/updatenotification_spec.js @@ -20,7 +20,7 @@ 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"); From 32aa5c8721b1ba76566bfe2da48c278a4373037b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 1 Apr 2026 21:55:27 +0200 Subject: [PATCH 392/418] chore: add permissions section to enforce pull-request rules workflow (#4079) GitHub Bot complained about that in PR #4072. Related to #4073 --- .github/workflows/enforce-pullrequest-rules.yaml | 3 +++ 1 file changed, 3 insertions(+) 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: From 8e1630e8bf21c7fe47b87d52bee83add03533cd4 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Thu, 2 Apr 2026 08:56:27 +0200 Subject: [PATCH 393/418] refactor: enable ESLint rule "no-unused-vars" and handle related issues (#4080) In PR #4072 GitHub Bot complained about an unused var. Instead of just removing that one, I checked why ESLint hadn't complained about it: We had disabled the rule for it. So I enabled rule and resolved the issues that ESLint then detected. Related to #4073 --- defaultmodules/calendar/calendar.js | 2 +- defaultmodules/calendar/calendarfetcher.js | 1 - defaultmodules/calendar/calendarfetcherutils.js | 2 +- defaultmodules/compliments/compliments.js | 2 +- defaultmodules/newsfeed/newsfeed.js | 2 +- defaultmodules/updatenotification/git_helper.js | 2 +- defaultmodules/updatenotification/update_helper.js | 4 ++-- defaultmodules/weather/providers/yr.js | 2 +- defaultmodules/weather/weather.js | 2 +- eslint.config.mjs | 1 - js/animateCSS.js | 3 ++- js/app.js | 6 +++--- js/electron.js | 2 +- js/http_fetcher.js | 2 +- js/ip_access_control.js | 4 ++-- js/loader.js | 1 + js/logger.js | 2 +- js/main.js | 4 ++-- js/server.js | 2 +- js/socketclient.js | 1 + js/translator.js | 2 +- js/utils.js | 4 ++-- serveronly/watcher.js | 4 ++-- tests/e2e/translations_spec.js | 6 +++--- tests/electron/helpers/global-setup.js | 4 ++-- tests/electron/modules/calendar_spec.js | 1 + tests/mocks/testNotification/testNotification.js | 6 +++--- tests/unit/modules/default/weather/providers/yr_spec.js | 1 - 28 files changed, 38 insertions(+), 37 deletions(-) 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/updatenotification/git_helper.js b/defaultmodules/updatenotification/git_helper.js index 0444c9500c..a9c577b798 100644 --- a/defaultmodules/updatenotification/git_helper.js +++ b/defaultmodules/updatenotification/git_helper.js @@ -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 } 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/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..732958e6c8 100644 --- a/defaultmodules/weather/weather.js +++ b/defaultmodules/weather/weather.js @@ -1,4 +1,4 @@ -/* global WeatherProvider, WeatherUtils, WeatherObject, formatTime */ +/* global WeatherUtils, WeatherObject, formatTime */ Module.register("weather", { // Default module 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..398a1313a9 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}.`); } @@ -188,7 +188,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!"); } } 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..830b08bd17 100644 --- a/js/http_fetcher.js +++ b/js/http_fetcher.js @@ -300,7 +300,7 @@ class HTTPFetcher extends EventEmitter { try { const urlObj = new URL(this.url); shortUrl = `${urlObj.origin}${urlObj.pathname}${urlObj.search.length > 50 ? "?..." : urlObj.search}`; - } catch (urlError) { + } catch { // If URL parsing fails, use original URL } 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..0e20c41e82 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) { diff --git a/js/server.js b/js/server.js index 9922958ca9..081e90892c 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]}`); } 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/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/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/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. From d2304af331704a134a4b8298a9e225e6f9d6f8fe Mon Sep 17 00:00:00 2001 From: cgillinger Date: Fri, 3 Apr 2026 11:04:09 +0200 Subject: [PATCH 394/418] SMHI: migrate to SNOW1gv1 API (replace deprecated PMP3gv2) (#4082) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary This PR migrates the SMHI weather provider from the deprecated PMP3gv2 API to the new SNOW1gv1 API. The old API (pmp3g/version/2) started returning HTTP 404 on 2026-03-31. ## Changes - Updated API endpoint: - `pmp3g/version/2` → `snow1g/version/1` - Updated response parsing: - `validTime` → `time` - `parameters[]` → `data` (flat structure) - Updated parameter names: - `t` → `air_temperature` - `ws` → `wind_speed` - etc. - Updated precipitation handling to match new `predominant_precipitation_type_at_surface` - Updated coordinate parsing (flat `[lon, lat]`) - Added missing value handling (`9999 → null`) ## Notes - Maintains backward compatibility for `precipitationValue` config - No UI changes - Symbol mapping unchanged (same codes 1–27) ## Testing - Verified against live SMHI SNOW1gv1 API responses - Confirmed old API returns HTTP 404 ## Impact Fixes broken SMHI provider due to API deprecation. --- defaultmodules/weather/providers/smhi.js | 184 +- tests/mocks/weather_smhi.json | 3879 +++++++++-------- .../default/weather/providers/smhi_spec.js | 10 +- 3 files changed, 2130 insertions(+), 1943 deletions(-) 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/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/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); }); From 19c6489e6f6715902b5f41936f8772871b5bc803 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 3 Apr 2026 12:09:24 +0200 Subject: [PATCH 395/418] fix(newsfeed): prevent duplicate parse error callback when using pipeline (#4083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In PR #4072 GitHub Bot complained that `newsfeedfetcher.js` used the old `.pipe()` method to connect streams (HTTP body → iconv decoding → RSS parser). `.pipe()` has a weakness: errors in one stream are **not** automatically forwarded to downstream streams. An I/O or decoding error would silently disappear. ## Solution Replaced `.pipe()` with `await stream.promises.pipeline()`. The `pipeline()` API is designed to propagate errors correctly through the entire chain and to clean up all streams on failure. Errors now reliably land in the `catch` block and call `fetchFailedCallback` exactly once. The redundant `parser.on("error")` handler was removed, as it would have caught the same error again and called the callback a second time. ## Why not the bot's suggested fix? The GitHub Bot suggested the older callback-based `stream.pipeline(callback)` variant: ```js stream.pipeline(nodeStream, iconv.decodeStream(...), parser, (error) => { if (!error) return; // error handling... }); ``` This has two drawbacks compared to my approach: 1. It uses the older callback style — `stream.promises.pipeline()` with `async/await` is the modern, more readable API. 2. The bot's suggestion kept both the `parser.on("error")` handler **and** the `catch` block, which would not have fixed the double-callback problem. ---- Related to #4073 --- defaultmodules/newsfeed/newsfeedfetcher.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) 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)); From dce2df63afaac1972a86c188aee90668695b7cec Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:56:11 +0200 Subject: [PATCH 396/418] refactor: replace implicit global config with explicit global.config (#4085) In PR #4072 the GitHub bot complained about a missing variable declaration for `config` in `app.js` and suggested adding `let config`. Applying that suggestion broke the app because `server_functions.js` was accessing `config` as an implicit global variable - the `let` declaration made it unreachable from there. So instead of the `let` declaration, I replaced all bare `config` references with explicit `global.config`. This makes the dependency on the global variable visible without changing runtime behavior, consistent with how other globals like `global.root_path` and `global.version` are already handled throughout the codebase. Related to #4073 --- js/app.js | 5 +++-- js/server_functions.js | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/js/app.js b/js/app.js index 398a1313a9..0e6cba45e0 100644 --- a/js/app.js +++ b/js/app.js @@ -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; @@ -245,7 +246,7 @@ function App () { Log.log("Sockets connected & modules started ..."); - return config; + return global.config; }; /** diff --git a/js/server_functions.js b/js/server_functions.js index 063e9cfe35..7a01cd247a 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -46,7 +46,7 @@ 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); } @@ -144,15 +144,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 +163,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}/`, ""); } From 03f268934a531f666ff7863a7e5659c9d507026b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:57:26 +0200 Subject: [PATCH 397/418] fix: prevent SSRF via /cors endpoint by blocking private/reserved IPs (#4084) Resolve target hostname before proxying and reject any address that is not globally routable (loopback, RFC 1918, link-local, etc.) using ipaddr.js and dns.lookup(). --- js/server_functions.js | 40 ++++++++- tests/unit/functions/server_functions_spec.js | 85 ++++++++++++++++++- 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/js/server_functions.js b/js/server_functions.js index 7a01cd247a..1d0f5e1ff5 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -1,9 +1,42 @@ +const dns = require("node:dns").promises; const fs = require("node:fs"); const path = require("node:path"); +const ipaddr = require("ipaddr.js"); const Log = require("logger"); const startUp = new Date(); +/** + * Checks whether a URL targets a private, reserved, or otherwise non-globally-routable address. + * Used to prevent SSRF (Server-Side Request Forgery) via the /cors proxy endpoint. + * @param {string} url - The URL to check. + * @returns {Promise} true if the target is private/reserved and should be blocked. + */ +async function isPrivateTarget (url) { + let parsed; + try { + parsed = new URL(url); + } catch { + return true; + } + + if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return true; + + const hostname = parsed.hostname.replace(/^\[|\]$/g, ""); + + if (hostname.toLowerCase() === "localhost") return true; + + try { + const results = await dns.lookup(hostname, { all: true }); + for (const { address } of results) { + if (ipaddr.process(address).range() !== "unicast") return true; + } + } catch { + return true; + } + return false; +} + /** * Gets the startup time. * @param {Request} req - the request @@ -52,6 +85,11 @@ async function cors (req, res) { } } + if (await isPrivateTarget(url)) { + Log.warn(`SSRF blocked: ${url}`); + return res.status(403).json({ error: "Forbidden: private or reserved addresses are not allowed" }); + } + const headersToSend = getHeadersToSend(req.url); const expectedReceivedHeaders = geExpectedReceivedHeaders(req.url); Log.log(`cors url: ${url}`); @@ -202,4 +240,4 @@ function getConfigFilePath () { return path.resolve(global.configuration_file || `${global.root_path}/config/config.js`); } -module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath, replaceSecretPlaceholder }; +module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath, replaceSecretPlaceholder, isPrivateTarget }; diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index 8fd0a01450..2b855e42a0 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -1,4 +1,12 @@ -const { cors, getUserAgent, replaceSecretPlaceholder } = require("#server_functions"); +const { cors, getUserAgent, replaceSecretPlaceholder, isPrivateTarget } = require("#server_functions"); + +const mockLookup = vi.fn(() => Promise.resolve([{ address: "93.184.216.34", family: 4 }])); + +vi.mock("node:dns", () => ({ + promises: { + lookup: mockLookup + } +})); describe("server_functions tests", () => { describe("The replaceSecretPlaceholder method", () => { @@ -53,7 +61,7 @@ describe("server_functions tests", () => { }; request = { - url: "/cors?url=www.test.com" + url: "/cors?url=http://www.test.com" }; }); @@ -182,4 +190,77 @@ describe("server_functions tests", () => { global.config = previousConfig; }); }); + + describe("The isPrivateTarget method", () => { + beforeEach(() => { + mockLookup.mockReset(); + }); + + it("Blocks unparseable URLs", async () => { + expect(await isPrivateTarget("not a url")).toBe(true); + }); + + it("Blocks non-http protocols", async () => { + expect(await isPrivateTarget("file:///etc/passwd")).toBe(true); + expect(await isPrivateTarget("ftp://internal/file")).toBe(true); + }); + + it("Blocks localhost", async () => { + expect(await isPrivateTarget("http://localhost/path")).toBe(true); + expect(await isPrivateTarget("http://LOCALHOST:8080/")).toBe(true); + }); + + it("Blocks private IPs (loopback)", async () => { + mockLookup.mockResolvedValue([{ address: "127.0.0.1", family: 4 }]); + expect(await isPrivateTarget("http://loopback.example.com/")).toBe(true); + }); + + it("Blocks private IPs (RFC 1918)", async () => { + mockLookup.mockResolvedValue([{ address: "192.168.1.1", family: 4 }]); + expect(await isPrivateTarget("http://internal.example.com/")).toBe(true); + }); + + it("Blocks link-local addresses", async () => { + mockLookup.mockResolvedValue([{ address: "169.254.169.254", family: 4 }]); + expect(await isPrivateTarget("http://metadata.example.com/")).toBe(true); + }); + + it("Blocks when DNS lookup fails", async () => { + mockLookup.mockRejectedValue(new Error("ENOTFOUND")); + expect(await isPrivateTarget("http://nonexistent.invalid/")).toBe(true); + }); + + it("Allows public unicast IPs", async () => { + mockLookup.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]); + expect(await isPrivateTarget("http://example.com/api")).toBe(false); + }); + + it("Blocks if any resolved address is private", async () => { + mockLookup.mockResolvedValue([ + { address: "93.184.216.34", family: 4 }, + { address: "127.0.0.1", family: 4 } + ]); + expect(await isPrivateTarget("http://dual.example.com/")).toBe(true); + }); + }); + + describe("The cors method blocks SSRF", () => { + it("Returns 403 for private target URLs", async () => { + mockLookup.mockReset(); + mockLookup.mockResolvedValue([{ address: "127.0.0.1", family: 4 }]); + + const request = { url: "/cors?url=http://127.0.0.1:8080/config" }; + const response = { + set: vi.fn(), + send: vi.fn(), + status: vi.fn(function () { return this; }), + json: vi.fn() + }; + + await cors(request, response); + + expect(response.status).toHaveBeenCalledWith(403); + expect(response.json).toHaveBeenCalledWith({ error: "Forbidden: private or reserved addresses are not allowed" }); + }); + }); }); From abf6989faa91f4886459637393fe66268d132290 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sat, 4 Apr 2026 11:55:13 +0200 Subject: [PATCH 398/418] add option to disable or restrict cors endpoint (#4087) --- js/defaults.js | 2 ++ js/server_functions.js | 5 +++++ tests/unit/functions/server_functions_spec.js | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+) 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/server_functions.js b/js/server_functions.js index 1d0f5e1ff5..b1b0b19c83 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -25,6 +25,7 @@ async function isPrivateTarget (url) { const hostname = parsed.hostname.replace(/^\[|\]$/g, ""); if (hostname.toLowerCase() === "localhost") return true; + if (global.config.cors === "allowWhitelist" && !global.config.corsDomainWhitelist.includes(hostname.toLowerCase())) return true; try { const results = await dns.lookup(hostname, { all: true }); @@ -68,6 +69,10 @@ 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" }); + } try { const urlRegEx = "url=(.+?)$"; let url; diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index 2b855e42a0..979a6a633d 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -35,6 +35,7 @@ describe("server_functions tests", () => { let fetchMock; beforeEach(() => { + global.config = { cors: "allowAll" }; fetchResponseHeadersGet = vi.fn(() => {}); fetchResponseArrayBuffer = vi.fn(() => {}); fetchResponse = { @@ -263,4 +264,22 @@ describe("server_functions tests", () => { expect(response.json).toHaveBeenCalledWith({ error: "Forbidden: private or reserved addresses are not allowed" }); }); }); + + describe("The isPrivateTarget method with allowWhitelist", () => { + beforeEach(() => { + mockLookup.mockReset(); + }); + + it("Block public unicast IPs if not whitelistet", async () => { + global.config = { cors: "allowWhitelist", corsDomainWhitelist: [] }; + mockLookup.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]); + expect(await isPrivateTarget("http://example.com/api")).toBe(true); + }); + + it("Allow public unicast IPs if whitelistet", async () => { + global.config = { cors: "allowWhitelist", corsDomainWhitelist: ["example.com"] }; + mockLookup.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]); + expect(await isPrivateTarget("http://example.com/api")).toBe(false); + }); + }); }); From 512e7461e4f596fc2bdb7af3979c1a12c35f4f73 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 4 Apr 2026 15:01:27 +0200 Subject: [PATCH 399/418] chore: update dependencies (#4088) `node-ical` has released a new version that fixes an issue reported by one of our users (https://github.com/jens-maus/node-ical/issues/495). I'd like to have that in the develop branch. Instead of just updating that, I think it would make sense to include the others as well. `undici` had a major release but according to the release notes we are not affected. --- package-lock.json | 218 ++++++++++++++++++++++------------------------ package.json | 12 +-- 2 files changed, 110 insertions(+), 120 deletions(-) diff --git a/package-lock.json b/package-lock.json index 70164861a9..f6fe447651 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "ajv": "^8.18.0", "animate.css": "^4.1.1", "croner": "^10.0.1", - "eslint": "^10.1.0", + "eslint": "^10.2.0", "express": "^5.2.1", "feedme": "^2.0.2", "globals": "^17.4.0", @@ -26,13 +26,13 @@ "ipaddr.js": "^2.3.0", "moment": "^2.30.1", "moment-timezone": "^0.6.1", - "node-ical": "^0.25.6", + "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.0.2", "weathericons": "^2.1.0" }, "devDependencies": { @@ -43,7 +43,7 @@ "@vitest/ui": "^4.1.2", "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.2", - "eslint-plugin-jsdoc": "^62.8.1", + "eslint-plugin-jsdoc": "^62.9.0", "eslint-plugin-package-json": "^0.91.1", "eslint-plugin-playwright": "^2.10.1", "express-basic-auth": "^1.2.1", @@ -52,7 +52,7 @@ "lint-staged": "^16.4.0", "markdownlint-cli2": "^0.22.0", "msw": "^2.12.14", - "playwright": "^1.58.2", + "playwright": "^1.59.1", "prettier": "^3.8.1", "prettier-plugin-jinja-template": "^2.1.0", "stylelint": "^17.6.0", @@ -64,7 +64,7 @@ "node": ">=22.21.1 <23 || >=24" }, "optionalDependencies": { - "electron": "^41.1.0" + "electron": "^41.1.1" } }, "node_modules/@altano/repository-tools": { @@ -75,9 +75,9 @@ "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.5", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.5.tgz", + "integrity": "sha512-8cMAA1bE66Mb/tfmkhcfJLjEPgyT7SSy6lW6id5XL113ai1ky76d/1L27sGnXCMsLfq66DInAU3OzuahB4lu9Q==", "dev": true, "license": "MIT", "dependencies": { @@ -92,9 +92,9 @@ } }, "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.0.6", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.0.6.tgz", + "integrity": "sha512-Tgmk6EQM0nc9xvp7sEHRVavbknhb/vGKht+04yAT3t5KQwZ02CSobCtcFgaHH04ZrjD1BhEKNA8tRhzFV20gkA==", "dev": true, "license": "MIT", "dependencies": { @@ -1153,14 +1153,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.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", "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 +1173,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.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", "dev": true, "license": "MIT", "optional": true, @@ -1192,9 +1192,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 +1211,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 +1277,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.4", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.4.tgz", + "integrity": "sha512-lf19F24LSMfF8weXvW5QEtnLqW70u7kgit5e9PSx0MsHAFclGd1T9ynvWEMDT1w5J4Qt54tomGeAhdoAku1Xow==", "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^3.0.3", + "@eslint/object-schema": "^3.0.4", "debug": "^4.3.1", "minimatch": "^10.2.4" }, @@ -1301,21 +1291,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.4", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.4.tgz", + "integrity": "sha512-jJhqiY3wPMlWWO3370M86CPJ7pt8GmEwSLglMfQhjXal07RCvhmU0as4IuUEW5SJeunfItiEetHmSxCCe9lDBg==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^1.1.1" + "@eslint/core": "^1.2.0" }, "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.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.0.tgz", + "integrity": "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -1346,21 +1336,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.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.4.tgz", + "integrity": "sha512-55lO/7+Yp0ISKRP0PsPtNTeNGapXaO085aELZmWCVc5SH3jfrqpuU6YgOdIxMS99ZHkQN1cXKE+cdIqwww9ptw==", "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.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.0.tgz", + "integrity": "sha512-ejvBr8MQCbVsWNZnCwDXjUKq40MDmHalq7cJ6e9s/qzTUFIIo/afzt1Vui9T97FM/V/pN4YsFVoed5NIa96RDg==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^1.1.1", + "@eslint/core": "^1.2.0", "levn": "^0.4.1" }, "engines": { @@ -2566,9 +2556,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" @@ -4850,9 +4840,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.1.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-41.1.1.tgz", + "integrity": "sha512-8bgvDhBjli+3Z2YCKgzzoBPh6391pr7Xv2h/tTJG4ETgvPvUxZomObbZLs31mUzYb6VrlcDDd9cyWyNKtPm3tA==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5145,17 +5135,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.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.0.tgz", + "integrity": "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==", "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.4", + "@eslint/config-helpers": "^0.5.4", + "@eslint/core": "^1.2.0", + "@eslint/plugin-kit": "^0.7.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -5282,19 +5272,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 +5300,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", @@ -6990,9 +6970,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": { @@ -7040,6 +7020,16 @@ } } }, + "node_modules/jsdom/node_modules/undici": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.7.tgz", + "integrity": "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==", + "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", @@ -7548,9 +7538,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": { @@ -8706,16 +8696,16 @@ } }, "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": { @@ -9201,13 +9191,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 +9210,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": { @@ -9984,9 +9974,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 +9984,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.2", + "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.5.2.tgz", + "integrity": "sha512-I5rAiZfRlMh0vuG23HrGBMLZOSiQO7H1Uq8l9qyfA6oTD5j+UMRwpRs4aVU4XdaFhgN1p3K+cHelG8KvLTTm+g==", "license": "MIT", "dependencies": { "@js-temporal/polyfill": "^0.5.1" @@ -11367,12 +11357,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.0.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.0.2.tgz", + "integrity": "sha512-B9MeU5wuFhkFAuNeA19K2GDFcQXZxq33fL0nRy2Aq30wdufZbyyvxW3/ChaeipXVfy/wUweZyzovQGk39+9k2w==", "license": "MIT", "engines": { - "node": ">=20.18.1" + "node": ">=22.19.0" } }, "node_modules/undici-types": { diff --git a/package.json b/package.json index 99944006ba..827bc9176e 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "ajv": "^8.18.0", "animate.css": "^4.1.1", "croner": "^10.0.1", - "eslint": "^10.1.0", + "eslint": "^10.2.0", "express": "^5.2.1", "feedme": "^2.0.2", "globals": "^17.4.0", @@ -103,13 +103,13 @@ "ipaddr.js": "^2.3.0", "moment": "^2.30.1", "moment-timezone": "^0.6.1", - "node-ical": "^0.25.6", + "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.0.2", "weathericons": "^2.1.0" }, "devDependencies": { @@ -120,7 +120,7 @@ "@vitest/ui": "^4.1.2", "cspell": "^9.7.0", "eslint-plugin-import-x": "^4.16.2", - "eslint-plugin-jsdoc": "^62.8.1", + "eslint-plugin-jsdoc": "^62.9.0", "eslint-plugin-package-json": "^0.91.1", "eslint-plugin-playwright": "^2.10.1", "express-basic-auth": "^1.2.1", @@ -129,7 +129,7 @@ "lint-staged": "^16.4.0", "markdownlint-cli2": "^0.22.0", "msw": "^2.12.14", - "playwright": "^1.58.2", + "playwright": "^1.59.1", "prettier": "^3.8.1", "prettier-plugin-jinja-template": "^2.1.0", "stylelint": "^17.6.0", @@ -138,7 +138,7 @@ "vitest": "^4.1.2" }, "optionalDependencies": { - "electron": "^41.1.0" + "electron": "^41.1.1" }, "engines": { "node": ">=22.21.1 <23 || >=24" From f07932442660769f15f275ee2ec0bce57771d260 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:39:53 +0200 Subject: [PATCH 400/418] ci(codeql): also scan develop branch on push and PR (#4086) Previously only master was scanned via the default CodeQL setup. Since development happens on develop, this PR replaces the default setup with a custom workflow that covers both branches. This gives an overview of the security status across the current release (master) and the development branch (develop). As a result we should also see issues in the develop branch here: https://github.com/MagicMirrorOrg/MagicMirror/security/code-scanning --- .github/workflows/codeql.yaml | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/codeql.yaml 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 }}" From 96c18ec8b07eee36da3b35716caa074a84f40de3 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 4 Apr 2026 20:40:14 +0200 Subject: [PATCH 401/418] fix(cors): prevent SSRF via DNS rebinding (#4090) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #4084 blocked SSRF by checking the IP before `fetch()` — but `fetch()` resolves DNS again on its own. With DNS rebinding (TTL=0, alternating IPs) an attacker can slip a private IP through between check and connection. Fix: resolve DNS once, validate, pin the validated IP for the connection. No second DNS query → no rebinding window. `isPrivateTarget()` is gone, code is shorter than before. Not a likely attack for a typical MagicMirror setup, but it doesn't add complexity so there's no reason not to close the gap. --- js/server_functions.js | 78 ++++---- tests/unit/functions/server_functions_spec.js | 174 +++++++++--------- 2 files changed, 124 insertions(+), 128 deletions(-) diff --git a/js/server_functions.js b/js/server_functions.js index b1b0b19c83..9d4aff4704 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -1,43 +1,12 @@ -const dns = require("node:dns").promises; +const dns = require("node:dns"); const fs = require("node:fs"); const path = require("node:path"); const ipaddr = require("ipaddr.js"); +const { Agent } = require("undici"); const Log = require("logger"); const startUp = new Date(); -/** - * Checks whether a URL targets a private, reserved, or otherwise non-globally-routable address. - * Used to prevent SSRF (Server-Side Request Forgery) via the /cors proxy endpoint. - * @param {string} url - The URL to check. - * @returns {Promise} true if the target is private/reserved and should be blocked. - */ -async function isPrivateTarget (url) { - let parsed; - try { - parsed = new URL(url); - } catch { - return true; - } - - if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return true; - - const hostname = parsed.hostname.replace(/^\[|\]$/g, ""); - - if (hostname.toLowerCase() === "localhost") return true; - if (global.config.cors === "allowWhitelist" && !global.config.corsDomainWhitelist.includes(hostname.toLowerCase())) return true; - - try { - const results = await dns.lookup(hostname, { all: true }); - for (const { address } of results) { - if (ipaddr.process(address).range() !== "unicast") return true; - } - } catch { - return true; - } - return false; -} - /** * Gets the startup time. * @param {Request} req - the request @@ -73,9 +42,9 @@ async function cors (req, res) { 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) { @@ -90,16 +59,48 @@ async function cors (req, res) { } } - if (await isPrivateTarget(url)) { - Log.warn(`SSRF blocked: ${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 Agent({ connect: { lookup: (_h, _o, cb) => cb(null, address, family) } }); + + const response = await fetch(url, { dispatcher, headers: headersToSend }); if (response.ok) { for (const header of expectedReceivedHeaders) { const headerValue = response.headers.get(header); @@ -112,7 +113,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}`); } @@ -245,4 +245,4 @@ function getConfigFilePath () { return path.resolve(global.configuration_file || `${global.root_path}/config/config.js`); } -module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath, replaceSecretPlaceholder, isPrivateTarget }; +module.exports = { cors, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent, getConfigFilePath, replaceSecretPlaceholder }; diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index 979a6a633d..ebb1d67893 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -1,12 +1,10 @@ -const { cors, getUserAgent, replaceSecretPlaceholder, isPrivateTarget } = require("#server_functions"); - -const mockLookup = vi.fn(() => Promise.resolve([{ address: "93.184.216.34", family: 4 }])); - -vi.mock("node:dns", () => ({ - promises: { - lookup: mockLookup - } -})); +// Tests use vi.spyOn on shared module objects (dns, global.fetch). +// 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 { cors, getUserAgent, replaceSecretPlaceholder } = require("#server_functions"); describe("server_functions tests", () => { describe("The replaceSecretPlaceholder method", () => { @@ -27,29 +25,29 @@ describe("server_functions tests", () => { }); 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(global, "fetch"); + fetchSpy.mockClear(); + fetchSpy.mockImplementation(() => Promise.resolve({ + headers: { get: fetchResponseHeadersGet }, + arrayBuffer: fetchResponseArrayBuffer, + ok: true + })); corsResponse = { set: vi.fn(() => {}), @@ -72,8 +70,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 () => { @@ -135,9 +133,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 () => { @@ -147,10 +145,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 () => { @@ -162,8 +160,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"); @@ -192,94 +190,92 @@ describe("server_functions tests", () => { }); }); - describe("The isPrivateTarget method", () => { + describe("The cors method blocks SSRF (DNS rebinding safe)", () => { + let response; + beforeEach(() => { - mockLookup.mockReset(); + response = { + set: vi.fn(), + send: vi.fn(), + status: vi.fn(function () { return this; }), + json: vi.fn() + }; }); - it("Blocks unparseable URLs", async () => { - expect(await isPrivateTarget("not a url")).toBe(true); + 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 () => { - expect(await isPrivateTarget("file:///etc/passwd")).toBe(true); - expect(await isPrivateTarget("ftp://internal/file")).toBe(true); - }); - - it("Blocks localhost", async () => { - expect(await isPrivateTarget("http://localhost/path")).toBe(true); - expect(await isPrivateTarget("http://LOCALHOST:8080/")).toBe(true); - }); - - it("Blocks private IPs (loopback)", async () => { - mockLookup.mockResolvedValue([{ address: "127.0.0.1", family: 4 }]); - expect(await isPrivateTarget("http://loopback.example.com/")).toBe(true); + await cors({ url: "/cors?url=ftp://example.com/file" }, response); + expect(response.status).toHaveBeenCalledWith(403); }); - it("Blocks private IPs (RFC 1918)", async () => { - mockLookup.mockResolvedValue([{ address: "192.168.1.1", family: 4 }]); - expect(await isPrivateTarget("http://internal.example.com/")).toBe(true); + it("Blocks invalid URLs", async () => { + await cors({ url: "/cors?url=not_a_valid_url" }, response); + expect(response.status).toHaveBeenCalledWith(403); }); - it("Blocks link-local addresses", async () => { - mockLookup.mockResolvedValue([{ address: "169.254.169.254", family: 4 }]); - expect(await isPrivateTarget("http://metadata.example.com/")).toBe(true); + 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 when DNS lookup fails", async () => { - mockLookup.mockRejectedValue(new Error("ENOTFOUND")); - expect(await isPrivateTarget("http://nonexistent.invalid/")).toBe(true); + 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("Allows public unicast IPs", async () => { - mockLookup.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]); - expect(await isPrivateTarget("http://example.com/api")).toBe(false); + 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("Blocks if any resolved address is private", async () => { - mockLookup.mockResolvedValue([ - { address: "93.184.216.34", family: 4 }, - { address: "127.0.0.1", family: 4 } - ]); - expect(await isPrivateTarget("http://dual.example.com/")).toBe(true); + 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("The cors method blocks SSRF", () => { - it("Returns 403 for private target URLs", async () => { - mockLookup.mockReset(); - mockLookup.mockResolvedValue([{ address: "127.0.0.1", family: 4 }]); + describe("cors method with allowWhitelist", () => { + let response; - const request = { url: "/cors?url=http://127.0.0.1:8080/config" }; - const response = { + beforeEach(() => { + response = { set: vi.fn(), send: vi.fn(), status: vi.fn(function () { return this; }), json: vi.fn() }; - - await cors(request, response); - - expect(response.status).toHaveBeenCalledWith(403); - expect(response.json).toHaveBeenCalledWith({ error: "Forbidden: private or reserved addresses are not allowed" }); - }); - }); - - describe("The isPrivateTarget method with allowWhitelist", () => { - beforeEach(() => { - mockLookup.mockReset(); + 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("Block public unicast IPs if not whitelistet", async () => { + it("Blocks domains not in whitelist", async () => { global.config = { cors: "allowWhitelist", corsDomainWhitelist: [] }; - mockLookup.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]); - expect(await isPrivateTarget("http://example.com/api")).toBe(true); + await cors({ url: "/cors?url=http://example.com/api" }, response); + expect(response.status).toHaveBeenCalledWith(403); }); - it("Allow public unicast IPs if whitelistet", async () => { + it("Allows domains in whitelist", async () => { global.config = { cors: "allowWhitelist", corsDomainWhitelist: ["example.com"] }; - mockLookup.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]); - expect(await isPrivateTarget("http://example.com/api")).toBe(false); + await cors({ url: "/cors?url=http://example.com/api" }, response); + expect(response.status).not.toHaveBeenCalledWith(403); }); }); }); From 0da343b9611db67b441ff7c16ea9e90066d1a19e Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 5 Apr 2026 21:42:02 +0200 Subject: [PATCH 402/418] fix(weather): use stable instanceId to prevent duplicate fetchers (#4092) During the server-side migration (PR #4032), the `instanceId` was built with `Date.now()`, making it unique per client reload. This approach was fine in the old browser-based architecture where reloads cleaned up everything automatically. But now the node_helper persists across reloads, so each reconnect created a new `HTTPFetcher` while the old one kept polling - silently multiplying API calls over time. The fix is simple: use `this.identifier` as the `instanceId`, which is already stable and unique per module slot. This is the same approach the Calendar module uses. On the node_helper side, when a provider already exists for the same `instanceId`, we now skip re-creation and just resend `WEATHER_INITIALIZED` so the client picks up where it left off. Fixes https://forum.magicmirror.builders/topic/20199 --- defaultmodules/weather/node_helper.js | 7 ++++++- defaultmodules/weather/weather.js | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/defaultmodules/weather/node_helper.js b/defaultmodules/weather/node_helper.js index f9ea08c42a..cda81a5140 100644 --- a/defaultmodules/weather/node_helper.js +++ b/defaultmodules/weather/node_helper.js @@ -31,7 +31,12 @@ 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 + }); return; } diff --git a/defaultmodules/weather/weather.js b/defaultmodules/weather/weather.js index 732958e6c8..d3fbeb13ac 100644 --- a/defaultmodules/weather/weather.js +++ b/defaultmodules/weather/weather.js @@ -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); From 9b97add1aebb47b2521f5349e34f1389fa8d305a Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 5 Apr 2026 21:42:32 +0200 Subject: [PATCH 403/418] fix cors function for alpine linux (#4091) I provide docker images with alpine linux and tested the new cors approach. It didn't work because after calling ```js const dispatcher = new Agent({ connect: { lookup: (_h, _o, cb) => cb(null, address, family) } }); ``` the dispatcher variable was undefined. This PR solves this and I tested this under debian too. The mix of internal fetch and newer undici did not work and alpine needs additionally the `process.nextTick`. --------- Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> --- js/server_functions.js | 13 ++++++++++--- tests/unit/functions/server_functions_spec.js | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/js/server_functions.js b/js/server_functions.js index 9d4aff4704..9650257c27 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -2,7 +2,7 @@ const dns = require("node:dns"); const fs = require("node:fs"); const path = require("node:path"); const ipaddr = require("ipaddr.js"); -const { Agent } = require("undici"); +const undici = require("undici"); const Log = require("logger"); const startUp = new Date(); @@ -98,9 +98,16 @@ async function cors (req, res) { } // Pin the validated IP — fetch() reuses it instead of doing its own DNS lookup - const dispatcher = new Agent({ connect: { lookup: (_h, _o, cb) => cb(null, address, family) } }); + const dispatcher = new undici.Agent({ + connect: { + lookup: (_h, _o, cb) => { + const addresses = [{ address: address, family: family }]; + process.nextTick(() => cb(null, addresses)); + } + } + }); - const response = await fetch(url, { dispatcher, headers: headersToSend }); + const response = await undici.fetch(url, { dispatcher, headers: headersToSend }); if (response.ok) { for (const header of expectedReceivedHeaders) { const headerValue = response.headers.get(header); diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index ebb1d67893..779daaf08e 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -1,9 +1,10 @@ -// Tests use vi.spyOn on shared module objects (dns, global.fetch). +// 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", () => { @@ -41,7 +42,7 @@ describe("server_functions tests", () => { // 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(global, "fetch"); + fetchSpy = vi.spyOn(undici, "fetch"); fetchSpy.mockClear(); fetchSpy.mockImplementation(() => Promise.resolve({ headers: { get: fetchResponseHeadersGet }, From d8c29d5ec3967bb856e5b6deb209608a9e477970 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 7 Apr 2026 21:15:25 +0200 Subject: [PATCH 404/418] fix: prevent crash when config is undefined in socket handler (#4096) If a module uses this.io.of() to register a custom socket.io namespace, connections on that namespace trigger the onAny handler in setSocketIO before config is set, causing a TypeError. Fixes #4089 --- js/node_helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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)); From 2e97e29ab52ffeabd6a7b83ce3186aec0057c682 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Wed, 8 Apr 2026 18:42:30 +0200 Subject: [PATCH 405/418] fix(http_fetcher): use undici.fetch when dispatcher is present (#4097) ### What's the problem? The `selfSignedCert` option passes an undici `Agent` as `dispatcher` to `fetch()`. But Node's built-in `fetch()` and undici@8's `Agent` use different internal handler APIs - passing them together throws: ``` invalid onRequestStart method ``` ### What's the fix? When `selfSignedCert` is enabled (i.e. a `dispatcher` is set), use undici's own `fetch()` instead of the global one. For all other requests, keep using `globalThis.fetch`. ```js const fetchFn = requestOptions.dispatcher ? undiciFetch : globalThis.fetch; ``` ### Why not just always use undici's fetch? That would fix the crash - but it would break some tests. MSW (Mock Service Worker), which is used in our test suite to intercept HTTP requests, only hooks into `globalThis.fetch`. Undici's fetch bypasses those interceptors entirely, so tests would start making real network requests instead of getting the mocked responses. We could rewrite all tests to use undici-compatible mocking instead - but that would be a massive change for no real benefit. ---- Fixes #4093 --- js/http_fetcher.js | 11 ++++++--- tests/unit/functions/http_fetcher_spec.js | 29 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/js/http_fetcher.js b/js/http_fetcher.js index 830b08bd17..0766168401 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"); @@ -263,8 +263,13 @@ 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 }); diff --git a/tests/unit/functions/http_fetcher_spec.js b/tests/unit/functions/http_fetcher_spec.js index 046ddb9ca0..0d8d41be50 100644 --- a/tests/unit/functions/http_fetcher_spec.js +++ b/tests/unit/functions/http_fetcher_spec.js @@ -440,3 +440,32 @@ 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(); + }); +}); From 22a58d4ae59d7bd2159ebafd1f1faf8c9ec49d0a Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:20:41 +0200 Subject: [PATCH 406/418] fix(weather): restore OpenWeatherMap v2.5 support (#4101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the big weather refactor (#4032), OpenWeatherMap was effectively hard-wired to One Call v3. One Call 2.5 is deprecated and no longer available, so it looked like v2.5 support was effectively over — but the classic `/weather` and `/forecast` endpoints were never actually dropped. This restores support for those. Fixes #4100. ## What this PR does - handles OpenWeatherMap responses by endpoint again (`/onecall`, `/weather`, `/forecast`) - restores v2.5 current and forecast support (including hourly via 3-hour forecast slots) - filters outdated hourly entries centrally while keeping the current hour visible (if available) ## Screenshot bildo --- .../weather/providers/openweathermap.js | 172 ++++++++-- defaultmodules/weather/weather.js | 20 +- tests/mocks/weather_owm_current.json | 28 ++ tests/mocks/weather_owm_forecast.json | 180 ++++++++++ .../weather/providers/openweathermap_spec.js | 319 ++++++++++++++++++ 5 files changed, 696 insertions(+), 23 deletions(-) create mode 100644 tests/mocks/weather_owm_current.json create mode 100644 tests/mocks/weather_owm_forecast.json 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/weather.js b/defaultmodules/weather/weather.js index d3fbeb13ac..e40e41a4cd 100644 --- a/defaultmodules/weather/weather.js +++ b/defaultmodules/weather/weather.js @@ -5,7 +5,7 @@ Module.register("weather", { 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, @@ -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/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/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); + }); + }); }); From 39578d69b40291c7d22cdb25c0dd1746e3414a04 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Fri, 10 Apr 2026 23:11:57 +0200 Subject: [PATCH 407/418] restrict replaceSecretPlaceholder to cors with allowWhitelist (#4102) and cleanup spelling --- cspell.config.json | 19 +++++++++++++++ js/server_functions.js | 11 ++++++--- tests/unit/functions/server_functions_spec.js | 24 ++++++++++++++++++- 3 files changed, 50 insertions(+), 4 deletions(-) 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/js/server_functions.js b/js/server_functions.js index 9650257c27..bdc759c64e 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -22,9 +22,14 @@ 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 === "allowWhitelist") { + return input.replaceAll(/\*\*(SECRET_[^*]+)\*\*/g, (match, group) => { + return process.env[group]; + }); + } else { + Log.error("Replacing secrets works only with CORS and `allowWhitelist`, you need to set this in `config.js`, set `cors: allowWhitelist`"); + return input; + } } /** diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index 779daaf08e..8c38cf9f0a 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -8,7 +8,11 @@ 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); @@ -25,6 +29,24 @@ 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 fetchSpy; let fetchResponseHeadersGet; From 61870ae6236192f9ecff4ac62a71c1a7af3a3581 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 12 Apr 2026 00:46:10 +0200 Subject: [PATCH 408/418] fix replaceSecretPlaceholder (#4104) Disable secret substitution only for cors=allowAll, the last attempt in #4102 was to restrictive. Secret substitution should also work if cors=disabled. --------- Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> --- js/server_functions.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/server_functions.js b/js/server_functions.js index bdc759c64e..2d55bc3b44 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -22,12 +22,14 @@ function getStartup (req, res) { * @returns {string} the input with real variable content */ function replaceSecretPlaceholder (input) { - if (global.config.cors === "allowWhitelist") { + if (global.config.cors !== "allowAll") { return input.replaceAll(/\*\*(SECRET_[^*]+)\*\*/g, (match, group) => { return process.env[group]; }); } else { - Log.error("Replacing secrets works only with CORS and `allowWhitelist`, you need to set this in `config.js`, set `cors: allowWhitelist`"); + 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; } } From d3a3ad9caf948170787eaea9c8857cdbffcd7060 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Sun, 12 Apr 2026 22:50:00 +0200 Subject: [PATCH 409/418] config endpoint must handle functions in module configs (#4106) Fixes #4105 ```bash In JavaScript, standard JSON does not support functions. If you use JSON.stringify() on an object containing functions, those functions will be omitted (if they are object properties) or changed to null (if they are in an array). ``` --------- Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> --- js/main.js | 15 ++++++++++++- js/server.js | 19 +++++++++++----- tests/configs/config_functions.js | 35 ++++++++++++++++++++++++++++++ tests/e2e/config_functions_spec.js | 21 ++++++++++++++++++ 4 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 tests/configs/config_functions.js create mode 100644 tests/e2e/config_functions_spec.js diff --git a/js/main.js b/js/main.js index 0e20c41e82..73d6075f3b 100644 --- a/js/main.js +++ b/js/main.js @@ -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/server.js b/js/server.js index 081e90892c..f8a51e714d 100644 --- a/js/server.js +++ b/js/server.js @@ -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/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"); + }); +}); From de3f57f8afd9197af2e99680f84d021f4b982b1f Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 19 Apr 2026 12:50:20 +0200 Subject: [PATCH 410/418] weather: fix UV index display and add WeatherFlow precipitation (#4108) While looking at the WeatherFlow provider (to evaluate #4107), I noticed a few things that weren't quite right. 1. **UV index was broken for most providers in forecast/hourly views.** The templates read `uv_index`, but only the WeatherAPI provider actually wrote that key. All other providers (OpenWeatherMap, WeatherFlow, PirateWeather, etc.) use `uvIndex` - so UV was silently never displayed for them. This went unnoticed because `showUVIndex` defaults to `false` and there were no test assertions for it. Standardized everything on `uvIndex` and added test coverage. 2. **WeatherFlow didn't map precipitation for current weather.** The API provides `precip_accum_local_day` and `precip_probability`, but they weren't passed through. While adding them I also noticed the template used truthiness checks, which hid valid zero values. Fixed both. 3. **`||` vs `??` in WeatherFlow provider.** Several numeric fields used `|| null`, replacing valid `0` with `null`. Switched to `??` for correctness. --- defaultmodules/weather/current.njk | 6 ++-- defaultmodules/weather/forecast.njk | 2 +- defaultmodules/weather/hourly.njk | 4 +-- .../weather/providers/weatherapi.js | 4 +-- .../weather/providers/weatherflow.js | 33 ++++++++++--------- .../weather/providers/weatherapi_spec.js | 2 ++ .../weather/providers/weatherflow_spec.js | 3 ++ 7 files changed, 31 insertions(+), 23 deletions(-) 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/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/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(); }); From 3f2a0302eb1dd77befeca97ab568e7ff8d91b321 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:36:39 +0200 Subject: [PATCH 411/418] ci(actions): set explicit token permissions (#4114) Add minimal GITHUB_TOKEN permissions to electron-rebuild workflow to enforce least privilege and satisfy CodeQL alert [#14](https://github.com/MagicMirrorOrg/MagicMirror/security/code-scanning/14). --- .github/workflows/electron-rebuild.yaml | 3 +++ 1 file changed, 3 insertions(+) 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: From 7e1286257cf8451babe9c64a218cd570a3880e23 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:01:42 +0200 Subject: [PATCH 412/418] fix(http-fetcher): fall back to reloadInterval after retries exhausted (#4113) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As reported in #4109, the weather module retries much more frequently than expected after network errors. #4092 already fixed the main cause (duplicate fetchers), but the backoff logic in `HTTPFetcher` still has a gap: once retries are exhausted, `calculateBackoffDelay` keeps returning a short fixed delay (60s) instead of falling back to `reloadInterval`. The same problem existed for 5xx errors, where the delay grew to 8× the configured interval. Inspired by #4110 (thanks @CodeLine9), this PR makes both error paths fall back to `reloadInterval` after retries are exhausted. I also simplified the catch block, extracted a `#shortenUrl()` helper for log messages, and added tests for the backoff progression. --- js/http_fetcher.js | 78 +++++++++++----------- tests/unit/functions/http_fetcher_spec.js | 80 +++++++++++++++++++++++ 2 files changed, 120 insertions(+), 38 deletions(-) diff --git a/js/http_fetcher.js b/js/http_fetcher.js index 0766168401..7ec1d9a155 100644 --- a/js/http_fetcher.js +++ b/js/http_fetcher.js @@ -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 { @@ -293,28 +313,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 { - // 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( @@ -324,18 +338,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/tests/unit/functions/http_fetcher_spec.js b/tests/unit/functions/http_fetcher_spec.js index 0d8d41be50..be71c77028 100644 --- a/tests/unit/functions/http_fetcher_spec.js +++ b/tests/unit/functions/http_fetcher_spec.js @@ -469,3 +469,83 @@ describe("selfSignedCert dispatcher", () => { 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); + }); +}); From 9dc4b7a88f322e3c975c7ce077e5790156474d7b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:06:29 +0200 Subject: [PATCH 413/418] fix(updatenotification): harden git command execution + simplify checkUpdates (#4115) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes CodeQL alert [#16](https://github.com/MagicMirrorOrg/MagicMirror/security/code-scanning/16) by replacing shell-built git commands with `execFile` + `cwd` in updatenotification’s `git_helper`. It also includes a small cleanup in `checkUpdates()` (remove unnecessary async/Promise wrapper) and updates the related unit tests. --- .../updatenotification/git_helper.js | 40 ++--- .../unit/functions/updatenotification_spec.js | 170 +++++++++--------- 2 files changed, 104 insertions(+), 106 deletions(-) diff --git a/defaultmodules/updatenotification/git_helper.js b/defaultmodules/updatenotification/git_helper.js index a9c577b798..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}`); @@ -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/tests/unit/functions/updatenotification_spec.js b/tests/unit/functions/updatenotification_spec.js index e5c9654fa4..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(); @@ -23,7 +23,7 @@ async function createGitHelper (fsStatSyncMockRef, loggerMockRef, execShellSpyRe 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", + ] + `); }); }); }); From b8548f2203a180df23832fca4025282bd50f33b8 Mon Sep 17 00:00:00 2001 From: Sonny B <43247590+sonnyb9@users.noreply.github.com> Date: Mon, 27 Apr 2026 17:09:20 -0400 Subject: [PATCH 414/418] Allow HTTPFetcher to pass through 304 responses (#4120) ## Summary This updates `js/http_fetcher.js` so HTTP `304 Not Modified` responses are emitted through the normal `response` event instead of being treated as errors. That aligns the core fetcher with the built-in `yr` weather provider in `v2.35.0`, which already includes explicit logic to handle `304` and reuse cached data. Closes #4119. ## Root cause `HTTPFetcher` currently treats all non-OK responses as errors. Since `304` is not an OK response, it never reaches providers listening on the `response` event. At the same time, `defaultmodules/weather/providers/yr.js` expects to receive `304` and handle it by reusing cached data. ## What changed - special-case HTTP `304` in `HTTPFetcher` - emit `304` through the normal `response` event - preserve the existing error path for other non-OK statuses ## Validation - confirmed `defaultmodules/weather/providers/yr.js` already expects `response.status === 304` - compared the unpatched `v2.35.0` `HTTPFetcher` behavior to the provider logic - ran `node --check js/http_fetcher.js` Co-authored-by: sonnyb9 --- js/http_fetcher.js | 4 +++- tests/unit/functions/http_fetcher_spec.js | 25 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/js/http_fetcher.js b/js/http_fetcher.js index 7ec1d9a155..b2d7b8c083 100644 --- a/js/http_fetcher.js +++ b/js/http_fetcher.js @@ -293,7 +293,9 @@ class HTTPFetcher extends EventEmitter { 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); diff --git a/tests/unit/functions/http_fetcher_spec.js b/tests/unit/functions/http_fetcher_spec.js index be71c77028..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, () => { From 4c2a373ae32e933d8f6df249065619d4cedf89f1 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:15:01 +0200 Subject: [PATCH 415/418] fix(weather): avoid loading state after reconnect (#4121) When a client reconnects while the backend is still in its rate-limit protection phase, the weather module has no data to show and stays on `Loading...` until the next scheduled API call. This mainly affects server mode setups, where the server keeps running while a remote client temporarily loses its connection and reloads. It was [raised in the forum](https://forum.magicmirror.builders/topic/20218/request-loop-loading...-in-standard-weather-module-open-meteo-after-update/11?_=1777106416020) and is worthy of a fix to improve the user experience. With this PR the node helper caches the last successful `WEATHER_DATA` payload per instance and replays it immediately on reconnect. The client gets its last known state right away instead of waiting for the next fetch. The cache is cleaned up when the provider stops. Tests are included to cover reconnect with and without cached data, and the cleanup path. --- defaultmodules/weather/node_helper.js | 14 ++- .../default/weather/node_helper_spec.js | 116 ++++++++++++++++++ 2 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 tests/unit/modules/default/weather/node_helper_spec.js diff --git a/defaultmodules/weather/node_helper.js b/defaultmodules/weather/node_helper.js index cda81a5140..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}`); @@ -37,6 +38,10 @@ module.exports = NodeHelper.create({ 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; } @@ -53,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 @@ -101,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/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(); + }); +}); From 8af3d02cbbba20f721b5ce4f909e26f2af22d8be Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 28 Apr 2026 21:42:38 +0200 Subject: [PATCH 416/418] fix(weather): use nearest openmeteo hourly data (#4123) Open-Meteo updates `current_weather` every 15 minutes, but the hourly array only has entries at full hours. The old code did an exact timestamp match - so at 14:15, 14:30 or 14:45 it never found a match and silently fell back to index 0, showing midnight values for humidity, feels-like temp, precipitation, etc. Fix: `findLastIndex((hour) => hour.time <= currentMs)` - the last hourly entry at or before the current time. While fixing the bug I found several dead branches left over from the #4032 refactor: a path for pre-transposed hourly data that `#parseWeatherApiResponse` makes unreachable, an `Array.isArray` guard that's always true, and a `Log.debug` inside the dead branch. Removing those accounts for most of the ~40 deleted lines - the actual fix is one line. Fixes #4122. --- defaultmodules/weather/providers/openmeteo.js | 52 +++++-------------- .../weather/providers/openmeteo_spec.js | 5 +- 2 files changed, 16 insertions(+), 41 deletions(-) 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/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 () => { From 5a82c9d132519894180f63f80a3a87daac5cee06 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Wed, 29 Apr 2026 06:32:24 +0200 Subject: [PATCH 417/418] update dependencies (#4124) --- package-lock.json | 1553 +++++++++++++++++++++++---------------------- package.json | 36 +- 2 files changed, 797 insertions(+), 792 deletions(-) diff --git a/package-lock.json b/package-lock.json index f6fe447651..10ad4cfe7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,58 +13,58 @@ "@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.2.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", + "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": "^8.0.2", + "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.9.0", - "eslint-plugin-package-json": "^0.91.1", - "eslint-plugin-playwright": "^2.10.1", + "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", + "markdownlint-cli2": "^0.22.1", + "msw": "^2.13.6", "playwright": "^1.59.1", - "prettier": "^3.8.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.1" + "electron": "^41.3.0" } }, "node_modules/@altano/repository-tools": { @@ -75,39 +75,49 @@ "license": "ISC" }, "node_modules/@asamuzakjp/css-color": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.5.tgz", - "integrity": "sha512-8cMAA1bE66Mb/tfmkhcfJLjEPgyT7SSy6lW6id5XL113ai1ky76d/1L27sGnXCMsLfq66DInAU3OzuahB4lu9Q==", + "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.6", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.0.6.tgz", - "integrity": "sha512-Tgmk6EQM0nc9xvp7sEHRVavbknhb/vGKht+04yAT3t5KQwZ02CSobCtcFgaHH04ZrjD1BhEKNA8tRhzFV20gkA==", + "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,9 +1163,9 @@ } }, "node_modules/@emnapi/core": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", - "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "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, @@ -1173,9 +1183,9 @@ "optional": true }, "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "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, @@ -1277,12 +1287,12 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.23.4", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.4.tgz", - "integrity": "sha512-lf19F24LSMfF8weXvW5QEtnLqW70u7kgit5e9PSx0MsHAFclGd1T9ynvWEMDT1w5J4Qt54tomGeAhdoAku1Xow==", + "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.4", + "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" }, @@ -1291,21 +1301,21 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.4.tgz", - "integrity": "sha512-jJhqiY3wPMlWWO3370M86CPJ7pt8GmEwSLglMfQhjXal07RCvhmU0as4IuUEW5SJeunfItiEetHmSxCCe9lDBg==", + "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.2.0" + "@eslint/core": "^1.2.1" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.0.tgz", - "integrity": "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A==", + "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" @@ -1336,21 +1346,21 @@ } }, "node_modules/@eslint/object-schema": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.4.tgz", - "integrity": "sha512-55lO/7+Yp0ISKRP0PsPtNTeNGapXaO085aELZmWCVc5SH3jfrqpuU6YgOdIxMS99ZHkQN1cXKE+cdIqwww9ptw==", + "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.7.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.0.tgz", - "integrity": "sha512-ejvBr8MQCbVsWNZnCwDXjUKq40MDmHalq7cJ6e9s/qzTUFIIo/afzt1Vui9T97FM/V/pN4YsFVoed5NIa96RDg==", + "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.2.0", + "@eslint/core": "^1.2.1", "levn": "^0.4.1" }, "engines": { @@ -1403,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", @@ -1451,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" @@ -1483,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" @@ -1510,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" @@ -1665,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": { @@ -1682,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", @@ -1734,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" }, @@ -1759,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": { @@ -2034,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" ], @@ -2051,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" ], @@ -2068,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" ], @@ -2085,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" ], @@ -2102,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" ], @@ -2119,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" ], @@ -2139,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" ], @@ -2159,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" ], @@ -2179,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" ], @@ -2199,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" ], @@ -2219,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" ], @@ -2239,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" ], @@ -2256,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" ], @@ -2266,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, @@ -2292,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" ], @@ -2309,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" ], @@ -2326,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" }, @@ -2574,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", @@ -2608,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": { @@ -2630,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" @@ -2648,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": { @@ -2665,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": { @@ -2679,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", @@ -2707,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" @@ -2731,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": { @@ -3055,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", @@ -3076,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": { @@ -3086,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": { @@ -3117,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" }, @@ -3135,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" }, @@ -3162,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": { @@ -3175,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": { @@ -3189,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" }, @@ -3205,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": { @@ -3215,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", @@ -3233,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" }, @@ -3301,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", @@ -3539,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" @@ -3880,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", @@ -4156,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" @@ -4256,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", @@ -4290,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" }, @@ -4323,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": { @@ -4840,9 +4811,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "41.1.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-41.1.1.tgz", - "integrity": "sha512-8bgvDhBjli+3Z2YCKgzzoBPh6391pr7Xv2h/tTJG4ETgvPvUxZomObbZLs31mUzYb6VrlcDDd9cyWyNKtPm3tA==", + "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, @@ -4885,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", @@ -5060,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" }, @@ -5135,17 +5106,17 @@ } }, "node_modules/eslint": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.0.tgz", - "integrity": "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==", + "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.4", - "@eslint/config-helpers": "^0.5.4", - "@eslint/core": "^1.2.0", - "@eslint/plugin-kit": "^0.7.0", + "@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", @@ -5332,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": { @@ -5343,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", @@ -5358,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": { @@ -5405,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", @@ -5724,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", @@ -5740,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", @@ -5895,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", @@ -6057,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": { @@ -6200,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" @@ -6229,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": { @@ -6369,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" @@ -6381,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", @@ -6403,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", @@ -6597,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", @@ -6673,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" @@ -6980,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", @@ -7021,9 +7009,9 @@ } }, "node_modules/jsdom/node_modules/undici": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.7.tgz", - "integrity": "sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==", + "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": { @@ -7123,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", @@ -7598,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": { @@ -7688,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", @@ -7702,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" @@ -7727,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", @@ -8502,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" @@ -8530,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" }, @@ -8589,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": { @@ -8687,9 +8662,9 @@ } }, "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" @@ -8730,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", @@ -8947,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" @@ -8968,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": { @@ -9037,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" @@ -9393,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": [ { @@ -9479,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": { @@ -9517,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", @@ -9636,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" @@ -9804,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" @@ -9881,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" }, @@ -9924,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" @@ -9940,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 +9987,9 @@ } }, "node_modules/rrule-temporal": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.5.2.tgz", - "integrity": "sha512-I5rAiZfRlMh0vuG23HrGBMLZOSiQO7H1Uq8l9qyfA6oTD5j+UMRwpRs4aVU4XdaFhgN1p3K+cHelG8KvLTTm+g==", + "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" @@ -10177,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", @@ -10230,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" @@ -10476,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": { @@ -10641,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" }, @@ -10665,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": { @@ -10698,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": [ { @@ -10714,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", @@ -10730,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", @@ -10741,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", @@ -11115,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": { @@ -11125,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" @@ -11152,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" }, @@ -11305,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": { @@ -11335,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, @@ -11357,9 +11367,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.0.2.tgz", - "integrity": "sha512-B9MeU5wuFhkFAuNeA19K2GDFcQXZxq33fL0nRy2Aq30wdufZbyyvxW3/ChaeipXVfy/wUweZyzovQGk39+9k2w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.1.0.tgz", + "integrity": "sha512-E9MkTS4xXLnRPYqxH2e6Hr2/49e7WFDKczKcCaFH4VaZs2iNvHMqeIkyUAD9vM8kujy9TjVrRlQ5KkdEJxB2pw==", "license": "MIT", "engines": { "node": ">=22.19.0" @@ -11506,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" @@ -11533,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", @@ -11599,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", @@ -11639,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" @@ -11666,6 +11678,12 @@ "@vitest/browser-webdriverio": { "optional": true }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, "@vitest/ui": { "optional": true }, @@ -12063,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 827bc9176e..39e0455e82 100644 --- a/package.json +++ b/package.json @@ -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.2.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", + "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": "^8.0.2", + "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.9.0", - "eslint-plugin-package-json": "^0.91.1", - "eslint-plugin-playwright": "^2.10.1", + "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", + "markdownlint-cli2": "^0.22.1", + "msw": "^2.13.6", "playwright": "^1.59.1", - "prettier": "^3.8.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.1" + "electron": "^41.3.0" }, "engines": { "node": ">=22.21.1 <23 || >=24" From 8dbee62730ae57a5826da848840d2d70a8fa3dd6 Mon Sep 17 00:00:00 2001 From: Karsten Hassel Date: Thu, 30 Apr 2026 22:26:57 +0200 Subject: [PATCH 418/418] Prepare Release 2.36.0 (#4126) --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10ad4cfe7d..5e384ba317 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "magicmirror", - "version": "2.36.0-develop", + "version": "2.36.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.36.0-develop", + "version": "2.36.0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 39e0455e82..b2c0eca59b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.36.0-develop", + "version": "2.36.0", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror",