diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index 1c23a276..ec8f8966 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -18,9 +18,9 @@ jobs: timeout-minutes: 15 steps: - name: "Checkout code" - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: "Use Node.js" - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: lts/* cache: "npm" @@ -38,16 +38,16 @@ jobs: timeout-minutes: 30 strategy: matrix: - node-version: [22.14.0, 22.x, 24.x] + node-version: [22.18.0, 22.x, 24.x] steps: - name: Install electron dependencies and labwc run: | sudo apt-get update sudo apt-get install -y libnss3 libasound2t64 labwc - name: "Checkout code" - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: "Use Node.js ${{ matrix.node-version }}" - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: ${{ matrix.node-version }} check-latest: true diff --git a/.github/workflows/dep-review.yaml b/.github/workflows/dep-review.yaml index 141e821b..1573a7e9 100644 --- a/.github/workflows/dep-review.yaml +++ b/.github/workflows/dep-review.yaml @@ -13,6 +13,6 @@ jobs: runs-on: ubuntu-latest steps: - name: "Checkout code" - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: "Dependency Review" uses: actions/dependency-review-action@v4 diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml index b34a7553..7427734f 100644 --- a/.github/workflows/electron-rebuild.yaml +++ b/.github/workflows/electron-rebuild.yaml @@ -8,12 +8,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [22.14.0, 22.x, 24.x] + node-version: [22.18.0, 22.x, 24.x] steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: "Use Node.js ${{ matrix.node-version }}" - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: ${{ matrix.node-version }} check-latest: true diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml index 03053b21..63431988 100644 --- a/.github/workflows/spellcheck.yaml +++ b/.github/workflows/spellcheck.yaml @@ -15,11 +15,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: develop - name: Set up Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: lts/* check-latest: true diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 800684df..963fd0db 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -12,7 +12,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 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 diff --git a/CHANGELOG.md b/CHANGELOG.md index af3e0919..32bd1f3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,59 @@ 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.33.0] - 2025-10-01 + +Thanks to: @Crazylegstoo, @dathbe, @m-idler, @plebcity, @khassel, @KristjanESPERANTO, @rejas and @sdetweil! + +> ⚠️ This release needs nodejs version `v22.18.0 or higher` + +### Added + +- Add configuration option for `User-Agent`, used by calendar & news module (#3255) +- [linter] Add prettier plugin for nunjuck templates (#3887) +- [core] Add clear log for occupied port at startup (#3890) + +### Changed + +- [clock] Add CSS to prevent line breaking of sunset/sunrise time display (#3816) +- [core] Enhance system information logging format and include additional env and RAM details (#3839, #3843) +- [refactor] Add new file `js/module_functions.js` to move code used in several modules to one place (#3837) +- [refactor] Use global.root_path where possible and add tests for config:check (#3883, #3885, #3886, #3889) +- [tests] refactor: simplify jest config file (#3844) +- [tests] refactor: extract constants for weather electron tests (#3845) +- [tests] refactor: add `setupDOMEnvironment` helper function to eliminate repetitive JSDOM setup code (#3860) +- [tests] replace `console` with `Log` in calendar `debug.js` to avoid exception in eslint config (#3846) +- [tests] speed up e2e tests, cleanup and stabilize weather e2e tests, update snapshot url (#3847, #3848, #3861) +- [tests] refactor translation tests (#3866) + - Remove `sinon` dependency in favor of Jest native mocking + - Unify test helper functions across translation test suites + - Rename `setupDOMEnvironment` to `createTranslationTestEnvironment` for consistency + - Simplify DOM setup by removing unnecessary Promise/async patterns + - Avoid potential port conflicts by using port 3001 for translator unit tests + - Improve test reliability and maintainability +- [tests] add alert module tests for different welcome_message configurations (#3867) +- [lint-staged] use `prettier --write --ignore-unknown` in `lint-staged` to avoid errors on unsupported files (#3888) + +### Updated + +- [calendar] Update defaultSymbol name and also the link to the icon search site (#3879) +- [core] Update dependencies including electron to v38 as well as github actions (#3831, #3849, #3857, #3858, #3872, #3876, #3882, #3891, #3896) +- [weather] Update feels_like temperature calculation formula (#3869) +- [weather] Update null value handling for weather type (#3892) +- [layout] Update styles for weather and calendar (#3894) + +### Fixed + +- [calendar] Fixed broken unittest that only broke on the 1st of July and 1st of january (#3830) +- [clock] Fixed missing icons when no other modules with icons is loaded (#3834) +- [weather] Fixed handling of empty values in weathergov providers handling of precipitationAmount (#3859) +- [calendar] Fix regression handling of limit days (#3840) +- [calendar] Fixed regression of calendarfetcherutils.shouldEventBeExcluded (#3841) +- [core] Fixed socket.io timeout when server is slow to send notification, notification lost at client (#3380) +- [tests] refactor AnimateCSS tests after jsdom 27 upgrade (#3891) +- [weather] Use `apparent_temperature` data from openmeteo's hourly weather for current feelsLikeTemp (#3868). +- [weather] Updated envcanada Provider to use new database/URL schema for accessing weather data (#3878). + ## [2.32.0] - 2025-07-01 Thanks to: @bughaver, @bugsounet, @khassel, @KristjanESPERANTO, @plebcity, @rejas, @sdetweil. @@ -260,7 +313,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) -- [core] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368) +- [linter] 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) @@ -277,7 +330,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T - 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 -- Update layout of current weather indoor values +- [weather] Update layout of current weather indoor values ### Fixed @@ -422,7 +475,7 @@ Special thanks to @khassel, @rejas and @sdetweil for taking over most (if not al - Added UV Index to hourly and current Weather, with support for Openmeteo - 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 +- [linter] 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 - Added per-calendar fetchInterval @@ -687,7 +740,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 openweathermap's current weather being ignored (#2678). +- [weather] 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. @@ -725,7 +778,7 @@ Special thanks to the following contributors: @apiontek, @eouia, @jupadin, @khas - 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 forecast, when API URLs available. -- Refactored clock layout. +- [clock] Refactored clock layout. - Refactored methods from weather-providers into weatherobject (isDaytime, updateSunTime). - Use of `logger.js` in jest tests. - Run prettier over all relevant files. @@ -1771,6 +1824,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.33.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.32.0...v2.33.0 [2.32.0]: https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.31.0...v2.32.0 [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 diff --git a/Collaboration.md b/Collaboration.md index 403a9fe1..140a9af7 100644 --- a/Collaboration.md +++ b/Collaboration.md @@ -35,7 +35,7 @@ Are done by - [ ] 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 + - [ ] add min. node version: > ⚠️ This release needs nodejs version `v22.18.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` diff --git a/cspell.config.json b/cspell.config.json index e792a592..35442b2f 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -21,6 +21,7 @@ "browserwindow", "bryanzzhu", "btoconnor", + "bughaver", "bugsounet", "buxxi", "byday", @@ -44,6 +45,7 @@ "darksky", "dateheader", "dateheaders", + "dathbe", "davide", "DAYAFTERTOMORROW", "DAYBEFOREYESTERDAY", @@ -175,6 +177,7 @@ "oraclesean", "oscarb", "philnagel", + "plebcity", "Português", "PRECIP", "Problema", @@ -233,6 +236,7 @@ "Weatherflow", "weatherforecast", "weathergov", + "weathericon", "weathericons", "weatherobject", "weatherutils", diff --git a/css/main.css b/css/main.css index e981635b..e025b4db 100644 --- a/css/main.css +++ b/css/main.css @@ -252,3 +252,15 @@ sup { .region .container.hidden { display: none; } + +.region.left .flex { + justify-content: flex-start; +} + +.region.center .flex { + justify-content: center; +} + +.region.right .flex { + justify-content: flex-end; +} diff --git a/eslint.config.mjs b/eslint.config.mjs index b046879d..706bfefd 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -3,7 +3,7 @@ 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 jsdocPlugin from "eslint-plugin-jsdoc"; import packageJson from "eslint-plugin-package-json"; import stylistic from "@stylistic/eslint-plugin"; @@ -23,8 +23,8 @@ export default defineConfig([ moment: "readonly" } }, - plugins: {js, jsdoc, stylistic}, - extends: [importX.recommended, jest.configs["flat/recommended"], "js/recommended", jsdoc.configs["flat/recommended"], "stylistic/all"], + plugins: {js, stylistic}, + extends: [importX.recommended, jest.configs["flat/recommended"], "js/recommended", jsdocPlugin.configs["flat/recommended"], "stylistic/all"], rules: { "@stylistic/array-element-newline": ["error", "consistent"], "@stylistic/arrow-parens": ["error", "always"], @@ -88,7 +88,6 @@ export default defineConfig([ files: ["**/*.js"], ignores: [ "clientonly/index.js", - "modules/default/calendar/debug.js", "js/logger.js", "tests/**/*.js" ], diff --git a/jest.config.js b/jest.config.js index 0faea8b9..cc65330f 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,32 +1,37 @@ -module.exports = async () => { - return { - verbose: true, - testTimeout: 20000, - testSequencer: "/tests/utils/test_sequencer.js", - projects: [ - { - displayName: "unit", - globalSetup: "/tests/unit/helpers/global-setup.js", - moduleNameMapper: { - logger: "/js/logger.js" - }, - testMatch: ["**/tests/unit/**/*.[jt]s?(x)"], - testPathIgnorePatterns: ["/tests/unit/mocks", "/tests/unit/helpers"] +const config = { + verbose: true, + testTimeout: 20000, + testSequencer: "/tests/utils/test_sequencer.js", + projects: [ + { + displayName: "unit", + globalSetup: "/tests/unit/helpers/global-setup.js", + moduleNameMapper: { + logger: "/js/logger.js" }, - { - displayName: "electron", - testMatch: ["**/tests/electron/**/*.[jt]s?(x)"], - testPathIgnorePatterns: ["/tests/electron/helpers"] - }, - { - displayName: "e2e", - testMatch: ["**/tests/e2e/**/*.[jt]s?(x)"], - modulePaths: ["/js/"], - testPathIgnorePatterns: ["/tests/e2e/helpers", "/tests/e2e/mocks"] - } - ], - collectCoverageFrom: ["./clientonly/**/*.js", "./js/**/*.js", "./modules/default/**/*.js", "./serveronly/**/*.js"], - coverageReporters: ["lcov", "text"], - coverageProvider: "v8" - }; + testMatch: ["**/tests/unit/**/*.[jt]s?(x)"], + testPathIgnorePatterns: ["/tests/unit/mocks", "/tests/unit/helpers"] + }, + { + displayName: "electron", + testMatch: ["**/tests/electron/**/*.[jt]s?(x)"], + testPathIgnorePatterns: ["/tests/electron/helpers"] + }, + { + displayName: "e2e", + testMatch: ["**/tests/e2e/**/*.[jt]s?(x)"], + modulePaths: ["/js/"], + testPathIgnorePatterns: ["/tests/e2e/helpers", "/tests/e2e/mocks"] + } + ], + collectCoverageFrom: [ + "/clientonly/**/*.js", + "/js/**/*.js", + "/modules/default/**/*.js", + "/serveronly/**/*.js" + ], + coverageReporters: ["lcov", "text"], + coverageProvider: "v8" }; + +module.exports = config; diff --git a/js/app.js b/js/app.js index 72d9e852..c0677c71 100644 --- a/js/app.js +++ b/js/app.js @@ -6,26 +6,26 @@ const path = require("node:path"); const envsub = require("envsub"); const Log = require("logger"); +// global absolute root path +global.root_path = path.resolve(`${__dirname}/../`); + const Server = require(`${__dirname}/server`); const Utils = require(`${__dirname}/utils`); -const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`); -const { getEnvVarsAsObj } = require(`${__dirname}/server_functions`); +const defaultModules = require(`${global.root_path}/modules/default/defaultmodules`); // used to control fetch timeout for node_helpers const { setGlobalDispatcher, Agent } = require("undici"); +const { getEnvVarsAsObj } = require("#server_functions"); // 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.version = require(`${global.root_path}/package.json`).version; global.mmTestMode = process.env.mmTestMode === "true"; Log.log(`Starting MagicMirror: v${global.version}`); // Log system information. -Utils.logSystemInformation(); - -// global absolute root path -global.root_path = path.resolve(`${__dirname}/../`); +Utils.logSystemInformation(global.version); if (process.env.MM_CONFIG_FILE) { global.configuration_file = process.env.MM_CONFIG_FILE.replace(`${global.root_path}/`, ""); @@ -181,10 +181,10 @@ function App () { const elements = module.split("/"); const moduleName = elements[elements.length - 1]; const env = getEnvVarsAsObj(); - let moduleFolder = path.resolve(`${__dirname}/../${env.modulesDir}`, module); + let moduleFolder = path.resolve(`${global.root_path}/${env.modulesDir}`, module); if (defaultModules.includes(moduleName)) { - const defaultModuleFolder = path.resolve(`${__dirname}/../modules/default/`, module); + const defaultModuleFolder = path.resolve(`${global.root_path}/modules/default/`, module); if (process.env.JEST_WORKER_ID === undefined) { moduleFolder = defaultModuleFolder; } else { diff --git a/js/main.js b/js/main.js index 58740285..5ba319ff 100644 --- a/js/main.js +++ b/js/main.js @@ -90,7 +90,7 @@ const MM = (function () { /** * Send a notification to all modules. * @param {string} notification The identifier of the notification. - * @param {*} payload The payload of the notification. + * @param {object} payload The payload of the notification. * @param {Module} sender The module that sent the notification. * @param {Module} [sendTo] The (optional) module to send the notification to. */ @@ -262,7 +262,7 @@ const MM = (function () { * Hide the module. * @param {Module} module The module to hide. * @param {number} speed The speed of the hide animation. - * @param {Function} callback Called when the animation is done. + * @param {Promise} callback Called when the animation is done. * @param {object} [options] Optional settings for the hide method. */ const hideModule = function (module, speed, callback, options = {}) { @@ -347,7 +347,7 @@ const MM = (function () { * Show the module. * @param {Module} module The module to show. * @param {number} speed The speed of the show animation. - * @param {Function} callback Called when the animation is done. + * @param {Promise} callback Called when the animation is done. * @param {object} [options] Optional settings for the show method. */ const showModule = function (module, speed, callback, options = {}) { @@ -552,7 +552,7 @@ const MM = (function () { /** * Walks thru a collection of modules and executes the callback with the module as an argument. - * @param {Function} callback The function to execute with the module as an argument. + * @param {module} callback The function to execute with the module as an argument. */ const enumerate = function (callback) { modules.map(function (module) { @@ -629,7 +629,7 @@ const MM = (function () { /** * Send a notification to all modules. * @param {string} notification The identifier of the notification. - * @param {*} payload The payload of the notification. + * @param {object} payload The payload of the notification. * @param {Module} sender The module that sent the notification. */ sendNotification (notification, payload, sender) { @@ -688,7 +688,7 @@ const MM = (function () { * Hide the module. * @param {Module} module The module to hide. * @param {number} speed The speed of the hide animation. - * @param {Function} callback Called when the animation is done. + * @param {Promise} callback Called when the animation is done. * @param {object} [options] Optional settings for the hide method. */ hideModule (module, speed, callback, options) { @@ -700,7 +700,7 @@ const MM = (function () { * Show the module. * @param {Module} module The module to show. * @param {number} speed The speed of the show animation. - * @param {Function} callback Called when the animation is done. + * @param {Promise} callback Called when the animation is done. * @param {object} [options] Optional settings for the show method. */ showModule (module, speed, callback, options) { diff --git a/js/module.js b/js/module.js index 3fc2cf30..3a0c6a80 100644 --- a/js/module.js +++ b/js/module.js @@ -68,7 +68,7 @@ const Module = Class.extend({ * Returns a map of translation files the module requires to be loaded. * * return Map - - * @returns {*} A map with langKeys and filenames. + * @returns {Map} A map with langKeys and filenames. */ getTranslations () { return false; @@ -140,7 +140,7 @@ const Module = Class.extend({ /** * Called by the MagicMirror² core when a notification arrives. * @param {string} notification The identifier of the notification. - * @param {*} payload The payload of the notification. + * @param {object} payload The payload of the notification. * @param {Module} sender The module that sent the notification. */ notificationReceived (notification, payload, sender) { @@ -176,7 +176,7 @@ const Module = Class.extend({ /** * Called when a socket notification arrives. * @param {string} notification The identifier of the notification. - * @param {*} 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}`); @@ -344,7 +344,7 @@ const Module = Class.extend({ /** * Send a notification to all modules. * @param {string} notification The identifier of the notification. - * @param {*} payload The payload of the notification. + * @param {object} payload The payload of the notification. */ sendNotification (notification, payload) { MM.sendNotification(notification, payload, this); @@ -353,7 +353,7 @@ const Module = Class.extend({ /** * Send a socket notification to the node helper. * @param {string} notification The identifier of the notification. - * @param {*} payload The payload of the notification. + * @param {object} payload The payload of the notification. */ sendSocketNotification (notification, payload) { this.socket().sendNotification(notification, payload); @@ -362,7 +362,7 @@ const Module = Class.extend({ /** * Hide this module. * @param {number} speed The speed of the hide animation. - * @param {Function} callback Called when the animation is done. + * @param {Promise} callback Called when the animation is done. * @param {object} [options] Optional settings for the hide method. */ hide (speed, callback, options = {}) { @@ -389,7 +389,7 @@ const Module = Class.extend({ /** * Show this module. * @param {number} speed The speed of the show animation. - * @param {Function} callback Called when the animation is done. + * @param {Promise} callback Called when the animation is done. * @param {object} [options] Optional settings for the show method. */ show (speed, callback, options) { diff --git a/js/module_functions.js b/js/module_functions.js new file mode 100644 index 00000000..e4ea3349 --- /dev/null +++ b/js/module_functions.js @@ -0,0 +1,18 @@ +/** + * 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.JEST_WORKER_ID === undefined) { + // only set timer when not running in jest + let tmr = timer; + clearTimeout(tmr); + tmr = setTimeout(function () { + callback(); + }, intervalMS); + } +}; + +module.exports = { scheduleTimer }; diff --git a/js/node_helper.js b/js/node_helper.js index e1ecf632..bc91dd52 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 {*} 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}`); diff --git a/js/server.js b/js/server.js index a15c811d..fb17b906 100644 --- a/js/server.js +++ b/js/server.js @@ -7,7 +7,7 @@ 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 { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars } = require("#server_functions"); const vendor = require(`${__dirname}/vendor`); @@ -42,7 +42,9 @@ function Server (config) { origin: /.*$/, credentials: true }, - allowEIO3: true + allowEIO3: true, + pingInterval: 120000, // server → client ping every 2 mins + pingTimeout: 120000 // wait up to 2 mins for client pong }); server.on("connection", (socket) => { @@ -53,6 +55,29 @@ function Server (config) { }); Log.log(`Starting server on port ${port} ... `); + + // Add explicit error handling BEFORE calling listen so we can give user-friendly feedback + server.once("error", (err) => { + if (err && err.code === "EADDRINUSE") { + const bindAddr = config.address || "localhost"; + const portInUseMessage = [ + "", + "────────────────────────────────────────────────────────────────", + ` PORT IN USE: ${bindAddr}:${port}`, + "", + " Another process (most likely another MagicMirror instance)", + " is already using this port.", + "", + " Stop the other process (free the port) or use a different port.", + "────────────────────────────────────────────────────────────────" + ].join("\n"); + Log.error(portInUseMessage); + return; + } + + Log.error("Failed to start server:", err); + }); + server.listen(port, config.address || "localhost"); if (config.ipWhitelist instanceof Array && config.ipWhitelist.length === 0) { diff --git a/js/server_functions.js b/js/server_functions.js index 07c6df53..1f206ccd 100644 --- a/js/server_functions.js +++ b/js/server_functions.js @@ -69,7 +69,7 @@ async function cors (req, res) { * @returns {object} An object specifying name and value of the headers. */ function getHeadersToSend (url) { - const headersToSend = { "User-Agent": `Mozilla/5.0 MagicMirror/${global.version}` }; + const headersToSend = { "User-Agent": getUserAgent() }; const headersToSendMatch = new RegExp("sendheaders=(.+?)(&|$)", "g").exec(url); if (headersToSendMatch) { const headers = headersToSendMatch[1].split(","); @@ -129,6 +129,27 @@ function getVersion (req, res) { res.send(global.version); } +/** + * Gets the preferred `User-Agent` + * @returns {string} `User-Agent` to be used + */ +function getUserAgent () { + const defaultUserAgent = `Mozilla/5.0 (Node.js ${Number(process.version.match(/^v(\d+\.\d+)/)[1])}) MagicMirror/${global.version}`; + + if (typeof config === "undefined") { + return defaultUserAgent; + } + + switch (typeof config.userAgent) { + case "function": + return config.userAgent(); + case "string": + return config.userAgent; + default: + return defaultUserAgent; + } +} + /** * Gets environment variables needed in the browser. * @returns {object} environment variables key: values @@ -155,4 +176,4 @@ function getEnvVars (req, res) { res.send(obj); } -module.exports = { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj }; +module.exports = { cors, getConfig, getHtml, getVersion, getStartup, getEnvVars, getEnvVarsAsObj, getUserAgent }; diff --git a/js/socketclient.js b/js/socketclient.js index d8408e9e..73fdbf08 100644 --- a/js/socketclient.js +++ b/js/socketclient.js @@ -13,7 +13,9 @@ const MMSocket = function (moduleName) { base = config.basePath; } this.socket = io(`/${this.moduleName}`, { - path: `${base}socket.io` + path: `${base}socket.io`, + pingInterval: 120000, // send pings every 2 mins + pingTimeout: 120000 // wait up to 2 mins for a pong }); let notificationCallback = function () {}; diff --git a/js/utils.js b/js/utils.js index 636e26d2..d20d6cf6 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,4 +1,3 @@ -const execSync = require("node:child_process").execSync; const path = require("node:path"); const rootPath = path.resolve(`${__dirname}/../`); @@ -14,27 +13,34 @@ const discoveredPositionsJSFilename = "js/positions.js"; module.exports = { - async logSystemInformation () { + async logSystemInformation (mirrorVersion) { try { - let installedNodeVersion = execSync("node -v", { encoding: "utf-8" }).replace("v", "").replace(/(?:\r\n|\r|\n)/g, ""); + const system = await si.system(); + const osInfo = await si.osInfo(); + const versions = await si.versions(); - const staticData = await si.get({ - system: "manufacturer, model, virtual", - osInfo: "platform, distro, release, arch", - versions: "kernel, node, npm, pm2" - }); - 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, ""); + const usedNodeVersion = process.version.replace("v", ""); + const installedNodeVersion = versions.node; + const totalRam = (os.totalmem() / 1024 / 1024).toFixed(2); + const freeRam = (os.freemem() / 1024 / 1024).toFixed(2); + const usedRam = ((os.totalmem() - os.freemem()) / 1024 / 1024).toFixed(2); + + let systemDataString = [ + "\n#### System Information ####", + `- SYSTEM: manufacturer: ${system.manufacturer}; model: ${system.model}; virtual: ${system.virtual}; MM: ${mirrorVersion}`, + `- OS: platform: ${osInfo.platform}; distro: ${osInfo.distro}; release: ${osInfo.release}; arch: ${osInfo.arch}; kernel: ${versions.kernel}`, + `- VERSIONS: electron: ${process.versions.electron}; used node: ${usedNodeVersion}; installed node: ${installedNodeVersion}; npm: ${versions.npm}; pm2: ${versions.pm2}`, + `- ENV: XDG_SESSION_TYPE: ${process.env.XDG_SESSION_TYPE}; MM_CONFIG_FILE: ${process.env.MM_CONFIG_FILE}`, + ` WAYLAND_DISPLAY: ${process.env.WAYLAND_DISPLAY}; DISPLAY: ${process.env.DISPLAY}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}`, + `- RAM: total: ${totalRam} MB; free: ${freeRam} MB; used: ${usedRam} MB`, + `- OTHERS: uptime: ${Math.floor(os.uptime() / 60)} minutes; timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}` + ].join("\n"); Log.info(systemDataString); // Return is currently only for jest return systemDataString; - } catch (e) { - Log.error(e); + } catch (error) { + Log.error(error); } }, diff --git a/modules/default/alert/styles/notificationFx.css b/modules/default/alert/styles/notificationFx.css index df340751..6d6272fe 100644 --- a/modules/default/alert/styles/notificationFx.css +++ b/modules/default/alert/styles/notificationFx.css @@ -9,7 +9,7 @@ font-size: 70%; position: relative; display: table; - word-wrap: break-word; + overflow-wrap: break-word; max-width: 100%; border-width: 1px; border-radius: 5px; @@ -35,7 +35,7 @@ top: 40%; width: 40%; height: auto; - word-wrap: break-word; + overflow-wrap: break-word; border-radius: 20px; } diff --git a/modules/default/alert/templates/alert.njk b/modules/default/alert/templates/alert.njk index b7db3a4d..727c9185 100644 --- a/modules/default/alert/templates/alert.njk +++ b/modules/default/alert/templates/alert.njk @@ -1,20 +1,20 @@ {% if imageUrl or imageFA %} - {% set imageHeight = imageHeight if imageHeight else "80px" %} - {% if imageUrl %} - - {% else %} - - {% endif %} -
+ {% set imageHeight = imageHeight if imageHeight else "80px" %} + {% if imageUrl %} + + {% else %} + + {% endif %} +
{% endif %} {% if title %} - {{ title if titleType == 'text' else title | safe }} + {{ title if titleType == 'text' else title | safe }} {% endif %} {% if message %} - {% if title %}
{% endif %} - {{ message if messageType == 'text' else message | safe }} + {% if title %}
{% endif %} + {{ message if messageType == 'text' else message | safe }} {% endif %} diff --git a/modules/default/alert/templates/notification.njk b/modules/default/alert/templates/notification.njk index 0de6908b..8e4f3341 100644 --- a/modules/default/alert/templates/notification.njk +++ b/modules/default/alert/templates/notification.njk @@ -1,7 +1,7 @@ {% if title %} - {{ title if titleType == 'text' else title | safe }} + {{ title if titleType == 'text' else title | safe }} {% endif %} {% if message %} - {% if title %}
{% endif %} - {{ message if messageType == 'text' else message | safe }} + {% if title %}
{% endif %} + {{ message if messageType == 'text' else message | safe }} {% endif %} diff --git a/modules/default/calendar/calendar.css b/modules/default/calendar/calendar.css index f8e3bd79..973a5abb 100644 --- a/modules/default/calendar/calendar.css +++ b/modules/default/calendar/calendar.css @@ -2,23 +2,14 @@ display: flex; flex-direction: row; justify-content: flex-end; - padding-left: 0; - padding-right: 10px; - font-size: var(--font-size-small); -} - -.calendar .symbol span { - padding-top: 4px; + gap: 5px; } .calendar .title { - padding-left: 0; - padding-right: 0; - vertical-align: top; + padding: 0 10px; } .calendar .time { - padding-left: 30px; + padding-left: 20px; text-align: right; - vertical-align: top; } diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index a7aad9b3..e5b3621f 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -8,7 +8,7 @@ Module.register("calendar", { limitDays: 0, // Limit the number of days shown, 0 = no limit pastDaysCount: 0, displaySymbol: true, - defaultSymbol: "calendar-alt", // Fontawesome Symbol see https://fontawesome.com/cheatsheet?from=io + defaultSymbol: "calendar-days", // Fontawesome Symbol see https://fontawesome.com/search?ic=free&o=r defaultSymbolClassName: "fas fa-fw fa-", showLocation: false, displayRepeatingCountTitle: false, @@ -168,8 +168,8 @@ Module.register("calendar", { this.selfUpdate(); }, - notificationReceived (notification, payload, sender) { + notificationReceived (notification, payload, sender) { if (notification === "FETCH_CALENDAR") { if (this.hasCalendarURL(payload.url)) { this.sendSocketNotification(notification, { url: payload.url, id: this.identifier }); @@ -217,7 +217,6 @@ Module.register("calendar", { // Override dom generator. getDom () { - const ONE_SECOND = 1000; // 1,000 milliseconds const events = this.createEventList(true); const wrapper = document.createElement("table"); wrapper.className = this.config.tableClass; @@ -308,15 +307,12 @@ Module.register("calendar", { } const symbolClass = this.symbolClassForUrl(event.url); - symbolWrapper.className = `symbol align-right ${symbolClass}`; + symbolWrapper.className = `symbol ${symbolClass}`; const symbols = this.symbolsForEvent(event); - symbols.forEach((s, index) => { + symbols.forEach((s) => { const symbol = document.createElement("span"); symbol.className = s; - if (index > 0) { - symbol.style.paddingLeft = "5px"; - } symbolWrapper.appendChild(symbol); }); eventWrapper.appendChild(symbolWrapper); @@ -601,7 +597,6 @@ Module.register("calendar", { */ createEventList (limitNumberOfEntries) { let now = moment(); - let today = now.clone().startOf("day"); let future = now.clone().startOf("day").add(this.config.maximumNumberOfDays, "days"); let events = []; @@ -705,30 +700,24 @@ Module.register("calendar", { * 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"); - let days = 0; - for (const ev of events) { - let eventDate = this.timestampToMoment(ev.startDate); + if (this.config.limitDays > 0 && events.length > 0) { // watch out for initial display before events arrive from helper + // Group all events by date, events on the same date will be in a list with the key being the date. + const eventsByDate = Object.groupBy(events, (ev) => this.timestampToMoment(ev.startDate).format("YYYY-MM-DD")); + const newEvents = []; + let currentDate = moment(); + let daysCollected = 0; - /* - * if date of event is later than lastdate - * check if we already are showing max unique days - */ - 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--; - } - days++; - if (days > this.config.limitDays) { - continue; - } else { - lastDate = eventDate; - } + while (daysCollected < this.config.limitDays) { + const dateStr = currentDate.format("YYYY-MM-DD"); + // Check if there are events on the currentDate + if (eventsByDate[dateStr] && eventsByDate[dateStr].length > 0) { + // If there are any events today then get all those events and select the currently active events and the events that are starting later in the day. + newEvents.push(...eventsByDate[dateStr].filter((ev) => this.timestampToMoment(ev.endDate).isAfter(moment()))); + // Since we found a day with events, increase the daysCollected by 1 + daysCollected++; } - newEvents.push(ev); + // Search for the next day + currentDate.add(1, "day"); } events = newEvents; } @@ -887,7 +876,7 @@ Module.register("calendar", { * @param {string} url The calendar url * @param {string} property The property to look for * @param {string} defaultValue The value if the property is not found - * @returns {*} The property + * @returns {property} The property */ getCalendarProperty (url, property, defaultValue) { for (const calendar of this.config.calendars) { diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js index 92c65a1d..6f254156 100644 --- a/modules/default/calendar/calendarfetcher.js +++ b/modules/default/calendar/calendarfetcher.js @@ -3,6 +3,8 @@ const ical = require("node-ical"); const Log = require("logger"); const NodeHelper = require("node_helper"); const CalendarFetcherUtils = require("./calendarfetcherutils"); +const { getUserAgent } = require("#server_functions"); +const { scheduleTimer } = require("#module_functions"); /** * @@ -29,10 +31,9 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn const fetchCalendar = () => { clearTimeout(reloadTimer); reloadTimer = null; - const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); let httpsAgent = null; let headers = { - "User-Agent": `Mozilla/5.0 (Node.js ${nodeVersion}) MagicMirror/${global.version}` + "User-Agent": getUserAgent() }; if (selfSignedCert) { @@ -65,31 +66,18 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn }); } catch (error) { fetchFailedCallback(this, error); - scheduleTimer(); + scheduleTimer(reloadTimer, reloadInterval, fetchCalendar); return; } this.broadcastEvents(); - scheduleTimer(); + scheduleTimer(reloadTimer, reloadInterval, fetchCalendar); }) .catch((error) => { fetchFailedCallback(this, error); - scheduleTimer(); + scheduleTimer(reloadTimer, reloadInterval, fetchCalendar); }); }; - /** - * Schedule the timer for the next update. - */ - const scheduleTimer = function () { - if (process.env.JEST_WORKER_ID === undefined) { - // only set timer when not running in jest - clearTimeout(reloadTimer); - reloadTimer = setTimeout(function () { - fetchCalendar(); - }, reloadInterval); - } - }; - /* public methods */ /** @@ -109,7 +97,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn /** * Sets the on success callback - * @param {Function} callback The on success callback. + * @param {eventsReceivedCallback} callback The on success callback. */ this.onReceive = function (callback) { eventsReceivedCallback = callback; @@ -117,7 +105,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn /** * Sets the on error callback - * @param {Function} callback The on error callback. + * @param {fetchFailedCallback} callback The on error callback. */ this.onError = function (callback) { fetchFailedCallback = callback; diff --git a/modules/default/calendar/calendarfetcherutils.js b/modules/default/calendar/calendarfetcherutils.js index 880e68b5..729f121c 100644 --- a/modules/default/calendar/calendarfetcherutils.js +++ b/modules/default/calendar/calendarfetcherutils.js @@ -3,7 +3,7 @@ */ const moment = require("moment-timezone"); -const Log = require("../../../js/logger"); +const Log = require("logger"); const CalendarFetcherUtils = { @@ -16,7 +16,7 @@ const CalendarFetcherUtils = { * until: the date until the event should be excluded. */ shouldEventBeExcluded (config, title) { - let filter = { + let result = { excluded: false, until: null }; @@ -55,14 +55,14 @@ const CalendarFetcherUtils = { if (CalendarFetcherUtils.titleFilterApplies(testTitle, filter, useRegex, regexFlags)) { if (until) { - filter.until = until; + result.until = until; } else { - filter.excluded = true; + result.excluded = true; } break; } } - return filter; + return result; }, /** diff --git a/modules/default/calendar/debug.js b/modules/default/calendar/debug.js index 74d48cd7..3acfc311 100644 --- a/modules/default/calendar/debug.js +++ b/modules/default/calendar/debug.js @@ -5,6 +5,7 @@ */ // Alias modules mentioned in package.js under _moduleAliases. require("module-alias/register"); +const Log = require("logger"); const CalendarFetcher = require("./calendarfetcher"); @@ -20,22 +21,22 @@ const auth = { pass: pass }; -console.log("Create fetcher ..."); +Log.log("Create fetcher ..."); const fetcher = new CalendarFetcher(url, fetchInterval, [], maximumEntries, maximumNumberOfDays, auth); fetcher.onReceive(function (fetcher) { - console.log(fetcher.events()); - console.log("------------------------------------------------------------"); + Log.log(fetcher.events()); + Log.log("------------------------------------------------------------"); process.exit(0); }); fetcher.onError(function (fetcher, error) { - console.log("Fetcher error:"); - console.log(error); + Log.log("Fetcher error:"); + Log.log(error); process.exit(1); }); fetcher.startFetch(); -console.log("Create fetcher done! "); +Log.log("Create fetcher done! "); diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index d013cd25..c3f4e854 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -36,7 +36,7 @@ Module.register("clock", { }, // Define styles. getStyles () { - return ["clock_styles.css"]; + return ["clock_styles.css", "font-awesome.css"]; }, // Define start sequence. start () { diff --git a/modules/default/clock/clock_styles.css b/modules/default/clock/clock_styles.css index a6751e3d..8827b6ee 100644 --- a/modules/default/clock/clock_styles.css +++ b/modules/default/clock/clock_styles.css @@ -87,9 +87,17 @@ transform-origin: 50% 100%; } +.module.clock .digital { + display: flex; + flex-direction: column; + gap: 3px; +} + .module.clock .sun, .module.clock .moon { display: flex; + white-space: nowrap; + gap: 10px; } .module.clock .sun > *, diff --git a/modules/default/newsfeed/fullarticle.njk b/modules/default/newsfeed/fullarticle.njk index 0be4b042..fbd6e437 100644 --- a/modules/default/newsfeed/fullarticle.njk +++ b/modules/default/newsfeed/fullarticle.njk @@ -1,3 +1,3 @@
- +
diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 1e8cadfe..348a0d33 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -181,7 +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. + * @returns {property} The value of the specified property for the feed. */ getFeedProperty (feed, property) { let res = this.config[property]; diff --git a/modules/default/newsfeed/newsfeed.njk b/modules/default/newsfeed/newsfeed.njk index 5bdfe2cd..9a91cb94 100644 --- a/modules/default/newsfeed/newsfeed.njk +++ b/modules/default/newsfeed/newsfeed.njk @@ -1,89 +1,89 @@ {% macro escapeText(text, dangerouslyDisableAutoEscaping=false) %} - {% if dangerouslyDisableAutoEscaping -%} - {{ text | safe }} - {%- else -%} - {{ text }} - {%- endif %} + {% if dangerouslyDisableAutoEscaping -%} + {{ text | safe }} + {%- else -%} + {{ text }} + {%- endif %} {% endmacro %} {% macro escapeTitle(title, url, dangerouslyDisableAutoEscaping=false, showTitleAsUrl=false) %} - {% if dangerouslyDisableAutoEscaping %} - {% if showTitleAsUrl %} - {{ title | safe }} - {% else %} - {{ title | safe }} - {% endif %} + target="_blank" + >{{ title | safe }} {% else %} - {% if showTitleAsUrl %} - {{ title }} - {% else %} - {{ title }} - {% endif %} + {{ title | safe }} {% endif %} + {% else %} + {% if showTitleAsUrl %} + {{ title }} + {% else %} + {{ title }} + {% endif %} + {% endif %} {% endmacro %} {% if loaded %} - {% if config.showAsList %} -
    - {% for item in items %} -
  • - {% if (config.showSourceTitle and item.sourceTitle) or config.showPublishDate %} -
    - {% if item.sourceTitle and config.showSourceTitle %} - {{ item.sourceTitle }}{% if config.showPublishDate %}, {% else %}:{% endif %} - {% endif %} - {% if config.showPublishDate %}{{ item.publishDate }}:{% endif %} -
    - {% endif %} -
    - {{ escapeTitle(item.title, item.url, config.dangerouslyDisableAutoEscaping, config.showTitleAsUrl) }} -
    - {% if config.showDescription %} -
    - {% if config.truncDescription %} - {{ escapeText(item.description | truncate(config.lengthDescription) , config.dangerouslyDisableAutoEscaping) }} - {% else %} - {{ escapeText(item.description, config.dangerouslyDisableAutoEscaping) }} - {% endif %} -
    - {% endif %} -
  • - {% endfor %} -
- {% else %} -
- {% if (config.showSourceTitle and sourceTitle) or config.showPublishDate %} -
- {% if sourceTitle and config.showSourceTitle %} - {{ escapeText(sourceTitle, config.dangerouslyDisableAutoEscaping) }}{% if config.showPublishDate %}, {% else %}:{% endif %} - {% endif %} - {% if config.showPublishDate %}{{ publishDate }}:{% endif %} -
- {% endif %} -
- {{ escapeTitle(title, url, config.dangerouslyDisableAutoEscaping, config.showTitleAsUrl) }} + {% if config.showAsList %} +
    + {% for item in items %} +
  • + {% if (config.showSourceTitle and item.sourceTitle) or config.showPublishDate %} +
    + {% if item.sourceTitle and config.showSourceTitle %} + {{ item.sourceTitle }}{% if config.showPublishDate %},{% else %}:{% endif %} + {% endif %} + {% if config.showPublishDate %}{{ item.publishDate }}:{% endif %}
    - {% if config.showDescription %} -
    - {% if config.truncDescription %} - {{ escapeText(description | truncate(config.lengthDescription) , config.dangerouslyDisableAutoEscaping) }} - {% else %} - {{ escapeText(description, config.dangerouslyDisableAutoEscaping) }} - {% endif %} -
    - {% endif %} + {% endif %} +
    {{ escapeTitle(item.title, item.url, config.dangerouslyDisableAutoEscaping, config.showTitleAsUrl) }}
    + {% if config.showDescription %} +
    + {% if config.truncDescription %} + {{ escapeText(item.description | truncate(config.lengthDescription) , config.dangerouslyDisableAutoEscaping) }} + {% else %} + {{ escapeText(item.description, config.dangerouslyDisableAutoEscaping) }} + {% endif %} +
    + {% endif %} +
  • + {% endfor %} +
+ {% else %} +
+ {% if (config.showSourceTitle and sourceTitle) or config.showPublishDate %} +
+ {% if sourceTitle and config.showSourceTitle %} + {{ escapeText(sourceTitle, config.dangerouslyDisableAutoEscaping) }}{% if config.showPublishDate %},{% else %}:{% endif %} + {% endif %} + {% if config.showPublishDate %}{{ publishDate }}:{% endif %}
- {% endif %} -{% elseif empty %} -
{{ "NEWSFEED_NO_ITEMS" | translate | safe }}
-{% elseif error %} -
- {{ "MODULE_CONFIG_ERROR" | translate({MODULE_NAME: "Newsfeed", ERROR: error}) | safe }} + {% endif %} +
{{ escapeTitle(title, url, config.dangerouslyDisableAutoEscaping, config.showTitleAsUrl) }}
+ {% if config.showDescription %} +
+ {% if config.truncDescription %} + {{ escapeText(description | truncate(config.lengthDescription) , config.dangerouslyDisableAutoEscaping) }} + {% else %} + {{ escapeText(description, config.dangerouslyDisableAutoEscaping) }} + {% endif %} +
+ {% endif %}
+ {% endif %} + {% elseif empty %} +
{{ "NEWSFEED_NO_ITEMS" | translate | safe }}
+ {% elseif error %} +
{{ "MODULE_CONFIG_ERROR" | translate({MODULE_NAME: "Newsfeed", ERROR: error}) | safe }}
{% else %} -
{{ "LOADING" | translate | safe }}
+
{{ "LOADING" | translate | safe }}
{% endif %} diff --git a/modules/default/newsfeed/newsfeedfetcher.js b/modules/default/newsfeed/newsfeedfetcher.js index adad7442..9ddebe52 100644 --- a/modules/default/newsfeed/newsfeedfetcher.js +++ b/modules/default/newsfeed/newsfeedfetcher.js @@ -5,6 +5,8 @@ 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"); /** * Responsible for requesting an update on the set interval and broadcasting the data. @@ -79,12 +81,12 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings parser.on("error", (error) => { fetchFailedCallback(this, error); - scheduleTimer(); + scheduleTimer(reloadTimer, reloadIntervalMS, fetchNews); }); //"end" event is not broadcast if the feed is empty but "finish" is used for both parser.on("finish", () => { - scheduleTimer(); + scheduleTimer(reloadTimer, reloadIntervalMS, fetchNews); }); parser.on("ttl", (minutes) => { @@ -100,9 +102,8 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings } }); - const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); const headers = { - "User-Agent": `Mozilla/5.0 (Node.js ${nodeVersion}) MagicMirror/${global.version}`, + "User-Agent": getUserAgent(), "Cache-Control": "max-age=0, no-cache, no-store, must-revalidate", Pragma: "no-cache" }; @@ -120,23 +121,10 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings }) .catch((error) => { fetchFailedCallback(this, error); - scheduleTimer(); + scheduleTimer(reloadTimer, reloadIntervalMS, fetchNews); }); }; - /** - * Schedule the timer for the next update. - */ - const scheduleTimer = function () { - if (process.env.JEST_WORKER_ID === undefined) { - // only set timer when not running in jest - clearTimeout(reloadTimer); - reloadTimer = setTimeout(function () { - fetchNews(); - }, reloadIntervalMS); - } - }; - /* public methods */ /** diff --git a/modules/default/newsfeed/oldconfig.njk b/modules/default/newsfeed/oldconfig.njk index 0e3b9b5d..d8317ca2 100644 --- a/modules/default/newsfeed/oldconfig.njk +++ b/modules/default/newsfeed/oldconfig.njk @@ -1,3 +1 @@ -
- {{ "MODULE_CONFIG_CHANGED" | translate({MODULE_NAME: "Newsfeed"}) | safe }} -
+
{{ "MODULE_CONFIG_CHANGED" | translate({MODULE_NAME: "Newsfeed"}) | safe }}
diff --git a/modules/default/updatenotification/git_helper.js b/modules/default/updatenotification/git_helper.js index 4fb8c189..52161ee9 100644 --- a/modules/default/updatenotification/git_helper.js +++ b/modules/default/updatenotification/git_helper.js @@ -4,8 +4,6 @@ const fs = require("node:fs"); const path = require("node:path"); const Log = require("logger"); -const BASE_DIR = path.normalize(`${__dirname}/../../../`); - class GitHelper { constructor () { this.gitRepos = []; @@ -35,10 +33,10 @@ class GitHelper { } async add (moduleName) { - let moduleFolder = BASE_DIR; + let moduleFolder = `${global.root_path}`; if (moduleName !== "MagicMirror") { - moduleFolder = `${moduleFolder}modules/${moduleName}`; + moduleFolder = `${moduleFolder}/modules/${moduleName}`; } try { diff --git a/modules/default/updatenotification/node_helper.js b/modules/default/updatenotification/node_helper.js index 88264f7c..b5c5fbd1 100644 --- a/modules/default/updatenotification/node_helper.js +++ b/modules/default/updatenotification/node_helper.js @@ -1,7 +1,8 @@ const fs = require("node:fs"); const path = require("node:path"); const NodeHelper = require("node_helper"); -const defaultModules = require("../defaultmodules"); + +const defaultModules = require(`${global.root_path}/modules/default/defaultmodules`); const GitHelper = require("./git_helper"); const UpdateHelper = require("./update_helper"); @@ -21,7 +22,7 @@ module.exports = NodeHelper.create({ return modules; } else { // get modules from modules-directory - const moduleDir = path.normalize(`${__dirname}/../../`); + const moduleDir = path.normalize(`${global.root_path}/modules`); const getDirectories = (source) => { return fs.readdirSync(source, { withFileTypes: true }) .filter((dirent) => dirent.isDirectory() && dirent.name !== "default") diff --git a/modules/default/updatenotification/updatenotification.njk b/modules/default/updatenotification/updatenotification.njk index fbc43f22..b08346f3 100644 --- a/modules/default/updatenotification/updatenotification.njk +++ b/modules/default/updatenotification/updatenotification.njk @@ -1,41 +1,41 @@ {% if not suspended %} - {% if needRestart %} -
- - - {% set restartTextLabel = "UPDATE_NOTIFICATION_NEED-RESTART" %} - {{ restartTextLabel | translate() | safe }} - -
- {% endif %} - {% for name, status in moduleList %} -
- - - {% set mainTextLabel = "UPDATE_NOTIFICATION" if name === "MagicMirror" else "UPDATE_NOTIFICATION_MODULE" %} - {{ mainTextLabel | translate({MODULE_NAME: name}) }} - -
-
- {% set subTextLabel = "UPDATE_INFO_SINGLE" if status.behind === 1 else "UPDATE_INFO_MULTIPLE" %} - {{ subTextLabel | translate({COMMIT_COUNT: status.behind, BRANCH_NAME: status.current}) | diffLink(status) | safe }} -
- {% endfor %} - {% for name, status in updatesList %} -
- {% if status.done %} - - - {% set updateTextLabel = "UPDATE_NOTIFICATION_DONE" %} - {{ updateTextLabel | translate({MODULE_NAME: name}) | safe }} - - {% else %} - - - {% set updateTextLabel = "UPDATE_NOTIFICATION_ERROR" %} - {{ updateTextLabel | translate({MODULE_NAME: name}) | safe }} - - {% endif %} -
- {% endfor %} + {% if needRestart %} +
+ + + {% set restartTextLabel = "UPDATE_NOTIFICATION_NEED-RESTART" %} + {{ restartTextLabel | translate() | safe }} + +
+ {% endif %} + {% for name, status in moduleList %} +
+ + + {% set mainTextLabel = "UPDATE_NOTIFICATION" if name === "MagicMirror" else "UPDATE_NOTIFICATION_MODULE" %} + {{ mainTextLabel | translate({MODULE_NAME: name}) }} + +
+
+ {% set subTextLabel = "UPDATE_INFO_SINGLE" if status.behind === 1 else "UPDATE_INFO_MULTIPLE" %} + {{ subTextLabel | translate({COMMIT_COUNT: status.behind, BRANCH_NAME: status.current}) | diffLink(status) | safe }} +
+ {% endfor %} + {% for name, status in updatesList %} +
+ {% if status.done %} + + + {% set updateTextLabel = "UPDATE_NOTIFICATION_DONE" %} + {{ updateTextLabel | translate({MODULE_NAME: name}) | safe }} + + {% else %} + + + {% set updateTextLabel = "UPDATE_NOTIFICATION_ERROR" %} + {{ updateTextLabel | translate({MODULE_NAME: name}) | safe }} + + {% endif %} +
+ {% endfor %} {% endif %} diff --git a/modules/default/weather/current.njk b/modules/default/weather/current.njk index d1984895..51687231 100644 --- a/modules/default/weather/current.njk +++ b/modules/default/weather/current.njk @@ -1,101 +1,97 @@ {% macro humidity() %} - {% if current.humidity %} - {{ current.humidity | decimalSymbol }}  - {% endif %} + {% if current.humidity %} + {{ current.humidity | decimalSymbol }}  + {% endif %} {% endmacro %} {% if current %} - {% if not config.onlyTemp %} -
- - - {{ current.windSpeed | unit("wind") | round }} - {% if config.showWindDirection %} - - {% if config.showWindDirectionAsArrow %} - - {% else %} - {{ current.cardinalWindDirection() | translate }} - {% endif %} -   - - {% endif %} - - {% if config.showHumidity === "wind" %} - {{ humidity() }} + {% if not config.onlyTemp %} +
+ + + {{ current.windSpeed | unit("wind") | round }} + {% if config.showWindDirection %} + + {% if config.showWindDirectionAsArrow %} + + {% else %} + {{ current.cardinalWindDirection() | translate }} {% endif %} - {% if config.showSun %} - - - {% if current.nextSunAction() === "sunset" %} - {{ current.sunset | formatTime }} - {% else %} - {{ current.sunrise | formatTime }} - {% endif %} - - {% endif %} - {% if config.showUVIndex %} - -
- {{ current.uv_index }} - - {% endif %} -
- {% endif %} -
- {% 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.showHumidity === "wind" %} + {{ humidity() }} + {% endif %} + {% if config.showSun %} + + + {% if current.nextSunAction() === "sunset" %} + {{ current.sunset | formatTime }} + {% else %} + {{ current.sunrise | formatTime }} + {% endif %} + + {% endif %} + {% if config.showUVIndex %} + +
+ {{ current.uv_index }} + + {% endif %}
- {% if (config.showFeelsLike or config.showPrecipitationAmount or config.showPrecipitationProbability) and not config.onlyTemp %} -
- {% if config.showFeelsLike %} - - {% if config.showHumidity === "feelslike" %} - {{ humidity() }} - {% endif %} - {{ "FEELS" | translate({DEGREE: current.feelsLike() | roundValue | unit("temperature") | decimalSymbol }) }} - -
- {% endif %} - {% if config.showPrecipitationAmount and current.precipitationAmount %} - - {{ "PRECIP_AMOUNT" | translate }} {{ current.precipitationAmount | unit("precip", current.precipitationUnits) }} - -
- {% endif %} - {% if config.showPrecipitationProbability and current.precipitationProbability %} - - {{ "PRECIP_POP" | translate }} {{ current.precipitationProbability }}% - - {% endif %} -
+ {% endif %} +
+ {% 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 %} - {% if config.showHumidity === "below" %} - {{ humidity() }} + {% if current.weatherType %} + {% endif %} + {{ current.temperature | roundValue | unit("temperature") | decimalSymbol }} + {% if config.showHumidity === "temp" %} + {{ humidity() }} + {% endif %} +
+ {% if (config.showFeelsLike or config.showPrecipitationAmount or config.showPrecipitationProbability) and not config.onlyTemp %} +
+ {% if config.showFeelsLike %} + + {% if config.showHumidity === "feelslike" %} + {{ humidity() }} + {% endif %} + {{ "FEELS" | translate({DEGREE: current.feelsLike() | roundValue | unit("temperature") | decimalSymbol }) }} + +
+ {% endif %} + {% if config.showPrecipitationAmount and current.precipitationAmount %} + {{ "PRECIP_AMOUNT" | translate }} {{ current.precipitationAmount | unit("precip", current.precipitationUnits) }} +
+ {% endif %} + {% if config.showPrecipitationProbability and current.precipitationProbability %} + {{ "PRECIP_POP" | translate }} {{ current.precipitationProbability }}% + {% endif %} +
+ {% endif %} + {% if config.showHumidity === "below" %} + {{ humidity() }} + {% endif %} {% else %} -
{{ "LOADING" | translate }}
+
{{ "LOADING" | translate }}
{% endif %} - + diff --git a/modules/default/weather/forecast.njk b/modules/default/weather/forecast.njk index 85570fbb..91fef6ab 100644 --- a/modules/default/weather/forecast.njk +++ b/modules/default/weather/forecast.njk @@ -1,52 +1,46 @@ {% if forecast %} - {% set numSteps = forecast | calcNumSteps %} - {% set currentStep = 0 %} - - {% if config.ignoreToday %} - {% set forecast = forecast.splice(1) %} + {% set numSteps = forecast | calcNumSteps %} + {% set currentStep = 0 %} +
+ {% if config.ignoreToday %} + {% set forecast = forecast.splice(1) %} + {% endif %} + {% set forecast = forecast.slice(0, numSteps) %} + {% for f in forecast %} + + {% if (currentStep == 0) and config.ignoreToday == false and config.absoluteDates == false %} + + {% elif (currentStep == 1) and config.ignoreToday == false and config.absoluteDates == false %} + + {% else %} + {% endif %} - {% set forecast = forecast.slice(0, numSteps) %} - {% for f in forecast %} - - {% if (currentStep == 0) and config.ignoreToday == false and config.absoluteDates == false %} - - {% elif (currentStep == 1) and config.ignoreToday == false and config.absoluteDates == false %} - - {% else %} - - {% endif %} - - - - {% if config.showPrecipitationAmount %} - - {% endif %} - {% if config.showPrecipitationProbability %} - - {% endif %} - {% if config.showUVIndex %} - - {% endif %} - - {% set currentStep = currentStep + 1 %} - {% endfor %} -
{{ "TODAY" | translate }}{{ "TOMORROW" | translate }}{{ f.date.format("ddd") }}
{{ "TODAY" | translate }}{{ "TOMORROW" | translate }}{{ f.date.format("ddd") }} - - - {{ f.maxTemperature | roundValue | unit("temperature") | decimalSymbol }} - - {{ f.minTemperature | roundValue | unit("temperature") | decimalSymbol }} - - {{ f.precipitationAmount | unit("precip", f.precipitationUnits) }} - - {{ f.precipitationProbability | unit('precip', '%') }} - - {{ f.uv_index }} - -
+ + + + {{ f.maxTemperature | roundValue | unit("temperature") | decimalSymbol }} + {{ f.minTemperature | roundValue | unit("temperature") | decimalSymbol }} + {% if config.showPrecipitationAmount %} + {{ f.precipitationAmount | unit("precip", f.precipitationUnits) }} + {% endif %} + {% if config.showPrecipitationProbability %} + {{ f.precipitationProbability | unit('precip', '%') }} + {% endif %} + {% if config.showUVIndex %} + + {{ f.uv_index }} + + + {% endif %} + + {% set currentStep = currentStep + 1 %} + {% endfor %} + {% else %} -
{{ "LOADING" | translate }}
+
{{ "LOADING" | translate }}
{% endif %} - + diff --git a/modules/default/weather/hourly.njk b/modules/default/weather/hourly.njk index 4223390b..05416de7 100644 --- a/modules/default/weather/hourly.njk +++ b/modules/default/weather/hourly.njk @@ -1,52 +1,48 @@ {% if hourly %} - {% set numSteps = hourly | calcNumEntries %} - {% set currentStep = 0 %} - - {% set hours = hourly.slice(0, numSteps) %} - {% for hour in hours %} - - - - - {% if config.showUVIndex %} - - {% endif %} - {% if config.showHumidity != "none" %} - - {% endif %} - {% if config.showPrecipitationAmount %} - {% if (not config.hideZeroes or hour.precipitationAmount>0) %} - - {% endif %} - {% endif %} - {% if config.showPrecipitationProbability %} - {% if (not config.hideZeroes or hour.precipitationAmount>0) %} - - {% endif %} - {% endif %} - - {% set currentStep = currentStep + 1 %} - {% endfor %} -
{{ hour.date | formatTime }} - - - {{ hour.temperature | roundValue | unit("temperature") }} - - {% if hour.uv_index!=0 %} - {{ hour.uv_index }} - - {% endif %} - - {{ hour.humidity }} - - - {{ hour.precipitationAmount | unit("precip", hour.precipitationUnits) }} - - {{ hour.precipitationProbability | unit('precip', '%') }} -
+ {% set numSteps = hourly | calcNumEntries %} + {% set currentStep = 0 %} + + {% set hours = hourly.slice(0, numSteps) %} + {% for hour in hours %} + + + + + {% if config.showUVIndex %} + + {% endif %} + {% if config.showHumidity != "none" %} + + {% endif %} + {% if config.showPrecipitationAmount %} + {% if (not config.hideZeroes or hour.precipitationAmount>0) %} + + {% endif %} + {% endif %} + {% if config.showPrecipitationProbability %} + {% if (not config.hideZeroes or hour.precipitationAmount>0) %} + + {% endif %} + {% endif %} + + {% set currentStep = currentStep + 1 %} + {% endfor %} +
{{ hour.date | formatTime }} + + {{ hour.temperature | roundValue | unit("temperature") }} + {% if hour.uv_index!=0 %} + {{ hour.uv_index }} + + {% endif %} + + {{ hour.humidity }} + + {{ hour.precipitationAmount | unit("precip", hour.precipitationUnits) }}{{ hour.precipitationProbability | unit('precip', '%') }}
{% else %} -
{{ "LOADING" | translate }}
+
{{ "LOADING" | translate }}
{% endif %} - + diff --git a/modules/default/weather/providers/envcanada.js b/modules/default/weather/providers/envcanada.js index 82558026..cf397c55 100644 --- a/modules/default/weather/providers/envcanada.js +++ b/modules/default/weather/providers/envcanada.js @@ -24,6 +24,8 @@ * 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/ */ @@ -49,6 +51,9 @@ WeatherProvider.register("envcanada", { this.todayTempCacheMax = 0; this.todayCached = false; this.cacheCurrentTemp = 999; + this.lastCityPageCurrent = " "; + this.lastCityPageForecast = " "; + this.lastCityPageHourly = " "; }, /* @@ -63,69 +68,158 @@ WeatherProvider.register("envcanada", { * Override the fetchCurrentWeather method to query EC and construct a Current weather object */ fetchCurrentWeather () { - this.fetchData(this.getUrl(), "xml") - .then((data) => { - if (!data) { - // Did not receive usable new data. - return; - } - const currentWeather = this.generateWeatherObjectFromCurrentWeather(data); - - this.setCurrentWeather(currentWeather); - }) - .catch(function (request) { - Log.error("Could not load EnvCanada site data ... ", request); - }) - .finally(() => this.updateAvailable()); + this.fetchCommon("Current"); }, /* - * Override the fetchWeatherForecast method to query EC and construct Forecast weather objects + * Override the fetchWeatherForecast method to query EC and construct Forecast/Daily weather objects */ fetchWeatherForecast () { - this.fetchData(this.getUrl(), "xml") - .then((data) => { - if (!data) { - // Did not receive usable new data. - return; - } - const forecastWeather = this.generateWeatherObjectsFromForecast(data); - this.setWeatherForecast(forecastWeather); - }) - .catch(function (request) { - Log.error("Could not load EnvCanada forecast data ... ", request); - }) - .finally(() => this.updateAvailable()); + this.fetchCommon("Forecast"); + }, /* - * Override the fetchWeatherHourly method to query EC and construct Forecast weather objects + * Override the fetchWeatherHourly method to query EC and construct Hourly weather objects */ fetchWeatherHourly () { - this.fetchData(this.getUrl(), "xml") - .then((data) => { - if (!data) { - // Did not receive usable new data. - return; - } - const hourlyWeather = this.generateWeatherObjectsFromHourly(data); - - this.setWeatherHourly(hourlyWeather); - }) - .catch(function (request) { - Log.error("Could not load EnvCanada hourly data ... ", request); - }) - .finally(() => this.updateAvailable()); + this.fetchCommon("Hourly"); }, /* - * 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. + * 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 approriate URL for the MSC Datamart Index page + + Log.debug(`[weather.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(`weather.envcanada ${target} - did not receive usable index data`); + this.updateAvailable(); // If there were issues, update anyways to reset timer + return; + } + + /** + * 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 unqiue 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 + } + + Log.debug(`[weather.envcanada] ${target} Citypage url: ${forecastFileURL}`); + + /* + * 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. + */ + + if (target === "Current" && this.lastCityPageCurrent === forecastFileURL) { + Log.debug(`[weather.envcanada] ${target} - Newest Citypage has already been seen - skipping!`); + this.updateAvailable(); // Update anyways to reset refresh timer + return; + } + + if (target === "Forecast" && this.lastCityPageForecast === forecastFileURL) { + Log.debug(`[weather.envcanada] ${target} - Newest Citypage has already been seen - skipping!`); + this.updateAvailable(); // Update anyways to reset refresh timer + return; + } + + if (target === "Hourly" && this.lastCityPageHourly === forecastFileURL) { + Log.debug(`[weather.envcanada] ${target} - Newest Citypage has already been seen - skipping!`); + this.updateAvailable(); // Update anyways to reset refresh timer + 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(`weather.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(`[weather.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(`weather.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(`weather.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 () { - return `https://dd.weather.gc.ca/citypage_weather/xml/${this.config.provCode}/${this.config.siteCode}_e.xml`; + let forecastURL = `https://dd.weather.gc.ca/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 }, /* @@ -151,7 +245,6 @@ WeatherProvider.register("envcanada", { } currentWeather.windSpeed = WeatherUtils.convertWindToMs(ECdoc.querySelector("siteData currentConditions wind speed").textContent); - currentWeather.windFromDirection = ECdoc.querySelector("siteData currentConditions wind bearing").textContent; currentWeather.humidity = ECdoc.querySelector("siteData currentConditions relativeHumidity").textContent; @@ -214,7 +307,7 @@ WeatherProvider.register("envcanada", { /* * 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. + * element details the Tonight (nighttime) forecast. Element 0 is always for the current day. * * However... the forecast is somewhat 'rolling'. * @@ -225,7 +318,7 @@ WeatherProvider.register("envcanada", { * * 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, + * 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 Todat forecast in Element 11. * @@ -436,17 +529,17 @@ WeatherProvider.register("envcanada", { * 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 + * 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 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 + * 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 nightime portions + * 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 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. + * 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")) { diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index 0d1fec43..38e694a9 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -13,7 +13,7 @@ WeatherProvider.register("openmeteo", { /* * Set the name of the provider. - * Not strictly required, but helps for debugging. + * Not strictly required but helps for debugging. */ providerName: "Open-Meteo", @@ -348,7 +348,7 @@ WeatherProvider.register("openmeteo", { generateWeatherDayFromCurrentWeather (weather) { /** - * Since some units comes from API response "splitted" into daily, hourly and current_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): * ``` @@ -381,6 +381,7 @@ WeatherProvider.register("openmeteo", { 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); diff --git a/modules/default/weather/providers/smhi.js b/modules/default/weather/providers/smhi.js index 14185c86..f01fe486 100644 --- a/modules/default/weather/providers/smhi.js +++ b/modules/default/weather/providers/smhi.js @@ -254,7 +254,7 @@ WeatherProvider.register("smhi", { * 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 {*} The value of the property in the weatherdata + * @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]; diff --git a/modules/default/weather/providers/weathergov.js b/modules/default/weather/providers/weathergov.js index d8fa621a..602e409c 100644 --- a/modules/default/weather/providers/weathergov.js +++ b/modules/default/weather/providers/weathergov.js @@ -218,7 +218,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 ? currentWeatherData.precipitationLastHour.value : currentWeatherData.precipitationLast3Hours.value; + currentWeather.precipitationAmount = currentWeatherData.precipitationLastHour?.value ?? currentWeatherData.precipitationLast3Hours?.value; if (currentWeatherData.heatIndex.value !== null) { currentWeather.feelsLikeTemp = currentWeatherData.heatIndex.value; } else if (currentWeatherData.windChill.value !== null) { diff --git a/modules/default/weather/weather.css b/modules/default/weather/weather.css index 4618be9f..d6e8ad80 100644 --- a/modules/default/weather/weather.css +++ b/modules/default/weather/weather.css @@ -1,9 +1,6 @@ .weather .weathericon, .weather .fa-home { font-size: 75%; - line-height: 65px; - display: inline-block; - transform: translate(0, -3px); } .weather .humidity-icon { @@ -37,10 +34,6 @@ padding-right: 0; } -.weather tr .weathericon { - line-height: 25px; -} - .weather tr.colored .min-temp { color: #bcddff; } @@ -48,3 +41,9 @@ .weather tr.colored .max-temp { color: #ff8e99; } + +.weather .type-temp { + display: flex; + align-items: baseline; + gap: 10px; +} diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index 448a905c..8a81b276 100644 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -163,11 +163,12 @@ Module.register("weather", { // What to do when the weather provider has new information available? updateAvailable () { Log.log("New weather information available."); - this.updateDom(0); + // 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("-", "_") }); + this.sendNotification("CURRENTWEATHER_TYPE", { type: this.weatherProvider.currentWeather().weatherType?.replace("-", "_") }); } const notificationPayload = { diff --git a/modules/default/weather/weatherutils.js b/modules/default/weather/weatherutils.js index 75414143..43a273b5 100644 --- a/modules/default/weather/weatherutils.js +++ b/modules/default/weather/weatherutils.js @@ -53,7 +53,7 @@ const WeatherUtils = { /** * Convert temp (from degrees C) into imperial or metric unit depending on * your config - * @param {number} tempInC the temperature in celsius you want to convert + * @param {number} tempInC the temperature in Celsius you want to convert * @param {string} unit can be 'imperial' or 'metric' * @returns {number} the converted temperature */ @@ -61,6 +61,15 @@ const WeatherUtils = { return unit === "imperial" ? tempInC * 1.8 + 32 : tempInC; }, + /** + * Convert temp (from degrees C) into metric unit + * @param {number} tempInF the temperature in Fahrenheit you want to convert + * @returns {number} the converted temperature + */ + convertTempToMetric (tempInF) { + return ((tempInF - 32) * 5) / 9; + }, + /** * Convert wind speed into another unit. * @param {number} windInMS the windspeed in meter/sec you want to convert @@ -118,27 +127,51 @@ const WeatherUtils = { return kmh * 0.27777777777778; }, + /** + * Taken from https://community.home-assistant.io/t/calculating-apparent-feels-like-temperature/370834/18 + * @param {number} temperature temperature in degrees Celsius + * @param {number} windSpeed wind speed in meter/second + * @param {number} humidity relative humidity in percent + * @returns {number} the feels like temperature in degrees Celsius + */ calculateFeelsLike (temperature, windSpeed, humidity) { const windInMph = this.convertWind(windSpeed, "imperial"); const tempInF = this.convertTemp(temperature, "imperial"); - let feelsLike = tempInF; - if (windInMph > 3 && tempInF < 50) { - feelsLike = Math.round(35.74 + 0.6215 * tempInF - 35.75 * Math.pow(windInMph, 0.16) + 0.4275 * tempInF * Math.pow(windInMph, 0.16)); - } 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; + let HI; + let WC = tempInF; + + // Calculate wind chill for certain conditions + if (tempInF <= 70 && windInMph >= 3) { + WC = 35.74 + (0.6215 * tempInF) - 35.75 * Math.pow(windInMph, 0.16) + ((0.4275 * tempInF) * Math.pow(windInMph, 0.16)); } - return ((feelsLike - 32) * 5) / 9; + // Steadman Heat Index Vorberechnung + const STEADMAN_HI = 0.5 * (tempInF + 61.0 + ((tempInF - 68.0) * 1.2) + (humidity * 0.094)); + + if (STEADMAN_HI >= 80) { + // Rothfusz-Komplex + const ROTHFUSZ_HI = -42.379 + 2.04901523 * tempInF + 10.14333127 * humidity - 0.22475541 * tempInF * humidity - 0.00683783 * tempInF * tempInF - 0.05481717 * humidity * humidity + 0.00122874 * tempInF * tempInF * humidity + 0.00085282 * tempInF * humidity * humidity - 0.00000199 * tempInF * tempInF * humidity * humidity; + + HI = ROTHFUSZ_HI; + + if (humidity < 13 && tempInF > 80 && tempInF < 112) { + const ADJUSTMENT = ((13 - humidity) / 4) * Math.pow(Math.abs(17 - (tempInF - 95)), 0.5) / 17; // sqrt Teil + HI = HI - ADJUSTMENT; + } else if (humidity > 85 && tempInF > 80 && tempInF < 87) { + const ADJUSTMENT = ((humidity - 85) / 10) * ((87 - tempInF) / 5); + HI = HI + ADJUSTMENT; + } + + } else { HI = STEADMAN_HI; } + + // Feuchte Lastberechnung FL + let FL; + if (tempInF < 50) { FL = WC; } + else if (tempInF >= 50 && tempInF < 70) { FL = ((70 - tempInF) / 20) * WC + ((tempInF - 50) / 20) * HI; } + else if (tempInF >= 70) { FL = HI; } + + return this.convertTempToMetric(FL); }, /** diff --git a/package-lock.json b/package-lock.json index 26a625db..e376534a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,110 +1,119 @@ { "name": "magicmirror", - "version": "2.32.0", + "version": "2.33.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "magicmirror", - "version": "2.32.0", + "version": "2.33.0", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@fontsource/roboto": "^5.2.6", - "@fontsource/roboto-condensed": "^5.2.6", - "@fortawesome/fontawesome-free": "^6.7.2", + "@fontsource/roboto": "^5.2.8", + "@fontsource/roboto-condensed": "^5.2.8", + "@fortawesome/fontawesome-free": "^7.0.1", "ajv": "^8.17.1", "animate.css": "^4.1.1", "console-stamp": "^3.1.2", "croner": "^9.1.0", "envsub": "^4.1.0", - "eslint": "^9.30.0", + "eslint": "^9.36.0", "express": "^5.1.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^8.1.0", "html-to-text": "^9.0.5", - "iconv-lite": "^0.6.3", + "iconv-lite": "^0.7.0", "module-alias": "^2.2.3", "moment": "^2.30.1", "moment-timezone": "^0.6.0", - "node-ical": "^0.20.1", + "node-ical": "^0.21.0", "nunjucks": "^3.2.4", - "pm2": "^6.0.8", + "pm2": "^6.0.13", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.27.7", - "undici": "^7.11.0", + "systeminformation": "^5.27.10", + "undici": "^7.16.0", "weathericons": "^2.1.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^5.1.0", - "cspell": "^9.1.2", + "@stylistic/eslint-plugin": "^5.4.0", + "cspell": "^9.2.1", "eslint-plugin-import-x": "^4.16.1", "eslint-plugin-jest": "^29.0.1", - "eslint-plugin-jsdoc": "^51.2.3", - "eslint-plugin-package-json": "^0.42.0", + "eslint-plugin-jsdoc": "^60.1.1", + "eslint-plugin-package-json": "^0.56.3", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", - "jest": "^30.0.3", - "jsdom": "^26.1.0", - "lint-staged": "^16.1.2", + "jest": "^30.1.3", + "jsdom": "^27.0.0", + "lint-staged": "^16.2.0", "markdownlint-cli2": "^0.18.1", - "playwright": "^1.53.1", + "playwright": "^1.55.0", "prettier": "^3.6.2", - "sinon": "^21.0.0", - "stylelint": "^16.21.0", - "stylelint-config-standard": "^38.0.0", + "prettier-plugin-jinja-template": "^2.1.0", + "stylelint": "^16.24.0", + "stylelint-config-standard": "^39.0.0", "stylelint-prettier": "^5.0.3" }, "engines": { - "node": ">=22.14.0" + "node": ">=22.18.0" }, "optionalDependencies": { - "electron": "^36.6.0" + "electron": "^38.1.2" } }, "node_modules/@altano/repository-tools": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@altano/repository-tools/-/repository-tools-1.0.1.tgz", - "integrity": "sha512-/FFHQOMp5TZWplkDWbbLIjmANDr9H/FtqUm+hfJMK76OBut0Ht0cNfd0ZXd/6LXf4pWUTzvpgVjcin7EEHSznA==", + "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==", "dev": true, "license": "ISC" }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "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" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@asamuzakjp/css-color": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", - "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.0.4.tgz", + "integrity": "sha512-cKjSKvWGmAziQWbCouOsFwb14mp1betm8Y7Fn+yglDMUUu3r9DCbJ9iJbeFDenLMqFbIMC0pQP8K+B8LAxX3OQ==", "dev": true, "license": "MIT", "dependencies": { - "@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" + "@csstools/css-calc": "^2.1.4", + "@csstools/css-color-parser": "^3.0.10", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "lru-cache": "^11.1.0" } }, "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.1.tgz", + "integrity": "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.5.5.tgz", + "integrity": "sha512-kI2MX9pmImjxWT8nxDZY+MuN6r1jJGe7WxizEbsAEPB/zxfW5wYLIiPG1v3UKgEOOP8EsDkp0ZL99oRFAdPM8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" }, "node_modules/@babel/code-frame": { "version": "7.27.1", @@ -122,9 +131,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.7.tgz", - "integrity": "sha512-xgu/ySj2mTiUFmdE9yCMfBxLp4DHd5DwmbbD05YAuICfodYT3VvRxbrh81LGQ/8UpSdtMdfKMn3KouYDX59DGQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", "dev": true, "license": "MIT", "engines": { @@ -132,22 +141,22 @@ } }, "node_modules/@babel/core": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.7.tgz", - "integrity": "sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.5", + "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.27.7", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.7", - "@babel/types": "^7.27.7", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -173,16 +182,16 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", - "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.5", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -216,6 +225,16 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", @@ -231,15 +250,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "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==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -289,27 +308,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", - "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", - "@babel/types": "^7.27.6" + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", - "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.7" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -573,38 +592,28 @@ } }, "node_modules/@babel/traverse": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.7.tgz", - "integrity": "sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.5", - "@babel/parser": "^7.27.7", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/types": "^7.27.7", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/types": "^7.28.4", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "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" - } - }, "node_modules/@babel/types": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", - "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -622,93 +631,134 @@ "dev": true, "license": "MIT" }, - "node_modules/@cspell/cspell-bundled-dicts": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.1.2.tgz", - "integrity": "sha512-mdhxj7j1zqXYKO/KPx2MgN3RPAvqoWvncxz2dOMFBcuUteZPt58NenUoi0VZXEhV/FM2V80NvhHZZafaIcxVjQ==", + "node_modules/@cacheable/memoize": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@cacheable/memoize/-/memoize-2.0.2.tgz", + "integrity": "sha512-wPrr7FUiq3Qt4yQyda2/NcOLTJCFcQSU3Am2adP+WLy+sz93/fKTokVTHmtz+rjp4PD7ee0AEOeRVNN6IvIfsg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-ada": "^4.1.0", - "@cspell/dict-al": "^1.1.0", - "@cspell/dict-aws": "^4.0.10", - "@cspell/dict-bash": "^4.2.0", - "@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.8", - "@cspell/dict-django": "^4.1.4", - "@cspell/dict-docker": "^1.1.14", - "@cspell/dict-dotnet": "^5.0.9", - "@cspell/dict-elixir": "^4.0.7", - "@cspell/dict-en_us": "^4.4.11", - "@cspell/dict-en-common-misspellings": "^2.1.1", - "@cspell/dict-en-gb-mit": "^3.1.1", - "@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.1", - "@cspell/dict-git": "^3.0.6", - "@cspell/dict-golang": "^6.0.22", - "@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", - "@cspell/dict-java": "^5.0.11", - "@cspell/dict-julia": "^1.1.0", - "@cspell/dict-k8s": "^1.0.11", - "@cspell/dict-kotlin": "^1.1.0", - "@cspell/dict-latex": "^4.0.3", - "@cspell/dict-lorem-ipsum": "^4.0.4", - "@cspell/dict-lua": "^4.0.7", - "@cspell/dict-makefile": "^1.0.4", - "@cspell/dict-markdown": "^2.0.11", - "@cspell/dict-monkeyc": "^1.0.10", - "@cspell/dict-node": "^5.0.7", - "@cspell/dict-npm": "^5.2.7", - "@cspell/dict-php": "^4.0.14", - "@cspell/dict-powershell": "^5.0.14", - "@cspell/dict-public-licenses": "^2.0.13", - "@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.1.1", - "@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.2", - "@cspell/dict-vue": "^3.0.4" + "@cacheable/utils": "^2.0.2" + } + }, + "node_modules/@cacheable/memory": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.0.2.tgz", + "integrity": "sha512-sJTITLfeCI1rg7P3ssaGmQryq235EGT8dXGcx6oZwX5NRnKq9IE6lddlllcOl+oXW+yaeTRddCjo0xrfU6ZySA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/memoize": "^2.0.1", + "@cacheable/utils": "^2.0.2", + "@keyv/bigmap": "^1.0.2", + "hookified": "^1.12.1", + "keyv": "^5.5.2" + } + }, + "node_modules/@cacheable/memory/node_modules/keyv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.2.tgz", + "integrity": "sha512-TXcFHbmm/z7MGd1u9ASiCSfTS+ei6Z8B3a5JHzx3oPa/o7QzWVtPRpc4KGER5RR469IC+/nfg4U5YLIuDUua2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.0.2.tgz", + "integrity": "sha512-JTFM3raFhVv8LH95T7YnZbf2YoE9wEtkPPStuRF9a6ExZ103hFvs+QyCuYJ6r0hA9wRtbzgZtwUCoDWxssZd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/cspell-bundled-dicts": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.2.1.tgz", + "integrity": "sha512-85gHoZh3rgZ/EqrHIr1/I4OLO53fWNp6JZCqCdgaT7e3sMDaOOG6HoSxCvOnVspXNIf/1ZbfTCDMx9x79Xq0AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-ada": "^4.1.1", + "@cspell/dict-al": "^1.1.1", + "@cspell/dict-aws": "^4.0.15", + "@cspell/dict-bash": "^4.2.1", + "@cspell/dict-companies": "^3.2.5", + "@cspell/dict-cpp": "^6.0.12", + "@cspell/dict-cryptocurrencies": "^5.0.5", + "@cspell/dict-csharp": "^4.0.7", + "@cspell/dict-css": "^4.0.18", + "@cspell/dict-dart": "^2.3.1", + "@cspell/dict-data-science": "^2.0.9", + "@cspell/dict-django": "^4.1.5", + "@cspell/dict-docker": "^1.1.16", + "@cspell/dict-dotnet": "^5.0.10", + "@cspell/dict-elixir": "^4.0.8", + "@cspell/dict-en_us": "^4.4.18", + "@cspell/dict-en-common-misspellings": "^2.1.5", + "@cspell/dict-en-gb-mit": "^3.1.8", + "@cspell/dict-filetypes": "^3.0.13", + "@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-gaming-terms": "^1.1.2", + "@cspell/dict-git": "^3.0.7", + "@cspell/dict-golang": "^6.0.23", + "@cspell/dict-google": "^1.0.9", + "@cspell/dict-haskell": "^4.0.6", + "@cspell/dict-html": "^4.0.12", + "@cspell/dict-html-symbol-entities": "^4.0.4", + "@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": "^4.0.4", + "@cspell/dict-lorem-ipsum": "^4.0.5", + "@cspell/dict-lua": "^4.0.8", + "@cspell/dict-makefile": "^1.0.5", + "@cspell/dict-markdown": "^2.0.12", + "@cspell/dict-monkeyc": "^1.0.11", + "@cspell/dict-node": "^5.0.8", + "@cspell/dict-npm": "^5.2.15", + "@cspell/dict-php": "^4.0.15", + "@cspell/dict-powershell": "^5.0.15", + "@cspell/dict-public-licenses": "^2.0.15", + "@cspell/dict-python": "^4.2.19", + "@cspell/dict-r": "^2.1.1", + "@cspell/dict-ruby": "^5.0.9", + "@cspell/dict-rust": "^4.0.12", + "@cspell/dict-scala": "^5.0.8", + "@cspell/dict-shell": "^1.1.1", + "@cspell/dict-software-terms": "^5.1.7", + "@cspell/dict-sql": "^2.2.1", + "@cspell/dict-svelte": "^1.0.7", + "@cspell/dict-swift": "^2.0.6", + "@cspell/dict-terraform": "^1.1.3", + "@cspell/dict-typescript": "^3.2.3", + "@cspell/dict-vue": "^3.0.5" }, "engines": { "node": ">=20" } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.1.2.tgz", - "integrity": "sha512-sSva/ACXDJd9LufzecR9LC+lNWUuGWNtVHdVj0orJxOIZjHUCNBXwVSgL2fmMg7jNQS6qoJFJ7F/QPXdwITijg==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.2.1.tgz", + "integrity": "sha512-LiiIWzLP9h2etKn0ap6g2+HrgOGcFEF/hp5D8ytmSL5sMxDcV13RrmJCEMTh1axGyW0SjQEFjPnYzNpCL1JjGA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.1.2" + "@cspell/cspell-types": "9.2.1" }, "engines": { "node": ">=20" } }, "node_modules/@cspell/cspell-pipe": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.1.2.tgz", - "integrity": "sha512-/pIhsf4SI4Q/kvehq9GsGKLgbQsRhiDgthQIgO6YOrEa761wOI2hVdRyc0Tgc1iAGiJEedDaFsAhabVRJBeo2g==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.2.1.tgz", + "integrity": "sha512-2N1H63If5cezLqKToY/YSXon4m4REg/CVTFZr040wlHRbbQMh5EF3c7tEC/ue3iKAQR4sm52ihfqo1n4X6kz+g==", "dev": true, "license": "MIT", "engines": { @@ -716,9 +766,9 @@ } }, "node_modules/@cspell/cspell-resolver": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.1.2.tgz", - "integrity": "sha512-dNDx7yMl2h1Ousk08lizTou+BUvce4RPSnPXrQPB7B7CscgZloSyuP3Yyj1Zt81pHNpggrym4Ezx6tMdyPjESw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.2.1.tgz", + "integrity": "sha512-fRPQ6GWU5eyh8LN1TZblc7t24TlGhJprdjJkfZ+HjQo+6ivdeBPT7pC7pew6vuMBQPS1oHBR36hE0ZnJqqkCeg==", "dev": true, "license": "MIT", "dependencies": { @@ -729,9 +779,9 @@ } }, "node_modules/@cspell/cspell-service-bus": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.1.2.tgz", - "integrity": "sha512-YOsUctzCMzEJbKdzNyvPkyMen/i7sGO3Xgcczn848GJPlRsJc50QwsoU67SY7zEARz6y2WS0tv5F5RMrRO4idw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.2.1.tgz", + "integrity": "sha512-k4M6bqdvWbcGSbcfLD7Lf4coZVObsISDW+sm/VaWp9aZ7/uwiz1IuGUxL9WO4JIdr9CFEf7Ivmvd2txZpVOCIA==", "dev": true, "license": "MIT", "engines": { @@ -739,9 +789,9 @@ } }, "node_modules/@cspell/cspell-types": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.1.2.tgz", - "integrity": "sha512-bSDDjoQi4pbh1BULEA596XCo1PMShTpTb4J2lj8jVYqYgXYQNjSmQFA1fj4NHesC84JpK1um4ybzXBcqtniC7Q==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.2.1.tgz", + "integrity": "sha512-FQHgQYdTHkcpxT0u1ddLIg5Cc5ePVDcLg9+b5Wgaubmc5I0tLotgYj8c/mvStWuKsuZIs6sUopjJrE91wk6Onw==", "dev": true, "license": "MIT", "engines": { @@ -749,441 +799,441 @@ } }, "node_modules/@cspell/dict-ada": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.1.0.tgz", - "integrity": "sha512-7SvmhmX170gyPd+uHXrfmqJBY5qLcCX8kTGURPVeGxmt8XNXT75uu9rnZO+jwrfuU2EimNoArdVy5GZRGljGNg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.1.1.tgz", + "integrity": "sha512-E+0YW9RhZod/9Qy2gxfNZiHJjCYFlCdI69br1eviQQWB8yOTJX0JHXLs79kOYhSW0kINPVUdvddEBe6Lu6CjGQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-al": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.1.0.tgz", - "integrity": "sha512-PtNI1KLmYkELYltbzuoztBxfi11jcE9HXBHCpID2lou/J4VMYKJPNqe4ZjVzSI9NYbMnMnyG3gkbhIdx66VSXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.1.1.tgz", + "integrity": "sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-aws": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.10.tgz", - "integrity": "sha512-0qW4sI0GX8haELdhfakQNuw7a2pnWXz3VYQA2MpydH2xT2e6EN9DWFpKAi8DfcChm8MgDAogKkoHtIo075iYng==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.15.tgz", + "integrity": "sha512-aPY7VVR5Os4rz36EaqXBAEy14wR4Rqv+leCJ2Ug/Gd0IglJpM30LalF3e2eJChnjje3vWoEC0Rz3+e5gpZG+Kg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-bash": { - "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==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.2.1.tgz", + "integrity": "sha512-SBnzfAyEAZLI9KFS7DUG6Xc1vDFuLllY3jz0WHvmxe8/4xV3ufFE3fGxalTikc1VVeZgZmxYiABw4iGxVldYEg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-shell": "1.1.0" + "@cspell/dict-shell": "1.1.1" } }, "node_modules/@cspell/dict-companies": { - "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==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.2.5.tgz", + "integrity": "sha512-H51R0w7c6RwJJPqH7Gs65tzP6ouZsYDEHmmol6MIIk0kQaOIBuFP2B3vIxHLUr2EPRVFZsMW8Ni7NmVyaQlwsg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cpp": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.8.tgz", - "integrity": "sha512-BzurRZilWqaJt32Gif6/yCCPi+FtrchjmnehVEIFzbWyeBd/VOUw77IwrEzehZsu5cRU91yPWuWp5fUsKfDAXA==", + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.12.tgz", + "integrity": "sha512-N4NsCTttVpMqQEYbf0VQwCj6np+pJESov0WieCN7R/0aByz4+MXEiDieWWisaiVi8LbKzs1mEj4ZTw5K/6O2UQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-cryptocurrencies": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.4.tgz", - "integrity": "sha512-6iFu7Abu+4Mgqq08YhTKHfH59mpMpGTwdzDB2Y8bbgiwnGFCeoiSkVkgLn1Kel2++hYcZ8vsAW/MJS9oXxuMag==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.5.tgz", + "integrity": "sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-csharp": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.6.tgz", - "integrity": "sha512-w/+YsqOknjQXmIlWDRmkW+BHBPJZ/XDrfJhZRQnp0wzpPOGml7W0q1iae65P2AFRtTdPKYmvSz7AL5ZRkCnSIw==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.7.tgz", + "integrity": "sha512-H16Hpu8O/1/lgijFt2lOk4/nnldFtQ4t8QHbyqphqZZVE5aS4J/zD/WvduqnLY21aKhZS6jo/xF5PX9jyqPKUA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-css": { - "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==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.18.tgz", + "integrity": "sha512-EF77RqROHL+4LhMGW5NTeKqfUd/e4OOv6EDFQ/UQQiFyWuqkEKyEz0NDILxOFxWUEVdjT2GQ2cC7t12B6pESwg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-dart": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.3.0.tgz", - "integrity": "sha512-1aY90lAicek8vYczGPDKr70pQSTQHwMFLbmWKTAI6iavmb1fisJBS1oTmMOKE4ximDf86MvVN6Ucwx3u/8HqLg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.3.1.tgz", + "integrity": "sha512-xoiGnULEcWdodXI6EwVyqpZmpOoh8RA2Xk9BNdR7DLamV/QMvEYn8KJ7NlRiTSauJKPNkHHQ5EVHRM6sTS7jdg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-data-science": { - "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==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.9.tgz", + "integrity": "sha512-wTOFMlxv06veIwKdXUwdGxrQcK44Zqs426m6JGgHIB/GqvieZQC5n0UI+tUm5OCxuNyo4OV6mylT4cRMjtKtWQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-django": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.4.tgz", - "integrity": "sha512-fX38eUoPvytZ/2GA+g4bbdUtCMGNFSLbdJJPKX2vbewIQGfgSFJKY56vvcHJKAvw7FopjvgyS/98Ta9WN1gckg==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.5.tgz", + "integrity": "sha512-AvTWu99doU3T8ifoMYOMLW2CXKvyKLukPh1auOPwFGHzueWYvBBN+OxF8wF7XwjTBMMeRleVdLh3aWCDEX/ZWg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-docker": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.14.tgz", - "integrity": "sha512-p6Qz5mokvcosTpDlgSUREdSbZ10mBL3ndgCdEKMqjCSZJFdfxRdNdjrGER3lQ6LMq5jGr1r7nGXA0gvUJK80nw==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.16.tgz", + "integrity": "sha512-UiVQ5RmCg6j0qGIxrBnai3pIB+aYKL3zaJGvXk1O/ertTKJif9RZikKXCEgqhaCYMweM4fuLqWSVmw3hU164Iw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-dotnet": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.9.tgz", - "integrity": "sha512-JGD6RJW5sHtO5lfiJl11a5DpPN6eKSz5M1YBa1I76j4dDOIqgZB6rQexlDlK1DH9B06X4GdDQwdBfnpAB0r2uQ==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.10.tgz", + "integrity": "sha512-ooar8BP/RBNP1gzYfJPStKEmpWy4uv/7JCq6FOnJLeD1yyfG3d/LFMVMwiJo+XWz025cxtkM3wuaikBWzCqkmg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-elixir": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.7.tgz", - "integrity": "sha512-MAUqlMw73mgtSdxvbAvyRlvc3bYnrDqXQrx5K9SwW8F7fRYf9V4vWYFULh+UWwwkqkhX9w03ZqFYRTdkFku6uA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.8.tgz", + "integrity": "sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.12.tgz", - "integrity": "sha512-p/ACn/SXcfCTAIAUfbvHrG/jacLDzo6V9Vc5mjtTMSaqeJVir4w5G9r1Pz19zcUvFzgio/Kg5b2xmosjPirLsg==", + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.19.tgz", + "integrity": "sha512-JYYgzhGqSGuIMNY1cTlmq3zrNpehrExMHqLmLnSM2jEGFeHydlL+KLBwBYxMy4e73w+p1+o/rmAiGsMj9g3MCw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.1.1.tgz", - "integrity": "sha512-6m2EEm4WUgsNzFzz/2boeOVrZenYQRaDXFtDNcaQK5Ly4A37HTRPm8uVvE8cAlACVk+HBHhH/4e7ebxdXwId9w==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.1.6.tgz", + "integrity": "sha512-xV9yryOqZizbSqxRS7kSVRrxVEyWHUqwdY56IuT7eAWGyTCJNmitXzXa4p+AnEbhL+AB2WLynGVSbNoUC3ceFA==", "dev": true, "license": "CC BY-SA 4.0" }, "node_modules/@cspell/dict-en-gb-mit": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.2.tgz", - "integrity": "sha512-IOsS2auF07ZOUqXsp4zuCaf3W5/OolWLvdq9xPd/ZQH2BfoFEmjdhelYaRuOKOmd6+SWdEbGhEeI7oLZSREqIQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.9.tgz", + "integrity": "sha512-1lSnphnHTOxnpNLpPLg1XXv8df3hs4oL0LJ6dkQ0IqNROl8Jzl6PD55BDTlKy4YOAA76dJlePB0wyrxB+VVKbg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-filetypes": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.12.tgz", - "integrity": "sha512-+ds5wgNdlUxuJvhg8A1TjuSpalDFGCh7SkANCWvIplg6QZPXL4j83lqxP7PgjHpx7PsBUS7vw0aiHPjZy9BItw==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.13.tgz", + "integrity": "sha512-g6rnytIpQlMNKGJT1JKzWkC+b3xCliDKpQ3ANFSq++MnR4GaLiifaC4JkVON11Oh/UTplYOR1nY3BR4X30bswA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-flutter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.1.0.tgz", - "integrity": "sha512-3zDeS7zc2p8tr9YH9tfbOEYfopKY/srNsAa+kE3rfBTtQERAZeOhe5yxrnTPoufctXLyuUtcGMUTpxr3dO0iaA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.1.1.tgz", + "integrity": "sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-fonts": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.4.tgz", - "integrity": "sha512-cHFho4hjojBcHl6qxidl9CvUb492IuSk7xIf2G2wJzcHwGaCFa2o3gRcxmIg1j62guetAeDDFELizDaJlVRIOg==", + "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==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-fsharp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.1.0.tgz", - "integrity": "sha512-oguWmHhGzgbgbEIBKtgKPrFSVAFtvGHaQS0oj+vacZqMObwkapcTGu7iwf4V3Bc2T3caf0QE6f6rQfIJFIAVsw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.1.1.tgz", + "integrity": "sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-fullstack": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.6.tgz", - "integrity": "sha512-cSaq9rz5RIU9j+0jcF2vnKPTQjxGXclntmoNp4XB7yFX2621PxJcekGjwf/lN5heJwVxGLL9toR0CBlGKwQBgA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.7.tgz", + "integrity": "sha512-IxEk2YAwAJKYCUEgEeOg3QvTL4XLlyArJElFuMQevU1dPgHgzWElFevN5lsTFnvMFA1riYsVinqJJX0BanCFEg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-gaming-terms": { - "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==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.1.2.tgz", + "integrity": "sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-git": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.6.tgz", - "integrity": "sha512-nazfOqyxlBOQGgcur9ssEOEQCEZkH8vXfQe8SDEx8sCN/g0SFm8ktabgLVmBOXjy3RzjVNLlM2nBfRQ7e6+5hQ==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.7.tgz", + "integrity": "sha512-odOwVKgfxCQfiSb+nblQZc4ErXmnWEnv8XwkaI4sNJ7cNmojnvogYVeMqkXPjvfrgEcizEEA4URRD2Ms5PDk1w==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-golang": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.22.tgz", - "integrity": "sha512-FvV0m3Y0nUFxw36uDCD8UtfOPv4wsZnnlabNwB3xNZ2IBn0gBURuMUZywScb9sd2wXM8VFBRoU//tc6NQsOVOg==", + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.23.tgz", + "integrity": "sha512-oXqUh/9dDwcmVlfUF5bn3fYFqbUzC46lXFQmi5emB0vYsyQXdNWsqi6/yH3uE7bdRE21nP7Yo0mR1jjFNyLamg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-google": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.8.tgz", - "integrity": "sha512-BnMHgcEeaLyloPmBs8phCqprI+4r2Jb8rni011A8hE+7FNk7FmLE3kiwxLFrcZnnb7eqM0agW4zUaNoB0P+z8A==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.9.tgz", + "integrity": "sha512-biL65POqialY0i4g6crj7pR6JnBkbsPovB2WDYkj3H4TuC/QXv7Pu5pdPxeUJA6TSCHI7T5twsO4VSVyRxD9CA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-haskell": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.5.tgz", - "integrity": "sha512-s4BG/4tlj2pPM9Ha7IZYMhUujXDnI0Eq1+38UTTCpatYLbQqDwRFf2KNPLRqkroU+a44yTUAe0rkkKbwy4yRtQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.6.tgz", + "integrity": "sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-html": { - "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==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.12.tgz", + "integrity": "sha512-JFffQ1dDVEyJq6tCDWv0r/RqkdSnV43P2F/3jJ9rwLgdsOIXwQbXrz6QDlvQLVvNSnORH9KjDtenFTGDyzfCaA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-html-symbol-entities": { - "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==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.4.tgz", + "integrity": "sha512-afea+0rGPDeOV9gdO06UW183Qg6wRhWVkgCFwiO3bDupAoyXRuvupbb5nUyqSTsLXIKL8u8uXQlJ9pkz07oVXw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-java": { - "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==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.12.tgz", + "integrity": "sha512-qPSNhTcl7LGJ5Qp6VN71H8zqvRQK04S08T67knMq9hTA8U7G1sTKzLmBaDOFhq17vNX/+rT+rbRYp+B5Nwza1A==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-julia": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.1.0.tgz", - "integrity": "sha512-CPUiesiXwy3HRoBR3joUseTZ9giFPCydSKu2rkh6I2nVjXnl5vFHzOMLXpbF4HQ1tH2CNfnDbUndxD+I+7eL9w==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.1.1.tgz", + "integrity": "sha512-WylJR9TQ2cgwd5BWEOfdO3zvDB+L7kYFm0I9u0s9jKHWQ6yKmfKeMjU9oXxTBxIufhCXm92SKwwVNAC7gjv+yA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-k8s": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.11.tgz", - "integrity": "sha512-8ojNwB5j4PfZ1Gq9n5c/HKJCtZD3h6+wFy+zpALpDWFFQ2qT22Be30+3PVd+G5gng8or0LeK8VgKKd0l1uKPTA==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.12.tgz", + "integrity": "sha512-2LcllTWgaTfYC7DmkMPOn9GsBWsA4DZdlun4po8s2ysTP7CPEnZc1ZfK6pZ2eI4TsZemlUQQ+NZxMe9/QutQxg==", "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==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-kotlin/-/dict-kotlin-1.1.1.tgz", + "integrity": "sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-latex": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.3.tgz", - "integrity": "sha512-2KXBt9fSpymYHxHfvhUpjUFyzrmN4c4P8mwIzweLyvqntBT3k0YGZJSriOdjfUjwSygrfEwiuPI1EMrvgrOMJw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.4.tgz", + "integrity": "sha512-YdTQhnTINEEm/LZgTzr9Voz4mzdOXH7YX+bSFs3hnkUHCUUtX/mhKgf1CFvZ0YNM2afjhQcmLaR9bDQVyYBvpA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-lorem-ipsum": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.4.tgz", - "integrity": "sha512-+4f7vtY4dp2b9N5fn0za/UR0kwFq2zDtA62JCbWHbpjvO9wukkbl4rZg4YudHbBgkl73HRnXFgCiwNhdIA1JPw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.5.tgz", + "integrity": "sha512-9a4TJYRcPWPBKkQAJ/whCu4uCAEgv/O2xAaZEI0n4y1/l18Yyx8pBKoIX5QuVXjjmKEkK7hi5SxyIsH7pFEK9Q==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-lua": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.7.tgz", - "integrity": "sha512-Wbr7YSQw+cLHhTYTKV6cAljgMgcY+EUAxVIZW3ljKswEe4OLxnVJ7lPqZF5JKjlXdgCjbPSimsHqyAbC5pQN/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.8.tgz", + "integrity": "sha512-N4PkgNDMu9JVsRu7JBS/3E/dvfItRgk9w5ga2dKq+JupP2Y3lojNaAVFhXISh4Y0a6qXDn2clA6nvnavQ/jjLA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-makefile": { - "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==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.5.tgz", + "integrity": "sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-markdown": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.11.tgz", - "integrity": "sha512-stZieFKJyMQbzKTVoalSx2QqCpB0j8nPJF/5x+sBnDIWgMC65jp8Wil+jccWh9/vnUVukP3Ejewven5NC7SWuQ==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.12.tgz", + "integrity": "sha512-ufwoliPijAgWkD/ivAMC+A9QD895xKiJRF/fwwknQb7kt7NozTLKFAOBtXGPJAB4UjhGBpYEJVo2elQ0FCAH9A==", "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.2" + "@cspell/dict-css": "^4.0.18", + "@cspell/dict-html": "^4.0.12", + "@cspell/dict-html-symbol-entities": "^4.0.4", + "@cspell/dict-typescript": "^3.2.3" } }, "node_modules/@cspell/dict-monkeyc": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.10.tgz", - "integrity": "sha512-7RTGyKsTIIVqzbvOtAu6Z/lwwxjGRtY5RkKPlXKHEoEAgIXwfDxb5EkVwzGQwQr8hF/D3HrdYbRT8MFBfsueZw==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.11.tgz", + "integrity": "sha512-7Q1Ncu0urALI6dPTrEbSTd//UK0qjRBeaxhnm8uY5fgYNFYAG+u4gtnTIo59S6Bw5P++4H3DiIDYoQdY/lha8w==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-node": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.7.tgz", - "integrity": "sha512-ZaPpBsHGQCqUyFPKLyCNUH2qzolDRm1/901IO8e7btk7bEDF56DN82VD43gPvD4HWz3yLs/WkcLa01KYAJpnOw==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.8.tgz", + "integrity": "sha512-AirZcN2i84ynev3p2/1NCPEhnNsHKMz9zciTngGoqpdItUb2bDt1nJBjwlsrFI78GZRph/VaqTVFwYikmncpXg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.8.tgz", - "integrity": "sha512-GRv5hQZ3Buf3BouoE/NgyUKMb58IQ+knjdWFes9X7sZJ+qU9VKaNg+Ovualr6c8apee07johhMX9ZfOAkcjuRw==", + "version": "5.2.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.17.tgz", + "integrity": "sha512-0yp7lBXtN3CtxBrpvTu/yAuPdOHR2ucKzPxdppc3VKO068waZNpKikn1NZCzBS3dIAFGVITzUPtuTXxt9cxnSg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-php": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.14.tgz", - "integrity": "sha512-7zur8pyncYZglxNmqsRycOZ6inpDoVd4yFfz1pQRe5xaRWMiK3Km4n0/X/1YMWhh3e3Sl/fQg5Axb2hlN68t1g==", + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.15.tgz", + "integrity": "sha512-iepGB2gtToMWSTvybesn4/lUp4LwXcEm0s8vasJLP76WWVkq1zYjmeS+WAIzNgsuURyZ/9mGqhS0CWMuo74ODw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-powershell": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.14.tgz", - "integrity": "sha512-ktjjvtkIUIYmj/SoGBYbr3/+CsRGNXGpvVANrY0wlm/IoGlGywhoTUDYN0IsGwI2b8Vktx3DZmQkfb3Wo38jBA==", + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.15.tgz", + "integrity": "sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-public-licenses": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.13.tgz", - "integrity": "sha512-1Wdp/XH1ieim7CadXYE7YLnUlW0pULEjVl9WEeziZw3EKCAw8ZI8Ih44m4bEa5VNBLnuP5TfqC4iDautAleQzQ==", + "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==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.18", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.18.tgz", - "integrity": "sha512-hYczHVqZBsck7DzO5LumBLJM119a3F17aj8a7lApnPIS7cmEwnPc2eACNscAHDk7qAo2127oI7axUoFMe9/g1g==", + "version": "4.2.19", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.19.tgz", + "integrity": "sha512-9S2gTlgILp1eb6OJcVZeC8/Od83N8EqBSg5WHVpx97eMMJhifOzePkE0kDYjyHMtAFznCQTUu0iQEJohNQ5B0A==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-data-science": "^2.0.8" + "@cspell/dict-data-science": "^2.0.9" } }, "node_modules/@cspell/dict-r": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.1.0.tgz", - "integrity": "sha512-k2512wgGG0lTpTYH9w5Wwco+lAMf3Vz7mhqV8+OnalIE7muA0RSuD9tWBjiqLcX8zPvEJr4LdgxVju8Gk3OKyA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.1.1.tgz", + "integrity": "sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-ruby": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.8.tgz", - "integrity": "sha512-ixuTneU0aH1cPQRbWJvtvOntMFfeQR2KxT8LuAv5jBKqQWIHSxzGlp+zX3SVyoeR0kOWiu64/O5Yn836A5yMcQ==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.9.tgz", + "integrity": "sha512-H2vMcERMcANvQshAdrVx0XoWaNX8zmmiQN11dZZTQAZaNJ0xatdJoSqY8C8uhEMW89bfgpN+NQgGuDXW2vmXEw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-rust": { - "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==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.12.tgz", + "integrity": "sha512-z2QiH+q9UlNhobBJArvILRxV8Jz0pKIK7gqu4TgmEYyjiu1TvnGZ1tbYHeu9w3I/wOP6UMDoCBTty5AlYfW0mw==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-scala": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.7.tgz", - "integrity": "sha512-yatpSDW/GwulzO3t7hB5peoWwzo+Y3qTc0pO24Jf6f88jsEeKmDeKkfgPbYuCgbE4jisGR4vs4+jfQZDIYmXPA==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.8.tgz", + "integrity": "sha512-YdftVmumv8IZq9zu1gn2U7A4bfM2yj9Vaupydotyjuc+EEZZSqAafTpvW/jKLWji2TgybM1L2IhmV0s/Iv9BTw==", "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==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-shell/-/dict-shell-1.1.1.tgz", + "integrity": "sha512-T37oYxE7OV1x/1D4/13Y8JZGa1QgDCXV7AVt3HLXjn0Fe3TaNDvf5sU0fGnXKmBPqFFrHdpD3uutAQb1dlp15g==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-software-terms": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.1.2.tgz", - "integrity": "sha512-MssT9yyInezB6mFqHTDNOIVjbMakORllIt7IJ91LrgiQOcDLzidR0gN9pE340s655TJ8U5MJNAfRfH0oRU14KQ==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.1.8.tgz", + "integrity": "sha512-iwCHLP11OmVHEX2MzE8EPxpPw7BelvldxWe5cJ3xXIDL8TjF2dBTs2noGcrqnZi15SLYIlO8897BIOa33WHHZA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-sql": { - "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==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.2.1.tgz", + "integrity": "sha512-qDHF8MpAYCf4pWU8NKbnVGzkoxMNrFqBHyG/dgrlic5EQiKANCLELYtGlX5auIMDLmTf1inA0eNtv74tyRJ/vg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-svelte": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.6.tgz", - "integrity": "sha512-8LAJHSBdwHCoKCSy72PXXzz7ulGROD0rP1CQ0StOqXOOlTUeSFaJJlxNYjlONgd2c62XBQiN2wgLhtPN+1Zv7Q==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.7.tgz", + "integrity": "sha512-hGZsGqP0WdzKkdpeVLBivRuSNzOTvN036EBmpOwxH+FTY2DuUH7ecW+cSaMwOgmq5JFSdTcbTNFlNC8HN8lhaQ==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-swift": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.5.tgz", - "integrity": "sha512-3lGzDCwUmnrfckv3Q4eVSW3sK3cHqqHlPprFJZD4nAqt23ot7fic5ALR7J4joHpvDz36nHX34TgcbZNNZOC/JA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.6.tgz", + "integrity": "sha512-PnpNbrIbex2aqU1kMgwEKvCzgbkHtj3dlFLPMqW1vSniop7YxaDTtvTUO4zA++ugYAEL+UK8vYrBwDPTjjvSnA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-terraform": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.1.1.tgz", - "integrity": "sha512-07KFDwCU7EnKl4hOZLsLKlj6Zceq/IsQ3LRWUyIjvGFfZHdoGtFdCp3ZPVgnFaAcd/DKv+WVkrOzUBSYqHopQQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.1.3.tgz", + "integrity": "sha512-gr6wxCydwSFyyBKhBA2xkENXtVFToheqYYGFvlMZXWjviynXmh+NK/JTvTCk/VHk3+lzbO9EEQKee6VjrAUSbA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-typescript": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.2.tgz", - "integrity": "sha512-H9Y+uUHsTIDFO/jdfUAcqmcd5osT+2DB5b0aRCHfLWN/twUbGn/1qq3b7YwEvttxKlYzWHU3uNFf+KfA93VY7w==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.3.tgz", + "integrity": "sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dict-vue": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.4.tgz", - "integrity": "sha512-0dPtI0lwHcAgSiQFx8CzvqjdoXROcH+1LyqgROCpBgppommWpVhbQ0eubnKotFEXgpUCONVkeZJ6Ql8NbTEu+w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.5.tgz", + "integrity": "sha512-Mqutb8jbM+kIcywuPQCCaK5qQHTdaByoEO2J9LKFy3sqAdiBogNkrplqUK0HyyRFgCfbJUgjz3N85iCMcWH0JA==", "dev": true, "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.1.2.tgz", - "integrity": "sha512-Kg22HCx5m0znVPLea2jRrvMnzHZAAzqcDr5g6Dbd4Pizs5b3SPQuRpFmYaDvKo26JNZnfRqA9eweiuE5aQAf2A==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.2.1.tgz", + "integrity": "sha512-izYQbk7ck0ffNA1gf7Gi3PkUEjj+crbYeyNK1hxHx5A+GuR416ozs0aEyp995KI2v9HZlXscOj3SC3wrWzHZeA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.1.2", - "import-meta-resolve": "^4.1.0" + "@cspell/url": "9.2.1", + "import-meta-resolve": "^4.2.0" }, "engines": { "node": ">=20" } }, "node_modules/@cspell/filetypes": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.1.2.tgz", - "integrity": "sha512-j+6kDz3GbeYwwtlzVosqVaSiFGMhf0u3y8eAP3IV2bTelhP2ZiOLD+yNbAyYGao7p10/Sqv+Ri0yT7IsGLniww==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.2.1.tgz", + "integrity": "sha512-Dy1y1pQ+7hi2gPs+jERczVkACtYbUHcLodXDrzpipoxgOtVxMcyZuo+84WYHImfu0gtM0wU2uLObaVgMSTnytw==", "dev": true, "license": "MIT", "engines": { @@ -1191,9 +1241,9 @@ } }, "node_modules/@cspell/strong-weak-map": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.1.2.tgz", - "integrity": "sha512-6X9oXnklvdt1pd0x0Mh6qXaaIRxjt0G50Xz5ZGm3wpAagv0MFvTThdmYVFfBuZ91x7fDT3u77y3d1uqdGQW1CA==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.2.1.tgz", + "integrity": "sha512-1HsQWZexvJSjDocVnbeAWjjgqWE/0op/txxzDPvDqI2sE6pY0oO4Cinj2I8z+IP+m6/E6yjPxdb23ydbQbPpJQ==", "dev": true, "license": "MIT", "engines": { @@ -1201,9 +1251,9 @@ } }, "node_modules/@cspell/url": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.1.2.tgz", - "integrity": "sha512-PMJBuLYQIdFnEfPHQXaVE5hHUkbbOxOIRmHyZwWEc9+79tIaIkiwLpjZvbm8p6f9WXAaESqXs/uK2tUC/bjwmw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.2.1.tgz", + "integrity": "sha512-9EHCoGKtisPNsEdBQ28tKxKeBmiVS3D4j+AN8Yjr+Dmtu+YACKGWiMOddNZG2VejQNIdFx7FwzU00BGX68ELhA==", "dev": true, "license": "MIT", "engines": { @@ -1211,9 +1261,9 @@ } }, "node_modules/@csstools/color-helpers": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz", - "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==", + "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==", "dev": true, "funding": [ { @@ -1255,9 +1305,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.10.tgz", - "integrity": "sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==", + "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==", "dev": true, "funding": [ { @@ -1271,7 +1321,7 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.0.2", + "@csstools/color-helpers": "^5.1.0", "@csstools/css-calc": "^2.1.4" }, "engines": { @@ -1305,6 +1355,29 @@ "@csstools/css-tokenizer": "^3.0.4" } }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.14.tgz", + "integrity": "sha512-zSlIxa20WvMojjpCSy8WrNpcZ61RqfTfX3XTaOeVlGJrt/8HF3YbzgFZa01yTbT4GWQLwfTcC3EB8i3XnB647Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/@csstools/css-tokenizer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", @@ -1373,14 +1446,14 @@ } }, "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz", + "integrity": "sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==", "dev": true, "license": "MIT", "funding": { "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/JounQin" } }, "node_modules/@electron/get": { @@ -1426,29 +1499,21 @@ } }, "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==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", + "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.0.2", + "@emnapi/wasi-threads": "1.1.0", "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", - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", "dev": true, "license": "MIT", "optional": true, @@ -1456,18 +1521,10 @@ "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", - "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "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, @@ -1475,35 +1532,27 @@ "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.52.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.52.0.tgz", - "integrity": "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing==", + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.58.0.tgz", + "integrity": "sha512-smMc5pDht/UVsCD3hhw/a/e/p8m0RdRYiluXToVfd+d4yaQQh7nn9bACjkk6nXJvat7EWPAxuFkMEFfrxeGa3Q==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.8", - "@typescript-eslint/types": "^8.34.1", + "@typescript-eslint/types": "^8.43.0", "comment-parser": "1.4.1", "esquery": "^1.6.0", - "jsdoc-type-pratt-parser": "~4.1.0" + "jsdoc-type-pratt-parser": "~5.4.0" }, "engines": { "node": ">=20.11.0" } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -1554,18 +1603,18 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -1620,9 +1669,9 @@ "license": "MIT" }, "node_modules/@eslint/js": { - "version": "9.30.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.30.0.tgz", - "integrity": "sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww==", + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", + "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1641,52 +1690,40 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", - "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.1", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@fontsource/roboto": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.6.tgz", - "integrity": "sha512-hzarG7yAhMoP418smNgfY4fO7UmuUEm5JUtbxCoCcFHT0hOJB+d/qAEyoNjz7YkPU5OjM2LM8rJnW8hfm0JLaA==", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.8.tgz", + "integrity": "sha512-oh9g4Cg3loVMz9MWeKWfDI+ooxxG1aRVetkiKIb2ESS2rrryGecQ/y4pAj4z5A5ebyw450dYRi/c4k/I3UBhHA==", "license": "OFL-1.1", "funding": { "url": "https://github.com/sponsors/ayuhito" } }, "node_modules/@fontsource/roboto-condensed": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.2.6.tgz", - "integrity": "sha512-xcvHM/urk/hdZknJNBpUzFdAA00QgKq+FdAfjO8soi9xeTlAPNz2wD2k+K7omsCfedGcOlQ6VnWJIRkF0egUjg==", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.2.8.tgz", + "integrity": "sha512-M2OxXXGJQeif+LhxHjWiCEX3BHIYeZf64CcUTeh9AQFGp7DXo2UAXZiZUUOalVdOiuUtQSIi2CDHLDWFiyoECQ==", "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==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-7.0.1.tgz", + "integrity": "sha512-RLmb9U6H2rJDnGxEqXxzy7ANPrQz7WK2/eTjdZqyU9uRU5W+FkAec9uU5gTYzFBH7aoXIw2WTJSCJR4KPlReQw==", "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", "engines": { "node": ">=6" @@ -1702,31 +1739,18 @@ } }, "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" + "@humanwhocodes/retry": "^0.4.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", @@ -1909,17 +1933,17 @@ } }, "node_modules/@jest/console": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.2.tgz", - "integrity": "sha512-krGElPU0FipAqpVZ/BRZOy0MZh/ARdJ0Nj+PiH1ykFY1+VpBlYNLjdjVA5CFKxnKR6PFqFutO4Z7cdK9BlGiDA==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.1.2.tgz", + "integrity": "sha512-BGMAxj8VRmoD0MoA/jo9alMXSRoqW8KPeqOfEo1ncxnRLatTBCpRoOwlwlEMdudp68Q6WSGwYrrLtTGOh8fLzw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.1", + "@jest/types": "30.0.5", "@types/node": "*", "chalk": "^4.1.2", - "jest-message-util": "30.0.2", - "jest-util": "30.0.2", + "jest-message-util": "30.1.0", + "jest-util": "30.0.5", "slash": "^3.0.0" }, "engines": { @@ -1927,39 +1951,39 @@ } }, "node_modules/@jest/core": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.0.3.tgz", - "integrity": "sha512-Mgs1N+NSHD3Fusl7bOq1jyxv1JDAUwjy+0DhVR93Q6xcBP9/bAQ+oZhXb5TTnP5sQzAHgb7ROCKQ2SnovtxYtg==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.1.3.tgz", + "integrity": "sha512-LIQz7NEDDO1+eyOA2ZmkiAyYvZuo6s1UxD/e2IHldR6D7UYogVq3arTmli07MkENLq6/3JEQjp0mA8rrHHJ8KQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.0.2", + "@jest/console": "30.1.2", "@jest/pattern": "30.0.1", - "@jest/reporters": "30.0.2", - "@jest/test-result": "30.0.2", - "@jest/transform": "30.0.2", - "@jest/types": "30.0.1", + "@jest/reporters": "30.1.3", + "@jest/test-result": "30.1.3", + "@jest/transform": "30.1.2", + "@jest/types": "30.0.5", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "ci-info": "^4.2.0", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", - "jest-changed-files": "30.0.2", - "jest-config": "30.0.3", - "jest-haste-map": "30.0.2", - "jest-message-util": "30.0.2", + "jest-changed-files": "30.0.5", + "jest-config": "30.1.3", + "jest-haste-map": "30.1.0", + "jest-message-util": "30.1.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.0.2", - "jest-resolve-dependencies": "30.0.3", - "jest-runner": "30.0.3", - "jest-runtime": "30.0.3", - "jest-snapshot": "30.0.3", - "jest-util": "30.0.2", - "jest-validate": "30.0.2", - "jest-watcher": "30.0.2", + "jest-resolve": "30.1.3", + "jest-resolve-dependencies": "30.1.3", + "jest-runner": "30.1.3", + "jest-runtime": "30.1.3", + "jest-snapshot": "30.1.2", + "jest-util": "30.0.5", + "jest-validate": "30.1.0", + "jest-watcher": "30.1.3", "micromatch": "^4.0.8", - "pretty-format": "30.0.2", + "pretty-format": "30.0.5", "slash": "^3.0.0" }, "engines": { @@ -1985,70 +2009,70 @@ } }, "node_modules/@jest/environment": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.2.tgz", - "integrity": "sha512-hRLhZRJNxBiOhxIKSq2UkrlhMt3/zVFQOAi5lvS8T9I03+kxsbflwHJEF+eXEYXCrRGRhHwECT7CDk6DyngsRA==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.1.2.tgz", + "integrity": "sha512-N8t1Ytw4/mr9uN28OnVf0SYE2dGhaIxOVYcwsf9IInBKjvofAjbFRvedvBBlyTYk2knbJTiEjEJ2PyyDIBnd9w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.0.2", - "@jest/types": "30.0.1", + "@jest/fake-timers": "30.1.2", + "@jest/types": "30.0.5", "@types/node": "*", - "jest-mock": "30.0.2" + "jest-mock": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.3.tgz", - "integrity": "sha512-73BVLqfCeWjYWPEQoYjiRZ4xuQRhQZU0WdgvbyXGRHItKQqg5e6mt2y1kVhzLSuZpmUnccZHbGynoaL7IcLU3A==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.1.2.tgz", + "integrity": "sha512-tyaIExOwQRCxPCGNC05lIjWJztDwk2gPDNSDGg1zitXJJ8dC3++G/CRjE5mb2wQsf89+lsgAgqxxNpDLiCViTA==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.0.3", - "jest-snapshot": "30.0.3" + "expect": "30.1.2", + "jest-snapshot": "30.1.2" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.3.tgz", - "integrity": "sha512-SMtBvf2sfX2agcT0dA9pXwcUrKvOSDqBY4e4iRfT+Hya33XzV35YVg+98YQFErVGA/VR1Gto5Y2+A6G9LSQ3Yg==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.1.2.tgz", + "integrity": "sha512-HXy1qT/bfdjCv7iC336ExbqqYtZvljrV8odNdso7dWK9bSeHtLlvwWWC3YSybSPL03Gg5rug6WLCZAZFH72m0A==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.0.1" + "@jest/get-type": "30.1.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.2.tgz", - "integrity": "sha512-jfx0Xg7l0gmphTY9UKm5RtH12BlLYj/2Plj6wXjVW5Era4FZKfXeIvwC67WX+4q8UCFxYS20IgnMcFBcEU0DtA==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.1.2.tgz", + "integrity": "sha512-Beljfv9AYkr9K+ETX9tvV61rJTY706BhBUtiaepQHeEGfe0DbpvUA5Z3fomwc5Xkhns6NWrcFDZn+72fLieUnA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.1", + "@jest/types": "30.0.5", "@sinonjs/fake-timers": "^13.0.0", "@types/node": "*", - "jest-message-util": "30.0.2", - "jest-mock": "30.0.2", - "jest-util": "30.0.2" + "jest-message-util": "30.1.0", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/get-type": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.1.tgz", - "integrity": "sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==", + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", "dev": true, "license": "MIT", "engines": { @@ -2056,16 +2080,16 @@ } }, "node_modules/@jest/globals": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.3.tgz", - "integrity": "sha512-fIduqNyYpMeeSr5iEAiMn15KxCzvrmxl7X7VwLDRGj7t5CoHtbF+7K3EvKk32mOUIJ4kIvFRlaixClMH2h/Vaw==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.1.2.tgz", + "integrity": "sha512-teNTPZ8yZe3ahbYnvnVRDeOjr+3pu2uiAtNtrEsiMjVPPj+cXd5E/fr8BL7v/T7F31vYdEHrI5cC/2OoO/vM9A==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.0.2", - "@jest/expect": "30.0.3", - "@jest/types": "30.0.1", - "jest-mock": "30.0.2" + "@jest/environment": "30.1.2", + "@jest/expect": "30.1.2", + "@jest/types": "30.0.5", + "jest-mock": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -2086,17 +2110,17 @@ } }, "node_modules/@jest/reporters": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.2.tgz", - "integrity": "sha512-l4QzS/oKf57F8WtPZK+vvF4Io6ukplc6XgNFu4Hd/QxaLEO9f+8dSFzUua62Oe0HKlCUjKHpltKErAgDiMJKsA==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.1.3.tgz", + "integrity": "sha512-VWEQmJWfXMOrzdFEOyGjUEOuVXllgZsoPtEHZzfdNz18RmzJ5nlR6kp8hDdY8dDS1yGOXAY7DHT+AOHIPSBV0w==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.0.2", - "@jest/test-result": "30.0.2", - "@jest/transform": "30.0.2", - "@jest/types": "30.0.1", + "@jest/console": "30.1.2", + "@jest/test-result": "30.1.3", + "@jest/transform": "30.1.2", + "@jest/types": "30.0.5", "@jridgewell/trace-mapping": "^0.3.25", "@types/node": "*", "chalk": "^4.1.2", @@ -2109,9 +2133,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^5.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "30.0.2", - "jest-util": "30.0.2", - "jest-worker": "30.0.2", + "jest-message-util": "30.1.0", + "jest-util": "30.0.5", + "jest-worker": "30.1.0", "slash": "^3.0.0", "string-length": "^4.0.2", "v8-to-istanbul": "^9.0.1" @@ -2129,9 +2153,9 @@ } }, "node_modules/@jest/schemas": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz", - "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==", + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", "dev": true, "license": "MIT", "dependencies": { @@ -2142,13 +2166,13 @@ } }, "node_modules/@jest/snapshot-utils": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.1.tgz", - "integrity": "sha512-6Dpv7vdtoRiISEFwYF8/c7LIvqXD7xDXtLPNzC2xqAfBznKip0MQM+rkseKwUPUpv2PJ7KW/YsnwWXrIL2xF+A==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.1.2.tgz", + "integrity": "sha512-vHoMTpimcPSR7OxS2S0V1Cpg8eKDRxucHjoWl5u4RQcnxqQrV3avETiFpl8etn4dqxEGarBeHbIBety/f8mLXw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.1", + "@jest/types": "30.0.5", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "natural-compare": "^1.4.0" @@ -2173,14 +2197,14 @@ } }, "node_modules/@jest/test-result": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.2.tgz", - "integrity": "sha512-KKMuBKkkZYP/GfHMhI+cH2/P3+taMZS3qnqqiPC1UXZTJskkCS+YU/ILCtw5anw1+YsTulDHFpDo70mmCedW8w==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.1.3.tgz", + "integrity": "sha512-P9IV8T24D43cNRANPPokn7tZh0FAFnYS2HIfi5vK18CjRkTDR9Y3e1BoEcAJnl4ghZZF4Ecda4M/k41QkvurEQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.0.2", - "@jest/types": "30.0.1", + "@jest/console": "30.1.2", + "@jest/types": "30.0.5", "@types/istanbul-lib-coverage": "^2.0.6", "collect-v8-coverage": "^1.0.2" }, @@ -2189,15 +2213,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.2.tgz", - "integrity": "sha512-fbyU5HPka0rkalZ3MXVvq0hwZY8dx3Y6SCqR64zRmh+xXlDeFl0IdL4l9e7vp4gxEXTYHbwLFA1D+WW5CucaSw==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.1.3.tgz", + "integrity": "sha512-82J+hzC0qeQIiiZDThh+YUadvshdBswi5nuyXlEmXzrhw5ZQSRHeQ5LpVMD/xc8B3wPePvs6VMzHnntxL+4E3w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.0.2", + "@jest/test-result": "30.1.3", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.0.2", + "jest-haste-map": "30.1.0", "slash": "^3.0.0" }, "engines": { @@ -2205,23 +2229,23 @@ } }, "node_modules/@jest/transform": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.2.tgz", - "integrity": "sha512-kJIuhLMTxRF7sc0gPzPtCDib/V9KwW3I2U25b+lYCYMVqHHSrcZopS8J8H+znx9yixuFv+Iozl8raLt/4MoxrA==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.1.2.tgz", + "integrity": "sha512-UYYFGifSgfjujf1Cbd3iU/IQoSd6uwsj8XHj5DSDf5ERDcWMdJOPTkHWXj4U+Z/uMagyOQZ6Vne8C4nRIrCxqA==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", - "@jest/types": "30.0.1", + "@jest/types": "30.0.5", "@jridgewell/trace-mapping": "^0.3.25", "babel-plugin-istanbul": "^7.0.0", "chalk": "^4.1.2", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.0.2", + "jest-haste-map": "30.1.0", "jest-regex-util": "30.0.1", - "jest-util": "30.0.2", + "jest-util": "30.0.5", "micromatch": "^4.0.8", "pirates": "^4.0.7", "slash": "^3.0.0", @@ -2232,14 +2256,14 @@ } }, "node_modules/@jest/types": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz", - "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==", + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.5.tgz", + "integrity": "sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.1", + "@jest/schemas": "30.0.5", "@types/istanbul-lib-coverage": "^2.0.6", "@types/istanbul-reports": "^3.0.4", "@types/node": "*", @@ -2251,18 +2275,25 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -2275,27 +2306,17 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "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, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "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==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -2303,27 +2324,37 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@keyv/serialize": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz", - "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==", + "node_modules/@keyv/bigmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.0.2.tgz", + "integrity": "sha512-KR03xkEZlAZNF4IxXgVXb+uNIVNvwdh8UwI0cnc7WI6a+aQcDp8GL80qVfeB4E5NpsKJzou5jU0r6yLSSbMOtA==", "dev": true, "license": "MIT", "dependencies": { - "buffer": "^6.0.3" + "hookified": "^1.12.1" + }, + "engines": { + "node": ">= 18" } }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "dev": true, + "license": "MIT" + }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", - "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.9.0" + "@tybys/wasm-util": "^0.10.0" } }, "node_modules/@nodelib/fs.scandir": { @@ -2376,9 +2407,9 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", - "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, "license": "MIT", "engines": { @@ -2498,6 +2529,18 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, + "node_modules/@pm2/blessed": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/@pm2/blessed/-/blessed-0.1.81.tgz", + "integrity": "sha512-ZcNHqQjMuNRcQ7Z1zJbFIQZO/BDKV3KbiTckWdfbUaYhj7uNmUwb+FbdDWSCkvxNr9dBJQwvV17o6QBkAvgO0g==", + "license": "MIT", + "bin": { + "blessed": "bin/tput.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/@pm2/io": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.1.0.tgz", @@ -2582,6 +2625,12 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, + "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", @@ -2680,9 +2729,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.34.37", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.37.tgz", - "integrity": "sha512-2TRuQVgQYfy+EzHRTIvkhv2ADEouJ2xNS/Vq+W5EuuewBdOrvATvljZTxHWZSTYr2sTjTHpGvucaGAt67S2akw==", + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", + "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", "dev": true, "license": "MIT" }, @@ -2732,28 +2781,6 @@ "@sinonjs/commons": "^3.0.1" } }, - "node_modules/@sinonjs/samsam": { - "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": "^3.0.1", - "lodash.get": "^4.4.2", - "type-detect": "^4.1.0" - } - }, - "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": "MIT", - "engines": { - "node": ">=4" - } - }, "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", @@ -2761,18 +2788,18 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.1.0.tgz", - "integrity": "sha512-TJRJul4u/lmry5N/kyCU+7RWWOk0wyXN+BncRlDYBqpLFnzXkd7QGVfN7KewarFIXv0IX0jSF/Ksu7aHWEDeuw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.4.0.tgz", + "integrity": "sha512-UG8hdElzuBDzIbjG1QDwnYH0MQ73YLXDFHgZzB4Zh/YJfnw8XNsloVtytqzx0I2Qky9THSdpTmi8Vjn/pf/Lew==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/types": "^8.34.1", + "@eslint-community/eslint-utils": "^4.9.0", + "@typescript-eslint/types": "^8.44.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "estraverse": "^5.3.0", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2801,9 +2828,9 @@ "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==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", "dev": true, "license": "MIT", "optional": true, @@ -2811,14 +2838,6 @@ "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", @@ -2855,13 +2874,13 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.20.7" + "@babel/types": "^7.28.2" } }, "node_modules/@types/cacheable-request": { @@ -2967,9 +2986,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.34", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.34.tgz", - "integrity": "sha512-8Y6E5WUupYy1Dd0II32BsWAx5MWdcnRd8L84Oys3veg1YrYtNtzgO4CFhiBg6MDSjk7Ay36HYOnU7/tuOzIzcw==", + "version": "22.18.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.6.tgz", + "integrity": "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -3027,14 +3046,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.0.tgz", - "integrity": "sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz", + "integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.35.0", - "@typescript-eslint/types": "^8.35.0", + "@typescript-eslint/tsconfig-utils": "^8.44.1", + "@typescript-eslint/types": "^8.44.1", "debug": "^4.3.4" }, "engines": { @@ -3045,18 +3064,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz", - "integrity": "sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz", + "integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.35.0", - "@typescript-eslint/visitor-keys": "8.35.0" + "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/visitor-keys": "8.44.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3067,9 +3086,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz", - "integrity": "sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz", + "integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==", "dev": true, "license": "MIT", "engines": { @@ -3080,13 +3099,13 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.0.tgz", - "integrity": "sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz", + "integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==", "dev": true, "license": "MIT", "engines": { @@ -3098,16 +3117,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz", - "integrity": "sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz", + "integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.35.0", - "@typescript-eslint/tsconfig-utils": "8.35.0", - "@typescript-eslint/types": "8.35.0", - "@typescript-eslint/visitor-keys": "8.35.0", + "@typescript-eslint/project-service": "8.44.1", + "@typescript-eslint/tsconfig-utils": "8.44.1", + "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/visitor-keys": "8.44.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3123,7 +3142,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -3153,16 +3172,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.0.tgz", - "integrity": "sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz", + "integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.35.0", - "@typescript-eslint/types": "8.35.0", - "@typescript-eslint/typescript-estree": "8.35.0" + "@typescript-eslint/scope-manager": "8.44.1", + "@typescript-eslint/types": "8.44.1", + "@typescript-eslint/typescript-estree": "8.44.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3173,17 +3192,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz", - "integrity": "sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==", + "version": "8.44.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz", + "integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/types": "8.44.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3202,9 +3221,9 @@ "license": "ISC" }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.2.tgz", - "integrity": "sha512-tS+lqTU3N0kkthU+rYp0spAYq15DU8ld9kXkaKg9sbQqJNF+WPMuNHZQGCgdxrUOEO0j22RKMwRVhF1HTl+X8A==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", "cpu": [ "arm" ], @@ -3216,9 +3235,9 @@ ] }, "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.2.tgz", - "integrity": "sha512-MffGiZULa/KmkNjHeuuflLVqfhqLv1vZLm8lWIyeADvlElJ/GLSOkoUX+5jf4/EGtfwrNFcEaB8BRas03KT0/Q==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", "cpu": [ "arm64" ], @@ -3230,9 +3249,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.2.tgz", - "integrity": "sha512-dzJYK5rohS1sYl1DHdJ3mwfwClJj5BClQnQSyAgEfggbUwA9RlROQSSbKBLqrGfsiC/VyrDPtbO8hh56fnkbsQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", "cpu": [ "arm64" ], @@ -3244,9 +3263,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.2.tgz", - "integrity": "sha512-gaIMWK+CWtXcg9gUyznkdV54LzQ90S3X3dn8zlh+QR5Xy7Y+Efqw4Rs4im61K1juy4YNb67vmJsCDAGOnIeffQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", "cpu": [ "x64" ], @@ -3258,9 +3277,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.2.tgz", - "integrity": "sha512-S7QpkMbVoVJb0xwHFwujnwCAEDe/596xqY603rpi/ioTn9VDgBHnCCxh+UFrr5yxuMH+dliHfjwCZJXOPJGPnw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", "cpu": [ "x64" ], @@ -3272,9 +3291,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.2.tgz", - "integrity": "sha512-+XPUMCuCCI80I46nCDFbGum0ZODP5NWGiwS3Pj8fOgsG5/ctz+/zzuBlq/WmGa+EjWZdue6CF0aWWNv84sE1uw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", "cpu": [ "arm" ], @@ -3286,9 +3305,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.2.tgz", - "integrity": "sha512-sqvUyAd1JUpwbz33Ce2tuTLJKM+ucSsYpPGl2vuFwZnEIg0CmdxiZ01MHQ3j6ExuRqEDUCy8yvkDKvjYFPb8Zg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", "cpu": [ "arm" ], @@ -3300,9 +3319,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.2.tgz", - "integrity": "sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", "cpu": [ "arm64" ], @@ -3314,9 +3333,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.2.tgz", - "integrity": "sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", "cpu": [ "arm64" ], @@ -3328,9 +3347,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.2.tgz", - "integrity": "sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", "cpu": [ "ppc64" ], @@ -3342,9 +3361,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.2.tgz", - "integrity": "sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", "cpu": [ "riscv64" ], @@ -3356,9 +3375,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.2.tgz", - "integrity": "sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", "cpu": [ "riscv64" ], @@ -3370,9 +3389,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.2.tgz", - "integrity": "sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", "cpu": [ "s390x" ], @@ -3384,9 +3403,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.2.tgz", - "integrity": "sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", "cpu": [ "x64" ], @@ -3398,9 +3417,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.2.tgz", - "integrity": "sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", "cpu": [ "x64" ], @@ -3412,9 +3431,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.2.tgz", - "integrity": "sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", "cpu": [ "wasm32" ], @@ -3429,9 +3448,9 @@ } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.2.tgz", - "integrity": "sha512-EdFbGn7o1SxGmN6aZw9wAkehZJetFPao0VGZ9OMBwKx6TkvDuj6cNeLimF/Psi6ts9lMOe+Dt6z19fZQ9Ye2fw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", "cpu": [ "arm64" ], @@ -3443,9 +3462,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.2.tgz", - "integrity": "sha512-JY9hi1p7AG+5c/dMU8o2kWemM8I6VZxfGwn1GCtf3c5i+IKcMo2NQ8OjZ4Z3/itvY/Si3K10jOBQn7qsD/whUA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", "cpu": [ "ia32" ], @@ -3457,9 +3476,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.2.tgz", - "integrity": "sha512-ryoo+EB19lMxAd80ln9BVf8pdOAxLb97amrQ3SFN9OCRn/5M5wvwDgAe4i8ZjhpbiHoDeP8yavcTEnpKBo7lZg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", "cpu": [ "x64" ], @@ -3511,9 +3530,9 @@ } }, "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "license": "MIT", "engines": { "node": ">= 14" @@ -3582,9 +3601,9 @@ } }, "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": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -3731,12 +3750,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", @@ -3762,12 +3775,6 @@ "node": ">= 0.4" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "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", @@ -3783,25 +3790,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/axios": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", - "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/babel-jest": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.2.tgz", - "integrity": "sha512-A5kqR1/EUTidM2YC2YMEUDP2+19ppgOwK0IAd9Swc3q2KqFb5f9PtRUXVeZcngu0z5mDMyZ9zH2huJZSOMLiTQ==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.1.2.tgz", + "integrity": "sha512-IQCus1rt9kaSh7PQxLYRY5NmkNrNlU2TpabzwV7T2jljnpdHOcmnYYv8QmE04Li4S3a2Lj8/yXyET5pBarPr6g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "30.0.2", + "@jest/transform": "30.1.2", "@types/babel__core": "^7.20.5", "babel-plugin-istanbul": "^7.0.0", "babel-preset-jest": "30.0.1", @@ -3817,11 +3813,14 @@ } }, "node_modules/babel-plugin-istanbul": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", - "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", "dev": true, "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -3849,9 +3848,9 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "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==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", "dev": true, "license": "MIT", "dependencies": { @@ -3872,7 +3871,7 @@ "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0 || ^8.0.0-0" } }, "node_modules/babel-preset-jest": { @@ -3898,27 +3897,6 @@ "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", @@ -3928,6 +3906,16 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz", + "integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -3957,6 +3945,16 @@ "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, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -3969,18 +3967,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/blessed": { - "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" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -4013,6 +3999,18 @@ "node": ">=18" } }, + "node_modules/body-parser/node_modules/iconv-lite": { + "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" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -4044,9 +4042,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "version": "4.26.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", + "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", "dev": true, "funding": [ { @@ -4064,9 +4062,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", + "baseline-browser-mapping": "^2.8.3", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, "bin": { @@ -4086,31 +4085,6 @@ "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", @@ -4137,14 +4111,17 @@ } }, "node_modules/cacheable": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.0.tgz", - "integrity": "sha512-SSgQTAnhd7WlJXnGlIi4jJJOiHzgnM5wRMEPaXAU4kECTAMpBoYKoZ9i5zHmclIEZbxcu3j7yY/CF8DTmwIsHg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.0.2.tgz", + "integrity": "sha512-dWjhLx8RWnPsAWVKwW/wI6OJpQ/hSVb1qS0NUif8TR9vRiSwci7Gey8x04kRU9iAF+Rnbtex5Kjjfg/aB5w8Pg==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.8.2", - "keyv": "^5.3.3" + "@cacheable/memoize": "^2.0.2", + "@cacheable/memory": "^2.0.2", + "@cacheable/utils": "^2.0.2", + "hookified": "^1.12.1", + "keyv": "^5.5.2" } }, "node_modules/cacheable-lookup": { @@ -4177,13 +4154,13 @@ } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.4.tgz", - "integrity": "sha512-ypEvQvInNpUe+u+w8BIcPkQvEqXquyyibWE/1NB5T2BTzIpS5cGEV1LZskDzPSTvNAaT4+5FutvzlvnkxOSKlw==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.2.tgz", + "integrity": "sha512-TXcFHbmm/z7MGd1u9ASiCSfTS+ei6Z8B3a5JHzx3oPa/o7QzWVtPRpc4KGER5RR469IC+/nfg4U5YLIuDUua2g==", "dev": true, "license": "MIT", "dependencies": { - "@keyv/serialize": "^1.0.3" + "@keyv/serialize": "^1.1.1" } }, "node_modules/call-bind": { @@ -4253,9 +4230,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001726", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", - "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", + "version": "1.0.30001743", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", + "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", "dev": true, "funding": [ { @@ -4290,9 +4267,9 @@ } }, "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==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.2.tgz", + "integrity": "sha512-2bxTP2yUH7AJj/VAXfcA+4IcWGdQ87HwBANLt5XxGTeomo8yG0y95N1um9i5StvhT/Bl0/2cARA5v1PpPXUxUA==", "dev": true, "license": "MIT", "dependencies": { @@ -4306,9 +4283,9 @@ } }, "node_modules/chalk-template/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "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": { @@ -4411,9 +4388,9 @@ } }, "node_modules/ci-info": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", - "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, "funding": [ { @@ -4502,42 +4479,34 @@ } }, "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.0.tgz", + "integrity": "sha512-7JDGG+4Zp0CsknDCedl0DYdaeOhc46QNpXi3NLQblkZpXXgA6LncLDUUyvrjSvZeF3VRQa+KiMGomazQrC1V8g==", "dev": true, "license": "MIT", "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "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/cli-truncate/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==", + "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": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", + "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4694,22 +4663,10 @@ "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" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", - "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", "dev": true, "license": "MIT", "engines": { @@ -4889,28 +4846,28 @@ } }, "node_modules/cspell": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.1.2.tgz", - "integrity": "sha512-XtFNCt2ZCvdSAbtntlYBumShdDsSbKdgPhwx/PfEL42uhXWR1owQPTxhtHz3nBF2SR11iDI3LDMMGDp8Fw0Gdg==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.2.1.tgz", + "integrity": "sha512-PoKGKE9Tl87Sn/jwO4jvH7nTqe5Xrsz2DeJT5CkulY7SoL2fmsAqfbImQOFS2S0s36qD98t6VO+Ig2elEEcHew==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "9.1.2", - "@cspell/cspell-pipe": "9.1.2", - "@cspell/cspell-types": "9.1.2", - "@cspell/dynamic-import": "9.1.2", - "@cspell/url": "9.1.2", - "chalk": "^5.4.1", + "@cspell/cspell-json-reporter": "9.2.1", + "@cspell/cspell-pipe": "9.2.1", + "@cspell/cspell-types": "9.2.1", + "@cspell/dynamic-import": "9.2.1", + "@cspell/url": "9.2.1", + "chalk": "^5.6.0", "chalk-template": "^1.1.0", "commander": "^14.0.0", - "cspell-config-lib": "9.1.2", - "cspell-dictionary": "9.1.2", - "cspell-gitignore": "9.1.2", - "cspell-glob": "9.1.2", - "cspell-io": "9.1.2", - "cspell-lib": "9.1.2", + "cspell-config-lib": "9.2.1", + "cspell-dictionary": "9.2.1", + "cspell-gitignore": "9.2.1", + "cspell-glob": "9.2.1", + "cspell-io": "9.2.1", + "cspell-lib": "9.2.1", "fast-json-stable-stringify": "^2.1.0", - "file-entry-cache": "^9.1.0", + "flatted": "^3.3.3", "semver": "^7.7.2", "tinyglobby": "^0.2.14" }, @@ -4926,30 +4883,31 @@ } }, "node_modules/cspell-config-lib": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.1.2.tgz", - "integrity": "sha512-QvHHGUuMI5h3ymU6O/Qz8zfhMhvPTuopT1FgebYRBB1cyggl4KnEJKU9m7wy/SQ1IGSlFDtQp6rCy70ujTfavQ==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.2.1.tgz", + "integrity": "sha512-qqhaWW+0Ilc7493lXAlXjziCyeEmQbmPMc1XSJw2EWZmzb+hDvLdFGHoX18QU67yzBtu5hgQsJDEDZKvVDTsRA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.1.2", + "@cspell/cspell-types": "9.2.1", "comment-json": "^4.2.5", - "yaml": "^2.8.0" + "smol-toml": "^1.4.2", + "yaml": "^2.8.1" }, "engines": { "node": ">=20" } }, "node_modules/cspell-dictionary": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.1.2.tgz", - "integrity": "sha512-Osn5f9ugkX/zA3PVtSmYKRer3gZX3YqVB0UH0wVNzi8Ryl/1RUuYLIcvd0SDEhiVW56WKxFLfZ5sggTz/l9cDA==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.2.1.tgz", + "integrity": "sha512-0hQVFySPsoJ0fONmDPwCWGSG6SGj4ERolWdx4t42fzg5zMs+VYGXpQW4BJneQ5Tfxy98Wx8kPhmh/9E8uYzLTw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.1.2", - "@cspell/cspell-types": "9.1.2", - "cspell-trie-lib": "9.1.2", + "@cspell/cspell-pipe": "9.2.1", + "@cspell/cspell-types": "9.2.1", + "cspell-trie-lib": "9.2.1", "fast-equals": "^5.2.2" }, "engines": { @@ -4957,15 +4915,15 @@ } }, "node_modules/cspell-gitignore": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.1.2.tgz", - "integrity": "sha512-dbi7xPYYNT79gci9C3G/tldp13cvhuNXnIOSXJ5lXSDhinZFfrpFc0bOj195nn3HTL/EvlQ9Ga1a1+jOIZNVBQ==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.2.1.tgz", + "integrity": "sha512-WPnDh03gXZoSqVyXq4L7t9ljx6lTDvkiSRUudb125egEK5e9s04csrQpLI3Yxcnc1wQA2nzDr5rX9XQVvCHf7g==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.1.2", - "cspell-glob": "9.1.2", - "cspell-io": "9.1.2" + "@cspell/url": "9.2.1", + "cspell-glob": "9.2.1", + "cspell-io": "9.2.1" }, "bin": { "cspell-gitignore": "bin.mjs" @@ -4975,28 +4933,28 @@ } }, "node_modules/cspell-glob": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.1.2.tgz", - "integrity": "sha512-l7Mqirn5h2tilTXgRamRIqqnzeA7R5iJEtJkY/zHDMEBeLWTR/5ai7dBp2+ooe8gIebpDtvv4938IXa5/75E6g==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.2.1.tgz", + "integrity": "sha512-CrT/6ld3rXhB36yWFjrx1SrMQzwDrGOLr+wYEnrWI719/LTYWWCiMFW7H+qhsJDTsR+ku8+OAmfRNBDXvh9mnQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.1.2", - "picomatch": "^4.0.2" + "@cspell/url": "9.2.1", + "picomatch": "^4.0.3" }, "engines": { "node": ">=20" } }, "node_modules/cspell-grammar": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.1.2.tgz", - "integrity": "sha512-vUcnlUqJKK0yhwYHfGC71zjGyEn918l64U/NWb1ijn1VXrL6gsh3w8Acwdo++zbpOASd9HTAuuZelveDJKLLgA==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.2.1.tgz", + "integrity": "sha512-10RGFG7ZTQPdwyW2vJyfmC1t8813y8QYRlVZ8jRHWzer9NV8QWrGnL83F+gTPXiKR/lqiW8WHmFlXR4/YMV+JQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.1.2", - "@cspell/cspell-types": "9.1.2" + "@cspell/cspell-pipe": "9.2.1", + "@cspell/cspell-types": "9.2.1" }, "bin": { "cspell-grammar": "bin.mjs" @@ -5006,42 +4964,42 @@ } }, "node_modules/cspell-io": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.1.2.tgz", - "integrity": "sha512-oLPxbteI+uFV9ZPcJjII7Lr/C/gVXpdmDLlAMwR8/7LHGnEfxXR0lqYu5GZVEvZ7riX9whCUOsQWQQqr2u2Fzw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.2.1.tgz", + "integrity": "sha512-v9uWXtRzB+RF/Mzg5qMzpb8/yt+1bwtTt2rZftkLDLrx5ybVvy6rhRQK05gFWHmWVtWEe0P/pIxaG2Vz92C8Ag==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "9.1.2", - "@cspell/url": "9.1.2" + "@cspell/cspell-service-bus": "9.2.1", + "@cspell/url": "9.2.1" }, "engines": { "node": ">=20" } }, "node_modules/cspell-lib": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.1.2.tgz", - "integrity": "sha512-OFCssgfp6Z2gd1K8j2FsYr9YGoA/C6xXlcUwgU75Ut/XMZ/S44chdA9fUupGd4dUOw+CZl0qKzSP21J6kYObIw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.2.1.tgz", + "integrity": "sha512-KeB6NHcO0g1knWa7sIuDippC3gian0rC48cvO0B0B0QwhOxNxWVp8cSmkycXjk4ijBZNa++IwFjeK/iEqMdahQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "9.1.2", - "@cspell/cspell-pipe": "9.1.2", - "@cspell/cspell-resolver": "9.1.2", - "@cspell/cspell-types": "9.1.2", - "@cspell/dynamic-import": "9.1.2", - "@cspell/filetypes": "9.1.2", - "@cspell/strong-weak-map": "9.1.2", - "@cspell/url": "9.1.2", + "@cspell/cspell-bundled-dicts": "9.2.1", + "@cspell/cspell-pipe": "9.2.1", + "@cspell/cspell-resolver": "9.2.1", + "@cspell/cspell-types": "9.2.1", + "@cspell/dynamic-import": "9.2.1", + "@cspell/filetypes": "9.2.1", + "@cspell/strong-weak-map": "9.2.1", + "@cspell/url": "9.2.1", "clear-module": "^4.1.2", "comment-json": "^4.2.5", - "cspell-config-lib": "9.1.2", - "cspell-dictionary": "9.1.2", - "cspell-glob": "9.1.2", - "cspell-grammar": "9.1.2", - "cspell-io": "9.1.2", - "cspell-trie-lib": "9.1.2", + "cspell-config-lib": "9.2.1", + "cspell-dictionary": "9.2.1", + "cspell-glob": "9.2.1", + "cspell-grammar": "9.2.1", + "cspell-io": "9.2.1", + "cspell-trie-lib": "9.2.1", "env-paths": "^3.0.0", "fast-equals": "^5.2.2", "gensequence": "^7.0.0", @@ -5056,14 +5014,14 @@ } }, "node_modules/cspell-trie-lib": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.1.2.tgz", - "integrity": "sha512-TkIQaknRRusUznqy+HwpqKCETCAznrzPJJHRHi8m6Zo3tAMsnIpaBQPRN8xem6w8/r/yJqFhLrsLSma0swyviQ==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.2.1.tgz", + "integrity": "sha512-qOtbL+/tUzGFHH0Uq2wi7sdB9iTy66QNx85P7DKeRdX9ZH53uQd7qC4nEk+/JPclx1EgXX26svxr0jTGISJhLw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.1.2", - "@cspell/cspell-types": "9.1.2", + "@cspell/cspell-pipe": "9.2.1", + "@cspell/cspell-types": "9.2.1", "gensequence": "^7.0.0" }, "engines": { @@ -5071,9 +5029,9 @@ } }, "node_modules/cspell/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "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": { @@ -5121,17 +5079,18 @@ } }, "node_modules/cssstyle": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", - "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.1.tgz", + "integrity": "sha512-g5PC9Aiph9eiczFpcgUhd9S4UUO3F+LHGRIi5NUMZ+4xtoIYbHNZwZnWA2JsFGe8OU8nl4WyaEFiZuGuxlutJQ==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^3.2.0", - "rrweb-cssom": "^0.8.0" + "@asamuzakjp/css-color": "^4.0.3", + "@csstools/css-syntax-patches-for-csstree": "^1.0.14", + "css-tree": "^3.1.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/culvert": { @@ -5150,17 +5109,17 @@ } }, "node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.0.tgz", + "integrity": "sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==", "dev": true, "license": "MIT", "dependencies": { "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" + "whatwg-url": "^15.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/data-view-buffer": { @@ -5224,15 +5183,15 @@ } }, "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "version": "1.11.15", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.15.tgz", + "integrity": "sha512-MC+DfnSWiM9APs7fpiurHGCoeIx0Gdl6QZBy+5lu8MbYKN5FZEXqOgrundfibdfhGZ15o9hzmZ2xJjZnbvgKXQ==", "license": "MIT" }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5247,9 +5206,9 @@ } }, "node_modules/decimal.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "dev": true, "license": "MIT" }, @@ -5297,9 +5256,9 @@ } }, "node_modules/dedent": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", - "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5384,15 +5343,6 @@ "node": ">= 14" } }, - "node_modules/delayed-stream": { - "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" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -5413,13 +5363,16 @@ } }, "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==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.2.tgz", + "integrity": "sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==", "dev": true, "license": "MIT", "engines": { "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/detect-newline": { @@ -5571,9 +5524,9 @@ "license": "MIT" }, "node_modules/electron": { - "version": "36.6.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-36.6.0.tgz", - "integrity": "sha512-Tkkw4udDADEWKdbhzckt2CS0gwDTXwZUb2JWxX01HJXAeb8SBlTdQUtxUiAwIIWe0suGuot+uBs1bDPz931A6w==", + "version": "38.1.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-38.1.2.tgz", + "integrity": "sha512-WXUcN3W8h8NTTZViA3KNX0rV2YBU0X0mEUM3ubupXTDY4QtIN7tmiqYVOKSKpR2LckTmBWGuEeY4D6xVoffwKQ==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5590,9 +5543,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.177", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz", - "integrity": "sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==", + "version": "1.5.222", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.222.tgz", + "integrity": "sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==", "dev": true, "license": "ISC" }, @@ -5838,9 +5791,9 @@ } }, "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6034,19 +5987,19 @@ } }, "node_modules/eslint": { - "version": "9.30.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.30.0.tgz", - "integrity": "sha512-iN/SiPxmQu6EVkf+m1qpBxzUhE12YqFLOSySuOyVLJLEF9nzTf+h/1AJYc1JWzCnktggeNrjvQGLngDzXirU6g==", + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", + "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.14.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.30.0", - "@eslint/plugin-kit": "^0.3.1", + "@eslint/js": "9.36.0", + "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -6217,19 +6170,20 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "51.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.2.3.tgz", - "integrity": "sha512-pagzxFubOih+O6XSB1D8BkDkJjF4G4/v8s9pRg4FkXQJLu0e3QJg621ayhmnhyc5mNBpp3cYCNiUyeLQs7oz7w==", + "version": "60.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-60.1.1.tgz", + "integrity": "sha512-eEyINuG4pZtVFplyCPTeUif/+C14zh4fmm5IrDE5YY2Zc3IYKpdGjeaWahJcxWDDwjTVjWCw1zL9XbX3Fb0Wjg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.52.0", + "@es-joy/jsdoccomment": "~0.58.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", - "debug": "^4.4.1", + "debug": "^4.4.3", "escape-string-regexp": "^4.0.0", "espree": "^10.4.0", "esquery": "^1.6.0", + "object-deep-merge": "^1.0.5", "parse-imports-exports": "^0.2.4", "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" @@ -6242,22 +6196,22 @@ } }, "node_modules/eslint-plugin-package-json": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.42.0.tgz", - "integrity": "sha512-aOmIikMFtMC4bPMqf1ZxkV2nwrxp7YaVGWMB8ummKBW7TGeJrvQZ2p5aj7txoxfnLskTfCjn7bPayMKlE7o1Mw==", + "version": "0.56.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.56.3.tgz", + "integrity": "sha512-ArN3wnOAsduM/6a0egB83DQQfF/4KzxE53U8qcvELCXT929TnBy2IeCli4+in3QSHxcVYSIDa2Y5T2vVAXbe6A==", "dev": true, "license": "MIT", "dependencies": { - "@altano/repository-tools": "^1.0.0", + "@altano/repository-tools": "^2.0.1", "change-case": "^5.4.4", - "detect-indent": "7.0.1", - "detect-newline": "4.0.1", - "eslint-fix-utils": "^0.4.0", - "package-json-validator": "~0.16.0", + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.1", + "eslint-fix-utils": "~0.4.0", + "package-json-validator": "~0.30.0", "semver": "^7.5.4", "sort-object-keys": "^1.1.3", - "sort-package-json": "^3.0.0", - "validate-npm-package-name": "^6.0.0" + "sort-package-json": "^3.3.0", + "validate-npm-package-name": "^6.0.2" }, "engines": { "node": "^=20.19.0 || >=22.12.0" @@ -6311,31 +6265,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "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", @@ -6491,18 +6420,18 @@ } }, "node_modules/expect": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.3.tgz", - "integrity": "sha512-HXg6NvK35/cSYZCUKAtmlgCFyqKM4frEPbzrav5hRqb0GMz0E0lS5hfzYjSaiaE5ysnp/qI2aeZkeyeIAOeXzQ==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.1.2.tgz", + "integrity": "sha512-xvHszRavo28ejws8FpemjhwswGj4w/BetHIL8cU49u4sGyXDw2+p3YbeDbj6xzlxi6kWTjIRSTJ+9sNXPnF0Zg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.0.3", - "@jest/get-type": "30.0.1", - "jest-matcher-utils": "30.0.3", - "jest-message-util": "30.0.2", - "jest-mock": "30.0.2", - "jest-util": "30.0.2" + "@jest/expect-utils": "30.1.2", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.1.2", + "jest-message-util": "30.1.0", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -6677,9 +6606,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "funding": [ { "type": "github", @@ -6739,11 +6668,14 @@ } }, "node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -6767,16 +6699,15 @@ } }, "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, + "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": "^5.0.0" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -6825,17 +6756,16 @@ } }, "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, + "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.3.1", + "flatted": "^3.2.9", "keyv": "^4.5.4" }, "engines": { - "node": ">=18" + "node": ">=16" } }, "node_modules/flatted": { @@ -6845,9 +6775,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", @@ -6896,43 +6826,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/form-data": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", - "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "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", @@ -7056,9 +6949,9 @@ } }, "node_modules/get-east-asian-width": { - "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==", + "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==", "dev": true, "license": "MIT", "engines": { @@ -7162,9 +7055,9 @@ } }, "node_modules/get-uri": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", - "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", "license": "MIT", "dependencies": { "basic-ftp": "^5.0.2", @@ -7590,9 +7483,9 @@ } }, "node_modules/hookified": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.10.0.tgz", - "integrity": "sha512-dJw0492Iddsj56U1JsSTm9E/0B/29a1AuoSLRAte8vQg/kaTGF3IgjEWT8c8yG4cC10+HisE1x5QAwR0Xwc+DA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.12.1.tgz", + "integrity": "sha512-xnKGl+iMIlhrZmGHB729MqlmPoWBznctSQTYCpFKqNsCgimJQmithcW0xSQMMFzYnV2iKUh25alswn6epgxS0Q==", "dev": true, "license": "MIT" }, @@ -7763,38 +7656,21 @@ } }, "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "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", @@ -7862,9 +7738,9 @@ } }, "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==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", "dev": true, "license": "MIT", "funding": { @@ -7930,24 +7806,14 @@ "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==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "license": "MIT", - "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==", - "license": "BSD-3-Clause" - }, "node_modules/ip6": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.2.11.tgz", @@ -8174,13 +8040,16 @@ } }, "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", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", "dev": true, "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8541,9 +8410,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8571,16 +8440,16 @@ } }, "node_modules/jest": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.0.3.tgz", - "integrity": "sha512-Uy8xfeE/WpT2ZLGDXQmaYNzw2v8NUKuYeKGtkS6sDxwsdQihdgYCXaKIYnph1h95DN5H35ubFDm0dfmsQnjn4Q==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.1.3.tgz", + "integrity": "sha512-Ry+p2+NLk6u8Agh5yVqELfUJvRfV51hhVBRIB5yZPY7mU0DGBmOuFG5GebZbMbm86cdQNK0fhJuDX8/1YorISQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.0.3", - "@jest/types": "30.0.1", + "@jest/core": "30.1.3", + "@jest/types": "30.0.5", "import-local": "^3.2.0", - "jest-cli": "30.0.3" + "jest-cli": "30.1.3" }, "bin": { "jest": "bin/jest.js" @@ -8598,14 +8467,14 @@ } }, "node_modules/jest-changed-files": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.2.tgz", - "integrity": "sha512-Ius/iRST9FKfJI+I+kpiDh8JuUlAISnRszF9ixZDIqJF17FckH5sOzKC8a0wd0+D+8em5ADRHA5V5MnfeDk2WA==", + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.5.tgz", + "integrity": "sha512-bGl2Ntdx0eAwXuGpdLdVYVr5YQHnSZlQ0y9HVDu565lCUAe9sj6JOtBbMmBBikGIegne9piDDIOeiLVoqTkz4A==", "dev": true, "license": "MIT", "dependencies": { "execa": "^5.1.1", - "jest-util": "30.0.2", + "jest-util": "30.0.5", "p-limit": "^3.1.0" }, "engines": { @@ -8613,29 +8482,29 @@ } }, "node_modules/jest-circus": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.3.tgz", - "integrity": "sha512-rD9qq2V28OASJHJWDRVdhoBdRs6k3u3EmBzDYcyuMby8XCO3Ll1uq9kyqM41ZcC4fMiPulMVh3qMw0cBvDbnyg==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.1.3.tgz", + "integrity": "sha512-Yf3dnhRON2GJT4RYzM89t/EXIWNxKTpWTL9BfF3+geFetWP4XSvJjiU1vrWplOiUkmq8cHLiwuhz+XuUp9DscA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.0.2", - "@jest/expect": "30.0.3", - "@jest/test-result": "30.0.2", - "@jest/types": "30.0.1", + "@jest/environment": "30.1.2", + "@jest/expect": "30.1.2", + "@jest/test-result": "30.1.3", + "@jest/types": "30.0.5", "@types/node": "*", "chalk": "^4.1.2", "co": "^4.6.0", "dedent": "^1.6.0", "is-generator-fn": "^2.1.0", - "jest-each": "30.0.2", - "jest-matcher-utils": "30.0.3", - "jest-message-util": "30.0.2", - "jest-runtime": "30.0.3", - "jest-snapshot": "30.0.3", - "jest-util": "30.0.2", + "jest-each": "30.1.0", + "jest-matcher-utils": "30.1.2", + "jest-message-util": "30.1.0", + "jest-runtime": "30.1.3", + "jest-snapshot": "30.1.2", + "jest-util": "30.0.5", "p-limit": "^3.1.0", - "pretty-format": "30.0.2", + "pretty-format": "30.0.5", "pure-rand": "^7.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" @@ -8645,21 +8514,21 @@ } }, "node_modules/jest-cli": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.0.3.tgz", - "integrity": "sha512-UWDSj0ayhumEAxpYRlqQLrssEi29kdQ+kddP94AuHhZknrE+mT0cR0J+zMHKFe9XPfX3dKQOc2TfWki3WhFTsA==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.1.3.tgz", + "integrity": "sha512-G8E2Ol3OKch1DEeIBl41NP7OiC6LBhfg25Btv+idcusmoUSpqUkbrneMqbW9lVpI/rCKb/uETidb7DNteheuAQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.0.3", - "@jest/test-result": "30.0.2", - "@jest/types": "30.0.1", + "@jest/core": "30.1.3", + "@jest/test-result": "30.1.3", + "@jest/types": "30.0.5", "chalk": "^4.1.2", "exit-x": "^0.2.2", "import-local": "^3.2.0", - "jest-config": "30.0.3", - "jest-util": "30.0.2", - "jest-validate": "30.0.2", + "jest-config": "30.1.3", + "jest-util": "30.0.5", + "jest-validate": "30.1.0", "yargs": "^17.7.2" }, "bin": { @@ -8678,34 +8547,34 @@ } }, "node_modules/jest-config": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.3.tgz", - "integrity": "sha512-j0L4oRCtJwNyZktXIqwzEiDVQXBbQ4dqXuLD/TZdn++hXIcIfZmjHgrViEy5s/+j4HvITmAXbexVZpQ/jnr0bg==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.1.3.tgz", + "integrity": "sha512-M/f7gqdQEPgZNA181Myz+GXCe8jXcJsGjCMXUzRj22FIXsZOyHNte84e0exntOvdPaeh9tA0w+B8qlP2fAezfw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", - "@jest/get-type": "30.0.1", + "@jest/get-type": "30.1.0", "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.0.2", - "@jest/types": "30.0.1", - "babel-jest": "30.0.2", + "@jest/test-sequencer": "30.1.3", + "@jest/types": "30.0.5", + "babel-jest": "30.1.2", "chalk": "^4.1.2", "ci-info": "^4.2.0", "deepmerge": "^4.3.1", "glob": "^10.3.10", "graceful-fs": "^4.2.11", - "jest-circus": "30.0.3", + "jest-circus": "30.1.3", "jest-docblock": "30.0.1", - "jest-environment-node": "30.0.2", + "jest-environment-node": "30.1.2", "jest-regex-util": "30.0.1", - "jest-resolve": "30.0.2", - "jest-runner": "30.0.3", - "jest-util": "30.0.2", - "jest-validate": "30.0.2", + "jest-resolve": "30.1.3", + "jest-runner": "30.1.3", + "jest-util": "30.0.5", + "jest-validate": "30.1.0", "micromatch": "^4.0.8", "parse-json": "^5.2.0", - "pretty-format": "30.0.2", + "pretty-format": "30.0.5", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -8730,16 +8599,16 @@ } }, "node_modules/jest-diff": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.3.tgz", - "integrity": "sha512-Q1TAV0cUcBTic57SVnk/mug0/ASyAqtSIOkr7RAlxx97llRYsM74+E8N5WdGJUlwCKwgxPAkVjKh653h1+HA9A==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.1.2.tgz", + "integrity": "sha512-4+prq+9J61mOVXCa4Qp8ZjavdxzrWQXrI80GNxP8f4tkI2syPuPrJgdRPZRrfUTRvIoUwcmNLbqEJy9W800+NQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/diff-sequences": "30.0.1", - "@jest/get-type": "30.0.1", + "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.0.2" + "pretty-format": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -8769,56 +8638,56 @@ } }, "node_modules/jest-each": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.2.tgz", - "integrity": "sha512-ZFRsTpe5FUWFQ9cWTMguCaiA6kkW5whccPy9JjD1ezxh+mJeqmz8naL8Fl/oSbNJv3rgB0x87WBIkA5CObIUZQ==", + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.1.0.tgz", + "integrity": "sha512-A+9FKzxPluqogNahpCv04UJvcZ9B3HamqpDNWNKDjtxVRYB8xbZLFuCr8JAJFpNp83CA0anGQFlpQna9Me+/tQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.0.1", - "@jest/types": "30.0.1", + "@jest/get-type": "30.1.0", + "@jest/types": "30.0.5", "chalk": "^4.1.2", - "jest-util": "30.0.2", - "pretty-format": "30.0.2" + "jest-util": "30.0.5", + "pretty-format": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-environment-node": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.2.tgz", - "integrity": "sha512-XsGtZ0H+a70RsxAQkKuIh0D3ZlASXdZdhpOSBq9WRPq6lhe0IoQHGW0w9ZUaPiZQ/CpkIdprvlfV1QcXcvIQLQ==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.1.2.tgz", + "integrity": "sha512-w8qBiXtqGWJ9xpJIA98M0EIoq079GOQRQUyse5qg1plShUCQ0Ek1VTTcczqKrn3f24TFAgFtT+4q3aOXvjbsuA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.0.2", - "@jest/fake-timers": "30.0.2", - "@jest/types": "30.0.1", + "@jest/environment": "30.1.2", + "@jest/fake-timers": "30.1.2", + "@jest/types": "30.0.5", "@types/node": "*", - "jest-mock": "30.0.2", - "jest-util": "30.0.2", - "jest-validate": "30.0.2" + "jest-mock": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.1.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-haste-map": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz", - "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==", + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.1.0.tgz", + "integrity": "sha512-JLeM84kNjpRkggcGpQLsV7B8W4LNUWz7oDNVnY1Vjj22b5/fAb3kk3htiD+4Na8bmJmjJR7rBtS2Rmq/NEcADg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.1", + "@jest/types": "30.0.5", "@types/node": "*", "anymatch": "^3.1.3", "fb-watchman": "^2.0.2", "graceful-fs": "^4.2.11", "jest-regex-util": "30.0.1", - "jest-util": "30.0.2", - "jest-worker": "30.0.2", + "jest-util": "30.0.5", + "jest-worker": "30.1.0", "micromatch": "^4.0.8", "walker": "^1.0.8" }, @@ -8830,49 +8699,49 @@ } }, "node_modules/jest-leak-detector": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.2.tgz", - "integrity": "sha512-U66sRrAYdALq+2qtKffBLDWsQ/XoNNs2Lcr83sc9lvE/hEpNafJlq2lXCPUBMNqamMECNxSIekLfe69qg4KMIQ==", + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.1.0.tgz", + "integrity": "sha512-AoFvJzwxK+4KohH60vRuHaqXfWmeBATFZpzpmzNmYTtmRMiyGPVhkXpBqxUQunw+dQB48bDf4NpUs6ivVbRv1g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.0.1", - "pretty-format": "30.0.2" + "@jest/get-type": "30.1.0", + "pretty-format": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.3.tgz", - "integrity": "sha512-hMpVFGFOhYmIIRGJ0HgM9htC5qUiJ00famcc9sRFchJJiLZbbVKrAztcgE6VnXLRxA3XZ0bvNA7hQWh3oHXo/A==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.1.2.tgz", + "integrity": "sha512-7ai16hy4rSbDjvPTuUhuV8nyPBd6EX34HkBsBcBX2lENCuAQ0qKCPb/+lt8OSWUa9WWmGYLy41PrEzkwRwoGZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.0.1", + "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.0.3", - "pretty-format": "30.0.2" + "jest-diff": "30.1.2", + "pretty-format": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-message-util": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz", - "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==", + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.1.0.tgz", + "integrity": "sha512-HizKDGG98cYkWmaLUHChq4iN+oCENohQLb7Z5guBPumYs+/etonmNFlg1Ps6yN9LTPyZn+M+b/9BbnHx3WTMDg==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.0.1", + "@jest/types": "30.0.5", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "micromatch": "^4.0.8", - "pretty-format": "30.0.2", + "pretty-format": "30.0.5", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -8881,15 +8750,15 @@ } }, "node_modules/jest-mock": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz", - "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==", + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.5.tgz", + "integrity": "sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.1", + "@jest/types": "30.0.5", "@types/node": "*", - "jest-util": "30.0.2" + "jest-util": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -8924,18 +8793,18 @@ } }, "node_modules/jest-resolve": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.2.tgz", - "integrity": "sha512-q/XT0XQvRemykZsvRopbG6FQUT6/ra+XV6rPijyjT6D0msOyCvR2A5PlWZLd+fH0U8XWKZfDiAgrUNDNX2BkCw==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.1.3.tgz", + "integrity": "sha512-DI4PtTqzw9GwELFS41sdMK32Ajp3XZQ8iygeDMWkxlRhm7uUTOFSZFVZABFuxr0jvspn8MAYy54NxZCsuCTSOw==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.0.2", + "jest-haste-map": "30.1.0", "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.0.2", - "jest-validate": "30.0.2", + "jest-util": "30.0.5", + "jest-validate": "30.1.0", "slash": "^3.0.0", "unrs-resolver": "^1.7.11" }, @@ -8944,46 +8813,46 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.3.tgz", - "integrity": "sha512-FlL6u7LiHbF0Oe27k7DHYMq2T2aNpPhxnNo75F7lEtu4A6sSw+TKkNNUGNcVckdFoL0RCWREJsC1HsKDwKRZzQ==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.1.3.tgz", + "integrity": "sha512-DNfq3WGmuRyHRHfEet+Zm3QOmVFtIarUOQHHryKPc0YL9ROfgWZxl4+aZq/VAzok2SS3gZdniP+dO4zgo59hBg==", "dev": true, "license": "MIT", "dependencies": { "jest-regex-util": "30.0.1", - "jest-snapshot": "30.0.3" + "jest-snapshot": "30.1.2" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runner": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.3.tgz", - "integrity": "sha512-CxYBzu9WStOBBXAKkLXGoUtNOWsiS1RRmUQb6SsdUdTcqVncOau7m8AJ4cW3Mz+YL1O9pOGPSYLyvl8HBdFmkQ==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.1.3.tgz", + "integrity": "sha512-dd1ORcxQraW44Uz029TtXj85W11yvLpDuIzNOlofrC8GN+SgDlgY4BvyxJiVeuabA1t6idjNbX59jLd2oplOGQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.0.2", - "@jest/environment": "30.0.2", - "@jest/test-result": "30.0.2", - "@jest/transform": "30.0.2", - "@jest/types": "30.0.1", + "@jest/console": "30.1.2", + "@jest/environment": "30.1.2", + "@jest/test-result": "30.1.3", + "@jest/transform": "30.1.2", + "@jest/types": "30.0.5", "@types/node": "*", "chalk": "^4.1.2", "emittery": "^0.13.1", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", "jest-docblock": "30.0.1", - "jest-environment-node": "30.0.2", - "jest-haste-map": "30.0.2", - "jest-leak-detector": "30.0.2", - "jest-message-util": "30.0.2", - "jest-resolve": "30.0.2", - "jest-runtime": "30.0.3", - "jest-util": "30.0.2", - "jest-watcher": "30.0.2", - "jest-worker": "30.0.2", + "jest-environment-node": "30.1.2", + "jest-haste-map": "30.1.0", + "jest-leak-detector": "30.1.0", + "jest-message-util": "30.1.0", + "jest-resolve": "30.1.3", + "jest-runtime": "30.1.3", + "jest-util": "30.0.5", + "jest-watcher": "30.1.3", + "jest-worker": "30.1.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -8992,32 +8861,32 @@ } }, "node_modules/jest-runtime": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.3.tgz", - "integrity": "sha512-Xjosq0C48G9XEQOtmgrjXJwPaUPaq3sPJwHDRaiC+5wi4ZWxO6Lx6jNkizK/0JmTulVNuxP8iYwt77LGnfg3/w==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.1.3.tgz", + "integrity": "sha512-WS8xgjuNSphdIGnleQcJ3AKE4tBKOVP+tKhCD0u+Tb2sBmsU8DxfbBpZX7//+XOz81zVs4eFpJQwBNji2Y07DA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.0.2", - "@jest/fake-timers": "30.0.2", - "@jest/globals": "30.0.3", + "@jest/environment": "30.1.2", + "@jest/fake-timers": "30.1.2", + "@jest/globals": "30.1.2", "@jest/source-map": "30.0.1", - "@jest/test-result": "30.0.2", - "@jest/transform": "30.0.2", - "@jest/types": "30.0.1", + "@jest/test-result": "30.1.3", + "@jest/transform": "30.1.2", + "@jest/types": "30.0.5", "@types/node": "*", "chalk": "^4.1.2", "cjs-module-lexer": "^2.1.0", "collect-v8-coverage": "^1.0.2", "glob": "^10.3.10", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.0.2", - "jest-message-util": "30.0.2", - "jest-mock": "30.0.2", + "jest-haste-map": "30.1.0", + "jest-message-util": "30.1.0", + "jest-mock": "30.0.5", "jest-regex-util": "30.0.1", - "jest-resolve": "30.0.2", - "jest-snapshot": "30.0.3", - "jest-util": "30.0.2", + "jest-resolve": "30.1.3", + "jest-snapshot": "30.1.2", + "jest-util": "30.0.5", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -9026,9 +8895,9 @@ } }, "node_modules/jest-snapshot": { - "version": "30.0.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.3.tgz", - "integrity": "sha512-F05JCohd3OA1N9+5aEPXA6I0qOfZDGIx0zTq5Z4yMBg2i1p5ELfBusjYAWwTkC12c7dHcbyth4QAfQbS7cRjow==", + "version": "30.1.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.1.2.tgz", + "integrity": "sha512-4q4+6+1c8B6Cy5pGgFvjDy/Pa6VYRiGu0yQafKkJ9u6wQx4G5PqI2QR6nxTl43yy7IWsINwz6oT4o6tD12a8Dg==", "dev": true, "license": "MIT", "dependencies": { @@ -9037,20 +8906,20 @@ "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.0.3", - "@jest/get-type": "30.0.1", - "@jest/snapshot-utils": "30.0.1", - "@jest/transform": "30.0.2", - "@jest/types": "30.0.1", + "@jest/expect-utils": "30.1.2", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.1.2", + "@jest/transform": "30.1.2", + "@jest/types": "30.0.5", "babel-preset-current-node-syntax": "^1.1.0", "chalk": "^4.1.2", - "expect": "30.0.3", + "expect": "30.1.2", "graceful-fs": "^4.2.11", - "jest-diff": "30.0.3", - "jest-matcher-utils": "30.0.3", - "jest-message-util": "30.0.2", - "jest-util": "30.0.2", - "pretty-format": "30.0.2", + "jest-diff": "30.1.2", + "jest-matcher-utils": "30.1.2", + "jest-message-util": "30.1.0", + "jest-util": "30.0.5", + "pretty-format": "30.0.5", "semver": "^7.7.2", "synckit": "^0.11.8" }, @@ -9059,13 +8928,13 @@ } }, "node_modules/jest-util": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz", - "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==", + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.5.tgz", + "integrity": "sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.1", + "@jest/types": "30.0.5", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", @@ -9077,18 +8946,18 @@ } }, "node_modules/jest-validate": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.2.tgz", - "integrity": "sha512-noOvul+SFER4RIvNAwGn6nmV2fXqBq67j+hKGHKGFCmK4ks/Iy1FSrqQNBLGKlu4ZZIRL6Kg1U72N1nxuRCrGQ==", + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.1.0.tgz", + "integrity": "sha512-7P3ZlCFW/vhfQ8pE7zW6Oi4EzvuB4sgR72Q1INfW9m0FGo0GADYlPwIkf4CyPq7wq85g+kPMtPOHNAdWHeBOaA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.0.1", - "@jest/types": "30.0.1", + "@jest/get-type": "30.1.0", + "@jest/types": "30.0.5", "camelcase": "^6.3.0", "chalk": "^4.1.2", "leven": "^3.1.0", - "pretty-format": "30.0.2" + "pretty-format": "30.0.5" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -9108,19 +8977,19 @@ } }, "node_modules/jest-watcher": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.2.tgz", - "integrity": "sha512-vYO5+E7jJuF+XmONr6CrbXdlYrgvZqtkn6pdkgjt/dU64UAdc0v1cAVaAeWtAfUUMScxNmnUjKPUMdCpNVASwg==", + "version": "30.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.1.3.tgz", + "integrity": "sha512-6jQUZCP1BTL2gvG9E4YF06Ytq4yMb4If6YoQGRR6PpjtqOXSP3sKe2kqwB6SQ+H9DezOfZaSLnmka1NtGm3fCQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.0.2", - "@jest/types": "30.0.1", + "@jest/test-result": "30.1.3", + "@jest/types": "30.0.5", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "emittery": "^0.13.1", - "jest-util": "30.0.2", + "jest-util": "30.0.5", "string-length": "^4.0.2" }, "engines": { @@ -9128,15 +8997,15 @@ } }, "node_modules/jest-worker": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz", - "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==", + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.1.0.tgz", + "integrity": "sha512-uvWcSjlwAAgIu133Tt77A05H7RIk3Ho8tZL50bQM2AkvLdluw9NG48lRCl3Dt+MOH719n/0nnb5YxUwcuJiKRA==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.0.2", + "jest-util": "30.0.5", "merge-stream": "^2.0.0", "supports-color": "^8.1.1" }, @@ -9191,16 +9060,10 @@ "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==", - "license": "MIT" - }, "node_modules/jsdoc-type-pratt-parser": { - "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==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-5.4.0.tgz", + "integrity": "sha512-F9GQ+F1ZU6qvSrZV8fNFpjDNf614YzR2eF6S0+XbDjAcUI28FSoXnYZFjQmb1kFx3rrJb5PnxUH3/Yti6fcM+g==", "dev": true, "license": "MIT", "engines": { @@ -9208,35 +9071,35 @@ } }, "node_modules/jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", - "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.0.0.tgz", + "integrity": "sha512-lIHeR1qlIRrIN5VMccd8tI2Sgw6ieYXSVktcSHaNe3Z5nE/tcPQYQWOq00wxMvYOsz+73eAkNenVvmPC6bba9A==", "dev": true, "license": "MIT", "dependencies": { - "cssstyle": "^4.2.1", - "data-urls": "^5.0.0", + "@asamuzakjp/dom-selector": "^6.5.4", + "cssstyle": "^5.3.0", + "data-urls": "^6.0.0", "decimal.js": "^10.5.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.16", - "parse5": "^7.2.1", + "parse5": "^7.3.0", "rrweb-cssom": "^0.8.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^5.1.1", + "tough-cookie": "^6.0.0", "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", + "webidl-conversions": "^8.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.1", - "ws": "^8.18.0", + "whatwg-url": "^15.0.0", + "ws": "^8.18.2", "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "peerDependencies": { "canvas": "^3.0.0" @@ -9306,9 +9169,9 @@ } }, "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==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.1.tgz", + "integrity": "sha512-uuPNLJkKN8NXAlZlQ6kmUF9qO+T6Kyd7oV4+/7yy8Jz6+MZNyhPq8EdLpdfnPVzUC8qSf1b4j1azKaGnFsjmsw==", "dev": true, "license": "MIT", "peer": true, @@ -9460,19 +9323,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lilconfig": { - "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": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -9491,22 +9341,19 @@ } }, "node_modules/lint-staged": { - "version": "16.1.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.1.2.tgz", - "integrity": "sha512-sQKw2Si2g9KUZNY3XNvRuDq4UJqpHwF0/FQzZR2M7I5MvtpWvibikCjUVJzZdGE0ByurEl3KQNvsGetd1ty1/Q==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.0.tgz", + "integrity": "sha512-spdYSOCQ2MdZ9CM1/bu/kDmaYGsrpNOeu1InFFV8uhv14x6YIubGxbCpSmGILFoxkiheNQPDXSg5Sbb5ZuVnug==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.4.1", - "commander": "^14.0.0", - "debug": "^4.4.1", - "lilconfig": "^3.1.3", - "listr2": "^8.3.3", - "micromatch": "^4.0.8", - "nano-spawn": "^1.0.2", - "pidtree": "^0.6.0", - "string-argv": "^0.3.2", - "yaml": "^2.8.0" + "commander": "14.0.1", + "listr2": "9.0.4", + "micromatch": "4.0.8", + "nano-spawn": "1.0.3", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.8.1" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -9518,27 +9365,14 @@ "url": "https://opencollective.com/lint-staged" } }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "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/listr2": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", - "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.4.tgz", + "integrity": "sha512-1wd/kpAdKRLwv7/3OKC8zZ5U8e/fajCfWMxacUvB79S5nLrYGPtUI/8chMQhn3LQjsRVErTb9i1ECAwW0ZIHnQ==", "dev": true, "license": "MIT", "dependencies": { - "cli-truncate": "^4.0.0", + "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", @@ -9546,13 +9380,13 @@ "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/listr2/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==", + "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": { @@ -9563,9 +9397,9 @@ } }, "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", "dev": true, "license": "MIT" }, @@ -9588,9 +9422,9 @@ } }, "node_modules/listr2/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==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { @@ -9626,14 +9460,6 @@ "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==", - "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", - "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", @@ -9668,9 +9494,9 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.0.tgz", + "integrity": "sha512-YdhtCd19sKRKfAAUsrcC1wzm4JuzJoiX4pOJqIoW2qmKj5WzG/dL8uUJ0361zaXtHqK7gEhOwtAtz7t3Yq3X5g==", "dev": true, "license": "MIT", "dependencies": { @@ -9684,9 +9510,9 @@ } }, "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", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "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": { @@ -9697,45 +9523,12 @@ } }, "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", "dev": true, "license": "MIT" }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "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" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.0", - "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" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/log-update/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", @@ -9755,9 +9548,9 @@ } }, "node_modules/log-update/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==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { @@ -10701,9 +10494,9 @@ "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==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.3.tgz", + "integrity": "sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA==", "dev": true, "license": "MIT", "engines": { @@ -10733,9 +10526,9 @@ } }, "node_modules/napi-postinstall": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.5.tgz", - "integrity": "sha512-kmsgUvCRIJohHjbZ3V8avP0I1Pekw329MVAMDzVxsrkjgdnqiwvMX5XwR+hWV66vsAtZ+iM+fVnq8RTQawUmCQ==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", + "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", "dev": true, "license": "MIT", "bin": { @@ -10817,27 +10610,16 @@ } }, "node_modules/node-ical": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.20.1.tgz", - "integrity": "sha512-NrXgzDJd6XcyX9kDMJVA3xYCZmntY7ghA2BOdBeYr3iu8tydHOAb+68jPQhF9V2CRQ0/386X05XhmLzQUN0+Hw==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.21.0.tgz", + "integrity": "sha512-69YB4OnngmGJjGKR5PudfiWEDsjFWi6w2dgHsiyDUaFRiR/3uX4VZG0SjkkiaKrvMFcuqwsoUImfRcoLTVr6uQ==", "license": "Apache-2.0", "dependencies": { - "axios": "^1.7.7", - "moment-timezone": "^0.5.45", - "rrule": "2.8.1", - "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" + "moment-timezone": "^0.6.0", + "rrule": "2.8.1" }, "engines": { - "node": "*" + "node": ">=18" } }, "node_modules/node-int64": { @@ -10848,9 +10630,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "dev": true, "license": "MIT" }, @@ -10923,13 +10705,6 @@ "node": ">= 6" } }, - "node_modules/nwsapi": { - "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" - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -10939,6 +10714,29 @@ "node": ">=0.10.0" } }, + "node_modules/object-deep-merge": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-1.0.5.tgz", + "integrity": "sha512-3DioFgOzetbxbeUq8pB2NunXo8V0n4EvqsWM/cJoI6IA9zghd7cl/2pBOuWRf4dlvA+fcg5ugFMZaN2/RuoaGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "4.2.0" + } + }, + "node_modules/object-deep-merge/node_modules/type-fest": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.2.0.tgz", + "integrity": "sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -11141,12 +10939,14 @@ "license": "BlueOak-1.0.0" }, "node_modules/package-json-validator": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.16.1.tgz", - "integrity": "sha512-7f5QUkPiH+wi75CKyOWBRJno35c6r/Zp7A8s+8UBhJgbMAGtq8/JLL9RItAHbrGhfgSs2xmnAQwxtjfb6OYqaw==", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.30.0.tgz", + "integrity": "sha512-gOLW+BBye32t+IB2trIALIcL3DZBy3s4G4ZV6dAgDM+qLs/7jUNOV7iO7PwXqyf+3izI12qHBwtS4kOSJp5Tdg==", "dev": true, "license": "MIT", "dependencies": { + "semver": "^7.7.2", + "validate-npm-package-license": "^3.0.4", "yargs": "~18.0.0" }, "bin": { @@ -11157,9 +10957,9 @@ } }, "node_modules/package-json-validator/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==", + "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": { @@ -11185,9 +10985,9 @@ } }, "node_modules/package-json-validator/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", "dev": true, "license": "MIT" }, @@ -11210,9 +11010,9 @@ } }, "node_modules/package-json-validator/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==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { @@ -11437,12 +11237,13 @@ "license": "ISC" }, "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==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "license": "MIT", - "engines": { - "node": ">=16" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/path-type": { @@ -11482,9 +11283,9 @@ "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==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -11599,13 +11400,13 @@ } }, "node_modules/playwright": { - "version": "1.53.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.1.tgz", - "integrity": "sha512-LJ13YLr/ocweuwxyGf1XNFWIU4M2zUSo149Qbp+A4cpwDjsxRPj7k6H25LBrEHiEwxvRbD8HdwvQmRMSvquhYw==", + "version": "1.55.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.0.tgz", + "integrity": "sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.53.1" + "playwright-core": "1.55.0" }, "bin": { "playwright": "cli.js" @@ -11618,9 +11419,9 @@ } }, "node_modules/playwright-core": { - "version": "1.53.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.1.tgz", - "integrity": "sha512-Z46Oq7tLAyT0lGoFx4DOuB1IA9D1TPj0QkYxpPVUnGDqHHvDpCftu1J2hM2PiWsNMoZh8+LQaarAWcDfPBc6zg==", + "version": "1.55.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.0.tgz", + "integrity": "sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -11646,37 +11447,37 @@ } }, "node_modules/pm2": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.8.tgz", - "integrity": "sha512-y7sO+UuGjfESK/ChRN+efJKAsHrBd95GY2p1GQfjVTtOfFtUfiW0NOuUhP5dN5QTF2F0EWcepgkLqbF32j90Iw==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-6.0.13.tgz", + "integrity": "sha512-1hS/adMgKoDpX4S1ichJW8SiGpex+oBSZK31dP1FSYOOGtaeuemXzhXPOCefmddgIY4K6v7uu+7xNPnmEnK3ag==", "license": "AGPL-3.0", "dependencies": { "@pm2/agent": "~2.1.1", + "@pm2/blessed": "0.1.81", "@pm2/io": "~6.1.0", "@pm2/js-api": "~0.8.0", "@pm2/pm2-version-check": "latest", "ansis": "4.0.0-node10", - "async": "~3.2.6", - "blessed": "0.1.81", - "chokidar": "^3.5.3", - "cli-tableau": "^2.0.0", + "async": "3.2.6", + "chokidar": "3.6.0", + "cli-tableau": "2.0.1", "commander": "2.15.1", - "croner": "~4.1.92", - "dayjs": "~1.11.13", - "debug": "^4.3.7", + "croner": "4.1.97", + "dayjs": "1.11.15", + "debug": "4.4.3", "enquirer": "2.3.6", "eventemitter2": "5.0.1", "fclone": "1.0.11", - "js-yaml": "~4.1.0", + "js-yaml": "4.1.0", "mkdirp": "1.0.4", "needle": "2.4.0", - "pidusage": "~3.0", + "pidusage": "3.0.2", "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.6.2", + "promptly": "2.2.0", + "semver": "7.7.2", "source-map-support": "0.5.21", "sprintf-js": "1.1.2", "vizion": "~2.2.1" @@ -11792,6 +11593,12 @@ "source-map": "^0.6.0" } }, + "node_modules/pm2/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==", + "license": "BSD-3-Clause" + }, "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", @@ -11923,14 +11730,24 @@ "node": ">=6.0.0" } }, + "node_modules/prettier-plugin-jinja-template": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-jinja-template/-/prettier-plugin-jinja-template-2.1.0.tgz", + "integrity": "sha512-mzoCp2Oy9BDSug80fw3B3J4n4KQj1hRvoQOL1akqcDKBb5nvYxrik9zUEDs4AEJ6nK7QDTGoH0y9rx7AlnQ78Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": "^3.0.0" + } + }, "node_modules/pretty-format": { - "version": "30.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz", - "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==", + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.1", + "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", "react-is": "^18.3.1" }, @@ -12136,18 +11953,18 @@ } }, "node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", - "iconv-lite": "0.6.3", + "iconv-lite": "0.7.0", "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.10" } }, "node_modules/react-is": { @@ -12454,12 +12271,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", @@ -12869,34 +12680,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sinon": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-21.0.0.tgz", - "integrity": "sha512-TOgRcwFPbfGtpqvZw+hyqJDvqfapr1qUlOizROIk4bBLjlsjlB00Pg6wMFXNtJRpu+eCZuVOaLatG7M8105kAw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.5", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/diff": { - "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": { - "node": ">=0.3.1" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -12908,26 +12691,26 @@ } }, "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==", + "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.0.0", - "is-fullwidth-code-point": "^4.0.0" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, "node_modules/slice-ansi/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==", + "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": { @@ -12947,6 +12730,19 @@ "npm": ">= 3.0.0" } }, + "node_modules/smol-toml": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.4.2.tgz", + "integrity": "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, "node_modules/socket.io": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", @@ -13104,12 +12900,12 @@ } }, "node_modules/socks": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", - "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -13139,9 +12935,9 @@ "license": "MIT" }, "node_modules/sort-package-json": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.3.1.tgz", - "integrity": "sha512-awjhQR2Iy5UN3NuguAK5+RezcEuUg9Ra4O8y2Aj+DlJa7MywyHaipAPf9bu4qqFj0hsYHHoT9sS3aV7Ucu728g==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.4.0.tgz", + "integrity": "sha512-97oFRRMM2/Js4oEA9LJhjyMlde+2ewpZQf53pgue27UkbEXfHJnDzHlUxQ/DWUkzqmp7DFwJp8D+wi/TYeQhpA==", "dev": true, "license": "MIT", "dependencies": { @@ -13190,6 +12986,28 @@ "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", @@ -13209,17 +13027,18 @@ } }, "node_modules/spdx-license-ids": { - "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==", + "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==", "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==", - "license": "BSD-3-Clause" + "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==", + "license": "BSD-3-Clause", + "optional": true }, "node_modules/stable-hash-x": { "version": "0.2.0", @@ -13481,9 +13300,9 @@ } }, "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": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { @@ -13553,9 +13372,9 @@ } }, "node_modules/stylelint": { - "version": "16.21.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.21.0.tgz", - "integrity": "sha512-ki3PpJGG7xhm3WtINoWGnlvqAmbqSexoRMbEMJzlwewSIOqPRKPlq452c22xAdEJISVi80r+I7KL9GPUiwFgbg==", + "version": "16.24.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.24.0.tgz", + "integrity": "sha512-7ksgz3zJaSbTUGr/ujMXvLVKdDhLbGl3R/3arNudH7z88+XZZGNLMTepsY28WlnvEFcuOmUe7fg40Q3lfhOfSQ==", "dev": true, "funding": [ { @@ -13582,7 +13401,7 @@ "debug": "^4.4.1", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.1.1", + "file-entry-cache": "^10.1.4", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -13596,7 +13415,7 @@ "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", - "postcss": "^8.5.5", + "postcss": "^8.5.6", "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.1.0", @@ -13616,9 +13435,9 @@ } }, "node_modules/stylelint-config-recommended": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-16.0.0.tgz", - "integrity": "sha512-4RSmPjQegF34wNcK1e1O3Uz91HN8P1aFdFzio90wNK9mjgAI19u5vsU868cVZboKzCaa5XbpvtTzAAGQAxpcXA==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-17.0.0.tgz", + "integrity": "sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA==", "dev": true, "funding": [ { @@ -13635,13 +13454,13 @@ "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.16.0" + "stylelint": "^16.23.0" } }, "node_modules/stylelint-config-standard": { - "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==", + "version": "39.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-39.0.0.tgz", + "integrity": "sha512-JabShWORb8Bmc1A47ZyJstran60P3yUdI1zWMpGYPeFiC6xzHXJMkpKAd8EjIhq3HPUplIWWMDJ/xu0AiPd+kA==", "dev": true, "funding": [ { @@ -13655,13 +13474,13 @@ ], "license": "MIT", "dependencies": { - "stylelint-config-recommended": "^16.0.0" + "stylelint-config-recommended": "^17.0.0" }, "engines": { "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.18.0" + "stylelint": "^16.23.0" } }, "node_modules/stylelint-prettier": { @@ -13706,25 +13525,25 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.1.tgz", - "integrity": "sha512-zcmsHjg2B2zjuBgjdnB+9q0+cWcgWfykIcsDkWDB4GTPtl1eXUA+gTI6sO0u01AqK3cliHryTU55/b2Ow1hfZg==", + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.4.tgz", + "integrity": "sha512-5XRUFc0WTtUbjfGzEwXc42tiGxQHBmtbUG1h9L2apu4SulCGN3Hqm//9D6FAolf8MYNL7f/YlJl9vy08pj5JuA==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.10" + "flat-cache": "^6.1.13" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.10", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.10.tgz", - "integrity": "sha512-B6/v1f0NwjxzmeOhzfXPGWpKBVA207LS7lehaVKQnFrVktcFRfkzjZZ2gwj2i1TkEUMQht7ZMJbABUT5N+V1Nw==", + "version": "6.1.14", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.14.tgz", + "integrity": "sha512-ExZSCSV9e7v/Zt7RzCbX57lY2dnPdxzU/h3UE6WJ6NtEMfwBd8jmi1n4otDEUfz+T/R+zxrFDpICFdjhD3H/zw==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.10.0", + "cacheable": "^2.0.1", "flatted": "^3.3.3", - "hookified": "^1.9.1" + "hookified": "^1.12.0" } }, "node_modules/stylelint/node_modules/globby": { @@ -13879,13 +13698,13 @@ "license": "MIT" }, "node_modules/synckit": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", - "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.4" + "@pkgr/core": "^0.2.9" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -13895,9 +13714,9 @@ } }, "node_modules/systeminformation": { - "version": "5.27.7", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.7.tgz", - "integrity": "sha512-saaqOoVEEFaux4v0K8Q7caiauRwjXC4XbD2eH60dxHXbpKxQ8kH9Rf7Jh+nryKpOUSEFxtCdBlSUx0/lO6rwRg==", + "version": "5.27.10", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.10.tgz", + "integrity": "sha512-jkeOerLSwLZqJrPHCYltlKHu0PisdepIuS4GwjFFtgQUG/5AQPVZekkECuULqdP0cgrrIHW8Nl8J7WQXo5ypEg==", "license": "MIT", "os": [ "darwin", @@ -14048,14 +13867,14 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -14065,22 +13884,22 @@ } }, "node_modules/tldts": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", - "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.15.tgz", + "integrity": "sha512-heYRCiGLhtI+U/D0V8YM3QRwPfsLJiP+HX+YwiHZTnWzjIKC+ZCxQRYlzvOoTEc6KIP62B1VeAN63diGCng2hg==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.86" + "tldts-core": "^7.0.15" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", - "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.15.tgz", + "integrity": "sha512-YBkp2VfS9VTRMPNL2PA6PMESmxV1JEVoAr5iBlZnB5JG3KUrWzNCB3yNNkRa2FZkqClaBgfNYCp8PgpYmpjkZw==", "dev": true, "license": "MIT" }, @@ -14113,29 +13932,29 @@ } }, "node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "tldts": "^6.1.32" + "tldts": "^7.0.5" }, "engines": { "node": ">=16" } }, "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/ts-api-utils": { @@ -14152,10 +13971,10 @@ } }, "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", @@ -14309,9 +14128,9 @@ } }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -14362,9 +14181,9 @@ } }, "node_modules/undici": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.11.0.tgz", - "integrity": "sha512-heTSIac3iLhsmZhUCjyS3JQEkZELateufzZuBaVM5RHXdSBMb1LPMQf5x+FH7qjsZYDP0ttAc3nnVpUB+wYbOg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", + "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -14409,38 +14228,38 @@ } }, "node_modules/unrs-resolver": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.2.tgz", - "integrity": "sha512-VUyWiTNQD7itdiMuJy+EuLEErLj3uwX/EpHQF8EOf33Dq3Ju6VW1GXm+swk6+1h7a49uv9fKZ+dft9jU7esdLA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "napi-postinstall": "^0.2.4" + "napi-postinstall": "^0.3.0" }, "funding": { "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.9.2", - "@unrs/resolver-binding-android-arm64": "1.9.2", - "@unrs/resolver-binding-darwin-arm64": "1.9.2", - "@unrs/resolver-binding-darwin-x64": "1.9.2", - "@unrs/resolver-binding-freebsd-x64": "1.9.2", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.9.2", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.9.2", - "@unrs/resolver-binding-linux-arm64-gnu": "1.9.2", - "@unrs/resolver-binding-linux-arm64-musl": "1.9.2", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.9.2", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.9.2", - "@unrs/resolver-binding-linux-riscv64-musl": "1.9.2", - "@unrs/resolver-binding-linux-s390x-gnu": "1.9.2", - "@unrs/resolver-binding-linux-x64-gnu": "1.9.2", - "@unrs/resolver-binding-linux-x64-musl": "1.9.2", - "@unrs/resolver-binding-wasm32-wasi": "1.9.2", - "@unrs/resolver-binding-win32-arm64-msvc": "1.9.2", - "@unrs/resolver-binding-win32-ia32-msvc": "1.9.2", - "@unrs/resolver-binding-win32-x64-msvc": "1.9.2" + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "node_modules/update-browserslist-db": { @@ -14490,19 +14309,6 @@ "dev": true, "license": "MIT" }, - "node_modules/uuid": { - "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" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -14518,10 +14324,32 @@ "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": "6.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.1.tgz", - "integrity": "sha512-OaI//3H0J7ZkR1OqlhGA8cA+Cbk/2xFOQpJOt5+s27/ta9eZwpeervh4Mxh4w0im/kdgktowaqVNR7QOrUd7Yg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.2.tgz", + "integrity": "sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==", "dev": true, "license": "ISC", "engines": { @@ -14611,13 +14439,13 @@ "license": "MIT" }, "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", + "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">=20" } }, "node_modules/whatwg-encoding": { @@ -14633,6 +14461,19 @@ "node": ">=18" } }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", @@ -14644,17 +14485,17 @@ } }, "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/which": { @@ -14865,9 +14706,9 @@ } }, "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", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "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": { @@ -14967,9 +14808,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", - "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 7fe9b545..5ab033c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "magicmirror", - "version": "2.32.0", + "version": "2.33.0", "description": "The open source modular smart mirror platform.", "keywords": [ "magic mirror", @@ -23,16 +23,24 @@ "https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors" ], "type": "commonjs", + "imports": { + "#module_functions": { + "default": "./js/module_functions.js" + }, + "#server_functions": { + "default": "./js/server_functions.js" + } + }, "main": "js/electron.js", "scripts": { "config:check": "node js/check_config.js", + "postinstall": "git clean -df fonts vendor", "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", "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": "git clean -df fonts vendor", "prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed.", "server": "node ./serveronly", "start": "node --run start:x11", @@ -56,63 +64,63 @@ "test:unit": "NODE_ENV=test jest --selectProjects unit" }, "lint-staged": { - "*": "prettier --write", + "*": "prettier --ignore-unknown --write", "*.js": "eslint --fix", "*.css": "stylelint --fix" }, "dependencies": { - "@fontsource/roboto": "^5.2.6", - "@fontsource/roboto-condensed": "^5.2.6", - "@fortawesome/fontawesome-free": "^6.7.2", + "@fontsource/roboto": "^5.2.8", + "@fontsource/roboto-condensed": "^5.2.8", + "@fortawesome/fontawesome-free": "^7.0.1", "ajv": "^8.17.1", "animate.css": "^4.1.1", "console-stamp": "^3.1.2", "croner": "^9.1.0", "envsub": "^4.1.0", - "eslint": "^9.30.0", + "eslint": "^9.36.0", "express": "^5.1.0", "express-ipfilter": "^1.3.2", "feedme": "^2.0.2", "helmet": "^8.1.0", "html-to-text": "^9.0.5", - "iconv-lite": "^0.6.3", + "iconv-lite": "^0.7.0", "module-alias": "^2.2.3", "moment": "^2.30.1", "moment-timezone": "^0.6.0", - "node-ical": "^0.20.1", + "node-ical": "^0.21.0", "nunjucks": "^3.2.4", - "pm2": "^6.0.8", + "pm2": "^6.0.13", "socket.io": "^4.8.1", "suncalc": "^1.9.0", - "systeminformation": "^5.27.7", - "undici": "^7.11.0", + "systeminformation": "^5.27.10", + "undici": "^7.16.0", "weathericons": "^2.1.0" }, "devDependencies": { - "@stylistic/eslint-plugin": "^5.1.0", - "cspell": "^9.1.2", + "@stylistic/eslint-plugin": "^5.4.0", + "cspell": "^9.2.1", "eslint-plugin-import-x": "^4.16.1", "eslint-plugin-jest": "^29.0.1", - "eslint-plugin-jsdoc": "^51.2.3", - "eslint-plugin-package-json": "^0.42.0", + "eslint-plugin-jsdoc": "^60.1.1", + "eslint-plugin-package-json": "^0.56.3", "express-basic-auth": "^1.2.1", "husky": "^9.1.7", - "jest": "^30.0.3", - "jsdom": "^26.1.0", - "lint-staged": "^16.1.2", + "jest": "^30.1.3", + "jsdom": "^27.0.0", + "lint-staged": "^16.2.0", "markdownlint-cli2": "^0.18.1", - "playwright": "^1.53.1", + "playwright": "^1.55.0", "prettier": "^3.6.2", - "sinon": "^21.0.0", - "stylelint": "^16.21.0", - "stylelint-config-standard": "^38.0.0", + "prettier-plugin-jinja-template": "^2.1.0", + "stylelint": "^16.24.0", + "stylelint-config-standard": "^39.0.0", "stylelint-prettier": "^5.0.3" }, "optionalDependencies": { - "electron": "^36.6.0" + "electron": "^38.1.2" }, "engines": { - "node": ">=22.14.0" + "node": ">=22.18.0" }, "_moduleAliases": { "node_helper": "js/node_helper.js", diff --git a/prettier.config.mjs b/prettier.config.mjs index 7ec216b4..4a626332 100644 --- a/prettier.config.mjs +++ b/prettier.config.mjs @@ -1,10 +1,17 @@ const config = { + plugins: ["prettier-plugin-jinja-template"], overrides: [ { files: "*.md", options: { parser: "markdown" } + }, + { + files: ["*.njk"], + options: { + parser: "jinja-template" + } } ], trailingComma: "none" diff --git a/tests/configs/modules/alert/welcome_false.js b/tests/configs/modules/alert/welcome_false.js new file mode 100644 index 00000000..1513904f --- /dev/null +++ b/tests/configs/modules/alert/welcome_false.js @@ -0,0 +1,18 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + modules: [ + { + module: "alert", + config: { + display_time: 1000000, + welcome_message: false + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/alert/welcome_string.js b/tests/configs/modules/alert/welcome_string.js new file mode 100644 index 00000000..6b7b690c --- /dev/null +++ b/tests/configs/modules/alert/welcome_string.js @@ -0,0 +1,18 @@ +let config = { + address: "0.0.0.0", + ipWhitelist: [], + modules: [ + { + module: "alert", + config: { + display_time: 1000000, + welcome_message: "Custom welcome message!" + } + } + ] +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/configs/modules/alert/default.js b/tests/configs/modules/alert/welcome_true.js similarity index 100% rename from tests/configs/modules/alert/default.js rename to tests/configs/modules/alert/welcome_true.js diff --git a/tests/e2e/animateCSS_spec.js b/tests/e2e/animateCSS_spec.js index 7ba34149..f363bc43 100644 --- a/tests/e2e/animateCSS_spec.js +++ b/tests/e2e/animateCSS_spec.js @@ -1,43 +1,79 @@ const helpers = require("./helpers/global-setup"); +// Validate Animate.css integration for compliments module using class toggling. +// We intentionally ignore computed animation styles (jsdom doesn't simulate real animations). describe("AnimateCSS integration Test", () => { - // define config file for testing - 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 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"; + // Config variants under test + const TEST_CONFIG_ANIM = "tests/configs/modules/compliments/compliments_animateCSS.js"; + const TEST_CONFIG_FALLBACK = "tests/configs/modules/compliments/compliments_animateCSS_fallbackToDefault.js"; // invalid animation names + const TEST_CONFIG_INVERTED = "tests/configs/modules/compliments/compliments_animateCSS_invertedAnimationName.js"; // in/out swapped + const TEST_CONFIG_NONE = "tests/configs/modules/compliments/compliments_anytime.js"; // no animations defined /** - * move similar tests in function doTest - * @param {string} [animationIn] animation in name of AnimateCSS to test. - * @param {string} [animationOut] animation out name of AnimateCSS to test. - * @returns {boolean} result + * Get the compliments container element (waits until available). + * @returns {Promise} compliments root element */ - const doTest = async (animationIn, animationOut) => { + async function getComplimentsElement () { await helpers.getDocument(); - let elem = await helpers.waitForElement(".compliments"); - expect(elem).not.toBeNull(); - let styles = window.getComputedStyle(elem); + const el = await helpers.waitForElement(".compliments"); + expect(el).not.toBeNull(); + return el; + } - if (animationIn && animationIn !== "") { - expect(styles._values.get("animation-name")).toBe(animationIn); - } else { - expect(styles._values.get("animation-name")).toBeUndefined(); + /** + * Wait for an Animate.css class to appear and persist briefly. + * @param {string} cls Animation class name without leading dot (e.g. animate__flipInX) + * @param {{timeout?: number}} [options] Poll timeout in ms (default 6000) + * @returns {Promise} true if class detected in time + */ + async function waitForAnimationClass (cls, { timeout = 6000 } = {}) { + const start = Date.now(); + while (Date.now() - start < timeout) { + if (document.querySelector(`.compliments.animate__animated.${cls}`)) { + // small stability wait + await new Promise((r) => setTimeout(r, 50)); + if (document.querySelector(`.compliments.animate__animated.${cls}`)) return true; + } + await new Promise((r) => setTimeout(r, 100)); } + throw new Error(`Timeout waiting for class ${cls}`); + } - if (animationOut && animationOut !== "") { - elem = await helpers.waitForElement(`.compliments.animate__animated.animate__${animationOut}`); - expect(elem).not.toBeNull(); - styles = window.getComputedStyle(elem); - expect(styles._values.get("animation-name")).toBe(animationOut); - } else { - expect(styles._values.get("animation-name")).toBeUndefined(); + /** + * Assert that no Animate.css animation class is applied within a time window. + * @param {number} [ms] Observation period in ms (default 2000) + * @returns {Promise} + */ + async function assertNoAnimationWithin (ms = 2000) { + const start = Date.now(); + while (Date.now() - start < ms) { + if (document.querySelector(".compliments.animate__animated")) { + throw new Error("Unexpected animate__animated class present in non-animation scenario"); + } + await new Promise((r) => setTimeout(r, 100)); + } + } + + /** + * Run one animation test scenario. + * @param {string} [animationIn] Expected animate-in name + * @param {string} [animationOut] Expected animate-out name + * @returns {Promise} true when scenario assertions pass + */ + async function runAnimationTest (animationIn, animationOut) { + await getComplimentsElement(); + if (!animationIn && !animationOut) { + await assertNoAnimationWithin(2000); + return true; + } + if (animationIn) await waitForAnimationClass(`animate__${animationIn}`); + if (animationOut) { + // Wait just beyond one update cycle (updateInterval=2000ms) before expecting animateOut. + await new Promise((r) => setTimeout(r, 2100)); + await waitForAnimationClass(`animate__${animationOut}`); } return true; - }; + } afterEach(async () => { await helpers.stopApplication(); @@ -45,29 +81,29 @@ describe("AnimateCSS integration Test", () => { describe("animateIn and animateOut Test", () => { it("with flipInX and flipOutX animation", async () => { - await helpers.startApplication(testConfigFile); - await expect(doTest("flipInX", "flipOutX")).resolves.toBe(true); + await helpers.startApplication(TEST_CONFIG_ANIM); + await expect(runAnimationTest("flipInX", "flipOutX")).resolves.toBe(true); }); }); describe("use animateOut name for animateIn (vice versa) Test", () => { - it("without animation", async () => { - await helpers.startApplication(testConfigFileInvertedAnimationName); - await expect(doTest()).resolves.toBe(true); + it("without animation (inverted names)", async () => { + await helpers.startApplication(TEST_CONFIG_INVERTED); + await expect(runAnimationTest()).resolves.toBe(true); }); }); describe("false Animation name test", () => { - it("without animation", async () => { - await helpers.startApplication(testConfigFileFallbackToDefault); - await expect(doTest()).resolves.toBe(true); + it("without animation (invalid names)", async () => { + await helpers.startApplication(TEST_CONFIG_FALLBACK); + await expect(runAnimationTest()).resolves.toBe(true); }); }); describe("no Animation defined test", () => { - it("without animation", async () => { - await helpers.startApplication(testConfigByDefault); - await expect(doTest()).resolves.toBe(true); + it("without animation (no config)", async () => { + await helpers.startApplication(TEST_CONFIG_NONE); + await expect(runAnimationTest()).resolves.toBe(true); }); }); }); diff --git a/tests/e2e/fonts_spec.js b/tests/e2e/fonts_spec.js index e09f745a..07ed1a5f 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}/../../css/roboto.css`, "utf8"); + const fileContent = require("node:fs").readFileSync(`${global.root_path}/css/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 c10e0f3c..865a69ff 100644 --- a/tests/e2e/helpers/basic-auth.js +++ b/tests/e2e/helpers/basic-auth.js @@ -13,10 +13,9 @@ app.use(basicAuth); // Set available directories const directories = ["/tests/configs", "/tests/mocks"]; -const rootPath = path.resolve(`${__dirname}/../../../`); for (let directory of directories) { - app.use(directory, express.static(path.resolve(rootPath + directory))); + app.use(directory, express.static(path.resolve(`${global.root_path}/${directory}`))); } let server; diff --git a/tests/e2e/helpers/global-setup.js b/tests/e2e/helpers/global-setup.js index 57d31aa8..67b597ea 100644 --- a/tests/e2e/helpers/global-setup.js +++ b/tests/e2e/helpers/global-setup.js @@ -1,9 +1,13 @@ +const path = require("node:path"); 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`; +// global absolute root path +global.root_path = path.resolve(`${__dirname}/../../../`); + +const indexFile = `${global.root_path}/index.html`; +const cssFile = `${global.root_path}/css/custom.css`; const sampleCss = [ ".region.row3 {", " top: 0;", @@ -29,12 +33,12 @@ exports.startApplication = async (configFilename, exec) => { process.env.mmTestMode = "true"; process.setMaxListeners(0); if (exec) exec; - global.app = require("../../../js/app"); + global.app = require(`${global.root_path}/js/app`); return global.app.start(); }; -exports.stopApplication = async (waitTime = 1000) => { +exports.stopApplication = async (waitTime = 10) => { if (global.window) { // no closing causes jest errors and memory leaks global.window.close(); diff --git a/tests/e2e/helpers/weather-functions.js b/tests/e2e/helpers/weather-functions.js index 9b55f15e..3a3e2d27 100644 --- a/tests/e2e/helpers/weather-functions.js +++ b/tests/e2e/helpers/weather-functions.js @@ -1,4 +1,4 @@ -const { injectMockData } = require("../../utils/weather_mocker"); +const { injectMockData, cleanupMockData } = require("../../utils/weather_mocker"); const helpers = require("./global-setup"); exports.getText = async (element, result) => { @@ -13,7 +13,12 @@ exports.getText = async (element, result) => { return true; }; -exports.startApp = async (configFileName, additionalMockData) => { +exports.startApplication = async (configFileName, additionalMockData) => { await helpers.startApplication(injectMockData(configFileName, additionalMockData)); await helpers.getDocument(); }; + +exports.stopApplication = async () => { + await helpers.stopApplication(); + cleanupMockData(); +}; diff --git a/tests/e2e/modules/alert_spec.js b/tests/e2e/modules/alert_spec.js index f3c95a6c..a8125b8a 100644 --- a/tests/e2e/modules/alert_spec.js +++ b/tests/e2e/modules/alert_spec.js @@ -1,17 +1,52 @@ const helpers = require("../helpers/global-setup"); describe("Alert module", () => { - beforeAll(async () => { - await helpers.startApplication("tests/configs/modules/alert/default.js"); - await helpers.getDocument(); - }); afterAll(async () => { await helpers.stopApplication(); }); - it("should show the welcome message", async () => { - const elem = await helpers.waitForElement(".ns-box .ns-box-inner .light.bright.small"); - expect(elem).not.toBeNull(); - expect(elem.textContent).toContain("Welcome, start was successful!"); + describe("with welcome_message set to false", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/alert/welcome_false.js"); + await helpers.getDocument(); + }); + + it("should not show any welcome message", async () => { + // Wait a bit to ensure no message appears + await new Promise((resolve) => setTimeout(resolve, 1000)); + + // Check that no alert/notification elements are present + const alertElements = document.querySelectorAll(".ns-box .ns-box-inner .light.bright.small"); + expect(alertElements).toHaveLength(0); + }); + }); + + describe("with welcome_message set to true", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/alert/welcome_true.js"); + await helpers.getDocument(); + + // Wait for the application to initialize + await new Promise((resolve) => setTimeout(resolve, 1000)); + }); + + it("should show the translated welcome message", async () => { + const elem = await helpers.waitForElement(".ns-box .ns-box-inner .light.bright.small"); + expect(elem).not.toBeNull(); + expect(elem.textContent).toContain("Welcome, start was successful!"); + }); + }); + + describe("with welcome_message set to custom string", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/modules/alert/welcome_string.js"); + await helpers.getDocument(); + }); + + it("should show the custom welcome message", async () => { + const elem = await helpers.waitForElement(".ns-box .ns-box-inner .light.bright.small"); + expect(elem).not.toBeNull(); + expect(elem.textContent).toContain("Custom welcome message!"); + }); }); }); diff --git a/tests/e2e/modules/calendar_spec.js b/tests/e2e/modules/calendar_spec.js index 03886421..56d2a45a 100644 --- a/tests/e2e/modules/calendar_spec.js +++ b/tests/e2e/modules/calendar_spec.js @@ -42,7 +42,7 @@ describe("Calendar module", () => { }); it("should show the default calendar symbol in each event", async () => { - await expect(testElementLength(".calendar .event .fa-calendar-alt", 0, "not")).resolves.toBe(true); + await expect(testElementLength(".calendar .event .fa-calendar-days", 0, "not")).resolves.toBe(true); }); }); diff --git a/tests/e2e/modules/newsfeed_spec.js b/tests/e2e/modules/newsfeed_spec.js index f93e3ca7..dc317c91 100644 --- a/tests/e2e/modules/newsfeed_spec.js +++ b/tests/e2e/modules/newsfeed_spec.js @@ -83,8 +83,7 @@ describe("Newsfeed module", () => { describe("Newsfeed module located in config directory", () => { beforeAll(() => { - const baseDir = `${__dirname}/../../..`; - fs.cpSync(`${baseDir}/modules/default/newsfeed`, `${baseDir}/config/newsfeed`, { recursive: true }); + fs.cpSync(`${global.root_path}/modules/default/newsfeed`, `${global.root_path}/config/newsfeed`, { recursive: true }); process.env.MM_MODULES_DIR = "config"; }); diff --git a/tests/e2e/modules/weather_current_spec.js b/tests/e2e/modules/weather_current_spec.js index d24ea1b1..78d32784 100644 --- a/tests/e2e/modules/weather_current_spec.js +++ b/tests/e2e/modules/weather_current_spec.js @@ -1,17 +1,15 @@ const helpers = require("../helpers/global-setup"); const weatherFunc = require("../helpers/weather-functions"); -const { cleanupMockData } = require("../../utils/weather_mocker"); describe("Weather module", () => { afterAll(async () => { - await helpers.stopApplication(); - await cleanupMockData(); + await weatherFunc.stopApplication(); }); describe("Current weather", () => { describe("Default configuration", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/currentweather_default.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_default.js", {}); }); it("should render wind speed and wind direction", async () => { @@ -20,12 +18,16 @@ describe("Weather module", () => { it("should render temperature with icon", async () => { await expect(weatherFunc.getText(".weather .large span.light.bright", "1.5°")).resolves.toBe(true); + + const elem = await helpers.waitForElement(".weather .large span.weathericon"); + expect(elem).not.toBeNull(); }); it("should render feels like temperature", async () => { // 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); }); @@ -34,7 +36,7 @@ describe("Weather module", () => { describe("Compliments Integration", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/currentweather_compliments.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_compliments.js", {}); }); it("should render a compliment based on the current weather", async () => { @@ -44,7 +46,7 @@ describe("Weather module", () => { describe("Configuration Options", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/currentweather_options.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_options.js", {}); }); it("should render windUnits in beaufort", async () => { @@ -72,7 +74,7 @@ describe("Weather module", () => { describe("Current weather with imperial units", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/currentweather_units.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_units.js", {}); }); it("should render wind in imperial units", async () => { diff --git a/tests/e2e/modules/weather_forecast_spec.js b/tests/e2e/modules/weather_forecast_spec.js index da4c9188..f9742643 100644 --- a/tests/e2e/modules/weather_forecast_spec.js +++ b/tests/e2e/modules/weather_forecast_spec.js @@ -1,16 +1,14 @@ const helpers = require("../helpers/global-setup"); const weatherFunc = require("../helpers/weather-functions"); -const { cleanupMockData } = require("../../utils/weather_mocker"); describe("Weather module: Weather Forecast", () => { afterAll(async () => { - await helpers.stopApplication(); - await cleanupMockData(); + await weatherFunc.stopApplication(); }); describe("Default configuration", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/forecastweather_default.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_default.js", {}); }); const days = ["Today", "Tomorrow", "Sun", "Mon", "Tue"]; @@ -54,7 +52,7 @@ describe("Weather module: Weather Forecast", () => { describe("Absolute configuration", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/forecastweather_absolute.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_absolute.js", {}); }); const days = ["Fri", "Sat", "Sun", "Mon", "Tue"]; @@ -67,7 +65,7 @@ describe("Weather module: Weather Forecast", () => { describe("Configuration Options", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/forecastweather_options.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_options.js", {}); }); it("should render custom table class", async () => { @@ -94,7 +92,7 @@ describe("Weather module: Weather Forecast", () => { describe("Forecast weather with imperial units", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/forecastweather_units.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_units.js", {}); }); describe("Temperature units", () => { diff --git a/tests/e2e/modules/weather_hourly_spec.js b/tests/e2e/modules/weather_hourly_spec.js index 861ff50f..bce715bc 100644 --- a/tests/e2e/modules/weather_hourly_spec.js +++ b/tests/e2e/modules/weather_hourly_spec.js @@ -1,16 +1,13 @@ -const helpers = require("../helpers/global-setup"); const weatherFunc = require("../helpers/weather-functions"); -const { cleanupMockData } = require("../../utils/weather_mocker"); describe("Weather module: Weather Hourly Forecast", () => { afterAll(async () => { - await helpers.stopApplication(); - await cleanupMockData(); + await weatherFunc.stopApplication(); }); describe("Default configuration", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/hourlyweather_default.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_default.js", {}); }); const minTemps = ["7:00 pm", "8:00 pm", "9:00 pm", "10:00 pm", "11:00 pm"]; @@ -23,7 +20,7 @@ describe("Weather module: Weather Hourly Forecast", () => { describe("Hourly weather options", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/hourlyweather_options.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_options.js", {}); }); describe("Hourly increments of 2", () => { @@ -38,7 +35,7 @@ describe("Weather module: Weather Hourly Forecast", () => { describe("Show precipitations", () => { beforeAll(async () => { - await weatherFunc.startApp("tests/configs/modules/weather/hourlyweather_showPrecipitation.js", {}); + await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_showPrecipitation.js", {}); }); describe("Shows precipitation amount", () => { diff --git a/tests/e2e/serveronly_spec.js b/tests/e2e/serveronly_spec.js index 70db4aaa..be44675d 100644 --- a/tests/e2e/serveronly_spec.js +++ b/tests/e2e/serveronly_spec.js @@ -2,11 +2,17 @@ const delay = (time) => { return new Promise((resolve) => setTimeout(resolve, time)); }; +const runConfigCheck = async () => { + const serverProcess = await require("node:child_process").spawnSync("node", ["--run", "config:check"], { env: process.env }); + expect(serverProcess.stderr.toString()).toBe(""); + return await serverProcess.status; +}; + describe("App environment", () => { let serverProcess; 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 }); + serverProcess = await require("node:child_process").spawn("node", ["--run", "server"], { env: process.env, detached: true }); // we have to wait until the server is started await delay(2000); }); @@ -24,3 +30,15 @@ describe("App environment", () => { expect(res.status).toBe(404); }); }); + +describe("Check config", () => { + it("config check should return without errors", async () => { + process.env.MM_CONFIG_FILE = "tests/configs/default.js"; + await expect(runConfigCheck()).resolves.toBe(0); + }); + + it("config check should fail with non existent config file", async () => { + process.env.MM_CONFIG_FILE = "tests/configs/not_exists.js"; + await expect(runConfigCheck()).resolves.toBe(1); + }); +}); diff --git a/tests/e2e/translations_spec.js b/tests/e2e/translations_spec.js index 2c43e6a1..c8489ace 100644 --- a/tests/e2e/translations_spec.js +++ b/tests/e2e/translations_spec.js @@ -3,9 +3,26 @@ const path = require("node:path"); const helmet = require("helmet"); const { JSDOM } = require("jsdom"); const express = require("express"); -const sinon = require("sinon"); const translations = require("../../translations/translations"); +/** + * Helper function to create a fresh Translator instance with DOM environment. + * @returns {object} Object containing window and Translator + */ +function createTranslationTestEnvironment () { + // Setup DOM environment with Translator + const translatorJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "translator.js"), "utf-8"); + const dom = new JSDOM("", { url: "http://localhost:3000", runScripts: "outside-only" }); + + dom.window.Log = { log: jest.fn(), error: jest.fn() }; + dom.window.translations = translations; + dom.window.eval(translatorJs); + + const window = dom.window; + + return { window, Translator: window.Translator }; +} + describe("translations", () => { let server; @@ -37,91 +54,76 @@ describe("translations", () => { let dom; beforeEach(() => { - // Create a new JSDOM instance for each test - dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" }); + // Create a new translation test environment for each test + const env = createTranslationTestEnvironment(); + const window = env.window; - // 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 + // Load class.js and module.js content directly for loadTranslations tests 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); + window.eval(classJs); + window.eval(moduleJs); + + // Additional setup for loadTranslations tests + window.config = { language: "de" }; + + dom = { window }; }); it("should load translation file", async () => { - await new Promise((resolve) => { - dom.window.onload = resolve; - }); - const { Translator, Module, config } = dom.window; config.language = "en"; - Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); + Translator.load = jest.fn().mockImplementation((_m, _f, _fb) => null); Module.register("name", { getTranslations: () => translations }); const MMM = Module.create("name"); await MMM.loadTranslations(); - expect(Translator.load.args).toHaveLength(1); - expect(Translator.load.calledWith(MMM, "translations/en.json", false)).toBe(true); + expect(Translator.load.mock.calls).toHaveLength(1); + expect(Translator.load).toHaveBeenCalledWith(MMM, "translations/en.json", false); }); it("should load translation + fallback file", async () => { - await new Promise((resolve) => { - dom.window.onload = resolve; - }); - const { Translator, Module } = dom.window; - Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); + Translator.load = jest.fn().mockImplementation((_m, _f, _fb) => null); Module.register("name", { getTranslations: () => translations }); const MMM = Module.create("name"); await MMM.loadTranslations(); - 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); + expect(Translator.load.mock.calls).toHaveLength(2); + expect(Translator.load).toHaveBeenCalledWith(MMM, "translations/de.json", false); + expect(Translator.load).toHaveBeenCalledWith(MMM, "translations/en.json", true); }); it("should load translation fallback file", async () => { - await new Promise((resolve) => { - dom.window.onload = resolve; - }); - const { Translator, Module, config } = dom.window; config.language = "--"; - Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null); + Translator.load = jest.fn().mockImplementation((_m, _f, _fb) => null); Module.register("name", { getTranslations: () => translations }); const MMM = Module.create("name"); await MMM.loadTranslations(); - expect(Translator.load.args).toHaveLength(1); - expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true); + expect(Translator.load.mock.calls).toHaveLength(1); + expect(Translator.load).toHaveBeenCalledWith(MMM, "translations/en.json", true); }); it("should load no file", async () => { - await new Promise((resolve) => { - dom.window.onload = resolve; - }); - const { Translator, Module } = dom.window; - Translator.load = sinon.stub(); + Translator.load = jest.fn(); Module.register("name", {}); const MMM = Module.create("name"); await MMM.loadTranslations(); - expect(Translator.load.callCount).toBe(0); + expect(Translator.load.mock.calls).toHaveLength(0); }); }); @@ -132,21 +134,10 @@ describe("translations", () => { } }; - const translatorJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "translator.js"), "utf-8"); - describe("parsing language files through the Translator class", () => { for (const language in translations) { it(`should parse ${language}`, async () => { - const dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" }); - dom.window.Log = { log: jest.fn() }; - dom.window.translations = translations; - dom.window.eval(translatorJs); - - await new Promise((resolve) => { - dom.window.onload = resolve; - }); - - const { Translator } = dom.window; + const { Translator } = createTranslationTestEnvironment(); await Translator.load(mmm, translations[language], false); expect(typeof Translator.translations[mmm.name]).toBe("object"); @@ -177,19 +168,10 @@ describe("translations", () => { }; // Function to initialize JSDOM and load translations - const initializeTranslationDOM = (language) => { - const dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" }); - dom.window.Log = { log: jest.fn() }; - dom.window.translations = translations; - dom.window.eval(translatorJs); - - return new Promise((resolve) => { - dom.window.onload = async () => { - const { Translator } = dom.window; - await Translator.load(mmm, translations[language], false); - resolve(Translator.translations[mmm.name]); - }; - }); + const initializeTranslationDOM = async (language) => { + const { Translator } = createTranslationTestEnvironment(); + await Translator.load(mmm, translations[language], false); + return Translator.translations[mmm.name]; }; beforeAll(async () => { diff --git a/tests/e2e/vendor_spec.js b/tests/e2e/vendor_spec.js index bd4407ed..5d669287 100644 --- a/tests/e2e/vendor_spec.js +++ b/tests/e2e/vendor_spec.js @@ -9,7 +9,7 @@ describe("Vendors", () => { }); describe("Get list vendors", () => { - const vendors = require(`${__dirname}/../../js/vendor.js`); + const vendors = require(`${global.root_path}/js/vendor.js`); Object.keys(vendors).forEach((vendor) => { it(`should return 200 HTTP code for vendor "${vendor}"`, async () => { diff --git a/tests/electron/modules/weather_spec.js b/tests/electron/modules/weather_spec.js index 40776eaf..fb362f80 100644 --- a/tests/electron/modules/weather_spec.js +++ b/tests/electron/modules/weather_spec.js @@ -2,29 +2,38 @@ 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"; +const SUNSET_DATE = "13 Jan 2019 12:30:00 GMT"; +const SUN_EVENT_SELECTOR = ".weather .normal.medium span:nth-child(4)"; +const EXPECTED_SUNRISE_TEXT = "7:00 am"; +const EXPECTED_SUNSET_TEXT = "3:45 pm"; + describe("Weather module", () => { afterEach(async () => { await helpers.stopApplication(); - await cleanupMockData(); + cleanupMockData(); }); describe("Current weather with sunrise", () => { beforeAll(async () => { - await weatherHelper.startApp("tests/configs/modules/weather/currentweather_default.js", "13 Jan 2019 00:30:00 GMT"); + await weatherHelper.startApp(CURRENT_WEATHER_CONFIG, SUNRISE_DATE); }); it("should render sunrise", async () => { - await expect(weatherHelper.getText(".weather .normal.medium span:nth-child(4)", "7:00 am")).resolves.toBe(true); + const isSunriseRendered = await weatherHelper.getText(SUN_EVENT_SELECTOR, EXPECTED_SUNRISE_TEXT); + expect(isSunriseRendered).toBe(true); }); }); describe("Current weather with sunset", () => { beforeAll(async () => { - await weatherHelper.startApp("tests/configs/modules/weather/currentweather_default.js", "13 Jan 2019 12:30:00 GMT"); + await weatherHelper.startApp(CURRENT_WEATHER_CONFIG, SUNSET_DATE); }); it("should render sunset", async () => { - await expect(weatherHelper.getText(".weather .normal.medium span:nth-child(4)", "3:45 pm")).resolves.toBe(true); + const isSunsetRendered = await weatherHelper.getText(SUN_EVENT_SELECTOR, EXPECTED_SUNSET_TEXT); + expect(isSunsetRendered).toBe(true); }); }); }); diff --git a/tests/unit/classes/translator_spec.js b/tests/unit/classes/translator_spec.js index a84742fe..37cb9990 100644 --- a/tests/unit/classes/translator_spec.js +++ b/tests/unit/classes/translator_spec.js @@ -4,11 +4,23 @@ const helmet = require("helmet"); const { JSDOM } = require("jsdom"); const express = require("express"); +/** + * Helper function to create a fresh Translator instance with DOM environment. + * @returns {object} Object containing window and Translator + */ +function createTranslationTestEnvironment () { + const translatorJs = fs.readFileSync(path.join(__dirname, "..", "..", "..", "js", "translator.js"), "utf-8"); + const dom = new JSDOM("", { url: "http://localhost:3001", runScripts: "outside-only" }); + + dom.window.Log = { log: jest.fn(), error: jest.fn() }; + dom.window.eval(translatorJs); + + return { window: dom.window, Translator: dom.window.Translator }; +} + describe("Translator", () => { let server; const sockets = new Set(); - const translatorJsPath = path.join(__dirname, "..", "..", "..", "js", "translator.js"); - const translatorJsScriptContent = fs.readFileSync(translatorJsPath, "utf8"); const translationTestData = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "..", "..", "tests", "mocks", "translation_test.json"), "utf8")); beforeAll(() => { @@ -20,7 +32,7 @@ describe("Translator", () => { }); app.use("/translations", express.static(path.join(__dirname, "..", "..", "..", "tests", "mocks"))); - server = app.listen(3000); + server = app.listen(3001); server.on("connection", (socket) => { sockets.add(socket); @@ -81,12 +93,7 @@ describe("Translator", () => { }; it("should return custom module translation", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); let translation = Translator.translate({ name: "MMM-Module" }, "Hello"); @@ -97,12 +104,7 @@ describe("Translator", () => { }); it("should return core translation", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); let translation = Translator.translate({ name: "MMM-Module" }, "FOO"); expect(translation).toBe("Foo"); @@ -111,48 +113,28 @@ describe("Translator", () => { }); it("should return custom module translation fallback", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + 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 () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + 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 () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + 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 () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { Translator } = createTranslationTestEnvironment(); setTranslations(Translator); const translation = Translator.translate({ name: "MMM-Module" }, "MISSING"); expect(translation).toBe("MISSING"); @@ -163,17 +145,12 @@ describe("Translator", () => { const mmm = { name: "TranslationTest", file (file) { - return `http://localhost:3000/translations/${file}`; + return `http://localhost:3001/translations/${file}`; } }; it("should load translations", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - dom.window.Log = { log: jest.fn() }; - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { Translator } = createTranslationTestEnvironment(); const file = "translation_test.json"; await Translator.load(mmm, file, false); @@ -182,30 +159,18 @@ describe("Translator", () => { }); it("should load translation fallbacks", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { Translator } = createTranslationTestEnvironment(); const file = "translation_test.json"; - dom.window.Log = { log: jest.fn() }; await Translator.load(mmm, file, true); const json = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "..", "..", "tests", "mocks", file), "utf8")); expect(Translator.translationsFallback[mmm.name]).toEqual(json); }); it("should not load translations, if module fallback exists", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { Translator } = createTranslationTestEnvironment(); const file = "translation_test.json"; - - dom.window.Log = { log: jest.fn() }; Translator.translationsFallback[mmm.name] = { Hello: "Hallo" }; @@ -220,37 +185,23 @@ describe("Translator", () => { describe("loadCoreTranslations", () => { it("should load core translations and fallback", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - dom.window.translations = { en: "http://localhost:3000/translations/translation_test.json" }; - dom.window.Log = { log: jest.fn() }; - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { window, Translator } = createTranslationTestEnvironment(); + window.translations = { en: "http://localhost:3001/translations/translation_test.json" }; await Translator.loadCoreTranslations("en"); const en = translationTestData; - await new Promise((resolve) => setTimeout(resolve, 500)); - expect(Translator.coreTranslations).toEqual(en); expect(Translator.coreTranslationsFallback).toEqual(en); }); it("should load core fallback if language cannot be found", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - dom.window.translations = { en: "http://localhost:3000/translations/translation_test.json" }; - dom.window.Log = { log: jest.fn() }; - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { window, Translator } = createTranslationTestEnvironment(); + window.translations = { en: "http://localhost:3001/translations/translation_test.json" }; await Translator.loadCoreTranslations("MISSINGLANG"); const en = translationTestData; - await new Promise((resolve) => setTimeout(resolve, 500)); - expect(Translator.coreTranslations).toEqual({}); expect(Translator.coreTranslationsFallback).toEqual(en); }); @@ -258,35 +209,20 @@ describe("Translator", () => { describe("loadCoreTranslationsFallback", () => { it("should load core translations fallback", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - dom.window.translations = { en: "http://localhost:3000/translations/translation_test.json" }; - dom.window.Log = { log: jest.fn() }; - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { window, Translator } = createTranslationTestEnvironment(); + window.translations = { en: "http://localhost:3001/translations/translation_test.json" }; await Translator.loadCoreTranslationsFallback(); const en = translationTestData; - await new Promise((resolve) => setTimeout(resolve, 500)); - expect(Translator.coreTranslationsFallback).toEqual(en); }); it("should load core fallback if language cannot be found", async () => { - const dom = new JSDOM("", { runScripts: "outside-only" }); - dom.window.eval(translatorJsScriptContent); - dom.window.translations = {}; - dom.window.Log = { log: jest.fn() }; - - await new Promise((resolve) => dom.window.onload = resolve); - - const { Translator } = dom.window; + const { window, Translator } = createTranslationTestEnvironment(); + window.translations = {}; await Translator.loadCoreTranslations(); - await new Promise((resolve) => setTimeout(resolve, 500)); - expect(Translator.coreTranslationsFallback).toEqual({}); }); }); diff --git a/tests/unit/functions/__snapshots__/updatenotification_spec.js.snap b/tests/unit/functions/__snapshots__/updatenotification_spec.js.snap index adacd250..f3ef9e79 100644 --- a/tests/unit/functions/__snapshots__/updatenotification_spec.js.snap +++ b/tests/unit/functions/__snapshots__/updatenotification_spec.js.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing exports[`Updatenotification custom module returns status information without hash 1`] = ` { diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js index d394d055..b7b6b06f 100644 --- a/tests/unit/functions/server_functions_spec.js +++ b/tests/unit/functions/server_functions_spec.js @@ -1,4 +1,5 @@ -const { cors } = require("../../../js/server_functions"); +const { expect } = require("playwright/test"); +const { cors, getUserAgent } = require("#server_functions"); describe("server_functions tests", () => { describe("The cors method", () => { @@ -142,5 +143,21 @@ describe("server_functions tests", () => { expect(corsResponse.set.mock.calls[2][0]).toBe("header2"); expect(corsResponse.set.mock.calls[2][1]).toBe("value2"); }); + + it("Gets User-Agent from configuration", async () => { + config = {}; + let userAgent; + + userAgent = getUserAgent(); + expect(userAgent).toContain("Mozilla/5.0 (Node.js "); + + config.userAgent = "Mozilla/5.0 (Foo)"; + userAgent = getUserAgent(); + expect(userAgent).toBe("Mozilla/5.0 (Foo)"); + + config.userAgent = () => "Mozilla/5.0 (Bar)"; + userAgent = getUserAgent(); + expect(userAgent).toBe("Mozilla/5.0 (Bar)"); + }); }); }); diff --git a/tests/unit/global_vars/defaults_modules_spec.js b/tests/unit/global_vars/defaults_modules_spec.js index 7fcdf253..465e2232 100644 --- a/tests/unit/global_vars/defaults_modules_spec.js +++ b/tests/unit/global_vars/defaults_modules_spec.js @@ -4,7 +4,7 @@ const path = require("node:path"); const root_path = path.join(__dirname, "../../.."); describe("Default modules set in modules/default/defaultmodules.js", () => { - const expectedDefaultModules = require("../../../modules/default/defaultmodules"); + const expectedDefaultModules = require(`${root_path}/modules/default/defaultmodules`); for (const defaultModule of expectedDefaultModules) { it(`contains a folder for modules/default/${defaultModule}"`, () => { diff --git a/tests/unit/global_vars/root_path_spec.js b/tests/unit/global_vars/root_path_spec.js index 32bcc74b..dcba2bf5 100644 --- a/tests/unit/global_vars/root_path_spec.js +++ b/tests/unit/global_vars/root_path_spec.js @@ -2,7 +2,7 @@ const fs = require("node:fs"); const path = require("node:path"); const root_path = path.join(__dirname, "../../.."); -const version = require(`${__dirname}/../../../package.json`).version; +const version = require(`${root_path}/package.json`).version; describe("'global.root_path' set in js/app.js", () => { const expectedSubPaths = ["modules", "serveronly", "js", "js/app.js", "js/main.js", "js/electron.js", "config"]; 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 db886180..fe3e1261 100644 --- a/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js +++ b/tests/unit/modules/default/calendar/calendar_fetcher_utils_spec.js @@ -10,7 +10,7 @@ describe("Calendar fetcher utils test", () => { excludedEvents: [], includePastEvents: false, maximumEntries: 10, - maximumNumberOfDays: 365 + maximumNumberOfDays: 367 }; describe("filterEvents", () => { diff --git a/tests/unit/modules/default/weather/weather_utils_spec.js b/tests/unit/modules/default/weather/weather_utils_spec.js index 979fba2f..da3979cd 100644 --- a/tests/unit/modules/default/weather/weather_utils_spec.js +++ b/tests/unit/modules/default/weather/weather_utils_spec.js @@ -2,10 +2,18 @@ const weather = require("../../../../../modules/default/weather/weatherutils"); const WeatherUtils = require("../../../../../modules/default/weather/weatherutils"); describe("Weather utils tests", () => { - describe("windspeed conversion to imperial", () => { + describe("temperature conversion to imperial", () => { + it("should convert temp correctly from Celsius to Celsius", () => { + expect(Math.round(WeatherUtils.convertTemp(10, "metric"))).toBe(10); + }); + it("should convert temp correctly from Celsius to Fahrenheit", () => { expect(Math.round(WeatherUtils.convertTemp(10, "imperial"))).toBe(50); }); + + it("should convert temp correctly from Fahrenheit to Celsius", () => { + expect(Math.round(WeatherUtils.convertTempToMetric(10))).toBe(-12); + }); }); describe("windspeed conversion to beaufort", () => { @@ -44,11 +52,11 @@ describe("Weather utils tests", () => { describe("feelsLike calculation", () => { it("should return a calculated feelsLike info (negative value)", () => { - expect(WeatherUtils.calculateFeelsLike(0, 20, 40)).toBe(-9.444444444444445); + expect(WeatherUtils.calculateFeelsLike(0, 20, 40)).toBe(-9.397005931555448); }); it("should return a calculated feelsLike info (positive value)", () => { - expect(WeatherUtils.calculateFeelsLike(30, 0, 60)).toBe(32.8320322777777); + expect(WeatherUtils.calculateFeelsLike(30, 0, 60)).toBe(32.832032277777756); }); }); diff --git a/tests/utils/weather_mocker.js b/tests/utils/weather_mocker.js index 70d56e68..c0ebbba1 100644 --- a/tests/utils/weather_mocker.js +++ b/tests/utils/weather_mocker.js @@ -1,7 +1,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 exec = require("node:child_process").execSync; /** * @param {string} type what data to read, can be "current" "forecast" or "hourly @@ -45,9 +44,9 @@ const injectMockData = (configFileName, extendedData = {}) => { return tempFile; }; -const cleanupMockData = async () => { +const cleanupMockData = () => { const tempDir = path.resolve(`${__dirname}/../configs`).toString(); - await exec(`find ${tempDir} -type f -name *_temp.js -delete`); + exec(`find ${tempDir} -type f -name *_temp.js -delete`); }; module.exports = { injectMockData, cleanupMockData };