From 976c8ae00a63ae148f6610da13f62ef93e693ba0 Mon Sep 17 00:00:00 2001 From: Veeck Date: Mon, 12 Aug 2024 22:52:43 +0200 Subject: [PATCH] Bump stylistic-eslint (#3520) updates plugin and adjust docs and config for smooth cleaning :-D --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .eslintrc.json | 1 + CHANGELOG.md | 2 +- js/class.js | 21 +- js/electron.js | 50 +- js/module.js | 29 +- js/node_helper.js | 9 +- modules/default/calendar/calendar.js | 31 +- modules/default/calendar/debug.js | 3 +- modules/default/defaultmodules.js | 3 +- .../updatenotification/update_helper.js | 19 +- .../default/weather/providers/envcanada.js | 342 ++++++-------- .../default/weather/providers/openmeteo.js | 10 +- .../weather/providers/openweathermap.js | 46 +- .../weather/providers/pirateweather.js | 10 +- modules/default/weather/providers/smhi.js | 11 +- .../default/weather/providers/ukmetoffice.js | 39 +- .../weather/providers/ukmetofficedatahub.js | 53 ++- .../default/weather/providers/weatherbit.js | 10 +- .../default/weather/providers/weatherflow.js | 10 +- .../default/weather/providers/weathergov.js | 38 +- modules/default/weather/providers/yr.js | 17 +- package-lock.json | 430 ++++++++++-------- package.json | 12 +- .../calendar/exdate_la_at_midnight_dst.js | 3 +- .../calendar/exdate_la_at_midnight_std.js | 3 +- .../calendar/exdate_la_before_midnight.js | 3 +- .../calendar/exdate_syd_at_midnight_dst.js | 3 +- .../calendar/exdate_syd_at_midnight_std.js | 3 +- .../calendar/exdate_syd_before_midnight.js | 3 +- .../modules/calendar/long-fullday-event.js | 3 +- .../modules/calendar/single-fullday-event.js | 3 +- tests/electron/modules/calendar_spec.js | 45 +- 32 files changed, 700 insertions(+), 565 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index dccd2ee2..629c0082 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -49,6 +49,7 @@ "@stylistic/function-paren-newline": ["error", "consistent"], "@stylistic/implicit-arrow-linebreak": ["error", "beside"], "@stylistic/max-statements-per-line": ["error", { "max": 2 }], + "@stylistic/multiline-comment-style": "off", "@stylistic/multiline-ternary": ["error", "always-multiline"], "@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 4 }], "@stylistic/no-extra-parens": "off", diff --git a/CHANGELOG.md b/CHANGELOG.md index b14684ab..a41be65c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ _This release is scheduled to be released on 2024-10-01._ ### Updated - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) -- [core] Updated dependencies +- [core] Updated dependencies including stylistic-eslint - [core] Allow custom module positions by setting `allowCustomModulePositions` in `config.js` (fixes #3504, related to https://github.com/MagicMirrorOrg/MagicMirror/pull/3445) ### Fixed diff --git a/js/class.js b/js/class.js index c3a0ab22..9cfeee4c 100644 --- a/js/class.js +++ b/js/class.js @@ -1,6 +1,7 @@ /* global Class, xyz */ -/* Simple JavaScript Inheritance +/* + * Simple JavaScript Inheritance * By John Resig https://johnresig.com/ * * Inspired by base2 and Prototype @@ -22,8 +23,10 @@ Class.extend = function (prop) { let _super = this.prototype; - // Instantiate a base class (but only create the instance, - // don't run the init constructor) + /* + * Instantiate a base class (but only create the instance, + * don't run the init constructor) + */ initializing = true; const prototype = new this(); initializing = false; @@ -42,12 +45,16 @@ return function () { const tmp = this._super; - // Add a new ._super() method that is the same method - // but on the super-class + /* + * Add a new ._super() method that is the same method + * but on the super-class + */ this._super = _super[name]; - // The method only need to be bound temporarily, so we - // remove it when we're done executing + /* + * The method only need to be bound temporarily, so we + * remove it when we're done executing + */ const ret = fn.apply(this, arguments); this._super = tmp; diff --git a/js/electron.js b/js/electron.js index 2dfde672..4bfe3542 100644 --- a/js/electron.js +++ b/js/electron.js @@ -8,9 +8,12 @@ const Log = require("./logger"); let config = process.env.config ? JSON.parse(process.env.config) : {}; // Module to control application life. const app = electron.app; -// Per default electron is started with --disable-gpu flag, if you want the gpu enabled, -// you must set the env var ELECTRON_ENABLE_GPU=1 on startup. -// See https://www.electronjs.org/docs/latest/tutorial/offscreen-rendering for more info. + +/* + * Per default electron is started with --disable-gpu flag, if you want the gpu enabled, + * you must set the env var ELECTRON_ENABLE_GPU=1 on startup. + * See https://www.electronjs.org/docs/latest/tutorial/offscreen-rendering for more info. + */ if (process.env.ELECTRON_ENABLE_GPU !== "1") { app.disableHardwareAcceleration(); } @@ -18,16 +21,21 @@ if (process.env.ELECTRON_ENABLE_GPU !== "1") { // Module to create native browser window. const BrowserWindow = electron.BrowserWindow; -// Keep a global reference of the window object, if you don't, the window will -// be closed automatically when the JavaScript object is garbage collected. +/* + * Keep a global reference of the window object, if you don't, the window will + * be closed automatically when the JavaScript object is garbage collected. + */ let mainWindow; /** * */ function createWindow () { - // see https://www.electronjs.org/docs/latest/api/screen - // Create a window that fills the screen's available work area. + + /* + * see https://www.electronjs.org/docs/latest/api/screen + * Create a window that fills the screen's available work area. + */ let electronSize = (800, 600); try { electronSize = electron.screen.getPrimaryDisplay().workAreaSize; @@ -52,8 +60,10 @@ function createWindow () { backgroundColor: "#000000" }; - // DEPRECATED: "kioskmode" backwards compatibility, to be removed - // settings these options directly instead provides cleaner interface + /* + * DEPRECATED: "kioskmode" backwards compatibility, to be removed + * settings these options directly instead provides cleaner interface + */ if (config.kioskmode) { electronOptionsDefaults.kiosk = true; } else { @@ -69,8 +79,10 @@ function createWindow () { // Create the browser window. mainWindow = new BrowserWindow(electronOptions); - // and load the index.html of the app. - // If config.address is not defined or is an empty string (listening on all interfaces), connect to localhost + /* + * and load the index.html of the app. + * If config.address is not defined or is an empty string (listening on all interfaces), connect to localhost + */ let prefix; if ((config["tls"] !== null && config["tls"]) || config.useHttps) { @@ -149,14 +161,18 @@ app.on("window-all-closed", function () { }); app.on("activate", function () { - // On OS X it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. + + /* + * On OS X it's common to re-create a window in the app when the + * dock icon is clicked and there are no other windows open. + */ if (mainWindow === null) { createWindow(); } }); -/* This method will be called when SIGINT is received and will call +/* + * This method will be called when SIGINT is received and will call * each node_helper's stop function if it exists. Added to fix #1056 * * Note: this is only used if running Electron. Otherwise @@ -187,8 +203,10 @@ if (process.env.clientonly) { }); } -// Start the core application if server is run on localhost -// This starts all node helpers and starts the webserver. +/* + * Start the core application if server is run on localhost + * This starts all node helpers and starts the webserver. + */ if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].includes(config.address)) { core.start().then((c) => { config = c; diff --git a/js/module.js b/js/module.js index 71451763..3fc2cf30 100644 --- a/js/module.js +++ b/js/module.js @@ -1,13 +1,16 @@ /* global Class, cloneObject, Loader, MMSocket, nunjucks, Translator */ -/* Module Blueprint. +/* + * Module Blueprint. * @typedef {Object} Module */ const Module = Class.extend({ - /********************************************************* + /** + ******************************************************** * All methods (and properties) below can be subclassed. * - *********************************************************/ + ******************************************************** + */ // Set the minimum MagicMirror² module version for this module. requiresVersion: "2.0.0", @@ -18,13 +21,17 @@ const Module = Class.extend({ // Timer reference used for showHide animation callbacks. showHideTimer: null, - // Array to store lockStrings. These strings are used to lock - // visibility when hiding and showing module. + /* + * Array to store lockStrings. These strings are used to lock + * visibility when hiding and showing module. + */ lockStrings: [], - // Storage of the nunjucks Environment, - // This should not be referenced directly. - // Use the nunjucksEnvironment() to get it. + /* + * Storage of the nunjucks Environment, + * This should not be referenced directly. + * Use the nunjucksEnvironment() to get it. + */ _nunjucksEnvironment: null, /** @@ -189,9 +196,11 @@ const Module = Class.extend({ Log.log(`${this.name} is resumed.`); }, - /********************************************* + /** + ******************************************** * The methods below don't need subclassing. * - *********************************************/ + ******************************************** + */ /** * Set the module data. diff --git a/js/node_helper.js b/js/node_helper.js index 42da0efc..dd272c4e 100644 --- a/js/node_helper.js +++ b/js/node_helper.js @@ -49,7 +49,8 @@ const NodeHelper = Class.extend({ this.path = path; }, - /* sendSocketNotification(notification, payload) + /* + * sendSocketNotification(notification, payload) * Send a socket notification to the node helper. * * argument notification string - The identifier of the notification. @@ -59,7 +60,8 @@ const NodeHelper = Class.extend({ this.io.of(this.name).emit(notification, payload); }, - /* setExpressApp(app) + /* + * setExpressApp(app) * Sets the express app object for this module. * This allows you to host files from the created webserver. * @@ -71,7 +73,8 @@ const NodeHelper = Class.extend({ app.use(`/${this.name}`, express.static(`${this.path}/public`)); }, - /* setSocketIO(io) + /* + * setSocketIO(io) * Sets the socket io object for this module. * Binds message receiver. * diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index 4b0409c0..31ad4f5e 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -82,9 +82,12 @@ Module.register("calendar", { // Define required translations. getTranslations () { - // The translations for the default modules are defined in the core translation files. - // Therefore we can just return false. Otherwise we should have returned a dictionary. - // If you're trying to build your own module including translations, check out the documentation. + + /* + * The translations for the default modules are defined in the core translation files. + * Therefore we can just return false. Otherwise we should have returned a dictionary. + * If you're trying to build your own module including translations, check out the documentation. + */ return false; }, @@ -148,8 +151,10 @@ Module.register("calendar", { }; } - // tell helper to start a fetcher for this calendar - // fetcher till cycle + /* + * tell helper to start a fetcher for this calendar + * fetcher till cycle + */ this.addCalendar(calendar.url, calendar.auth, calendarConfig); }); @@ -627,7 +632,8 @@ Module.register("calendar", { event.tomorrow = !event.today && event.startDate >= today + ONE_DAY && event.startDate < today + 2 * ONE_DAY; event.dayAfterTomorrow = !event.tomorrow && event.startDate >= today + ONE_DAY * 2 && event.startDate < today + 3 * ONE_DAY; - /* if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days, + /* + * if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days, * otherwise, esp. in dateheaders mode it is not clear how long these events are. */ const maxCount = Math.ceil((event.endDate - 1 - moment(event.startDate, "x").endOf("day").format("x")) / ONE_DAY) + 1; @@ -677,16 +683,21 @@ Module.register("calendar", { return events; } - // Limit the number of days displayed - // If limitDays is set > 0, limit display to that number of days + /* + * Limit the number of days displayed + * If limitDays is set > 0, limit display to that number of days + */ if (this.config.limitDays > 0) { let newEvents = []; let lastDate = today.clone().subtract(1, "days").format("YYYYMMDD"); let days = 0; for (const ev of events) { let eventDate = moment(ev.startDate, "x").format("YYYYMMDD"); - // if date of event is later than lastdate - // check if we already are showing max unique days + + /* + * if date of event is later than lastdate + * check if we already are showing max unique days + */ if (eventDate > lastDate) { // if the only entry in the first day is a full day event that day is not counted as unique if (!this.config.limitDaysNeverSkip && newEvents.length === 1 && days === 1 && newEvents[0].fullDayEvent) { diff --git a/modules/default/calendar/debug.js b/modules/default/calendar/debug.js index 71ed2f4a..74d48cd7 100644 --- a/modules/default/calendar/debug.js +++ b/modules/default/calendar/debug.js @@ -1,4 +1,5 @@ -/* CalendarFetcher Tester +/* + * CalendarFetcher Tester * use this script with `node debug.js` to test the fetcher without the need * of starting the MagicMirror² core. Adjust the values below to your desire. */ diff --git a/modules/default/defaultmodules.js b/modules/default/defaultmodules.js index e28413ff..695bba44 100644 --- a/modules/default/defaultmodules.js +++ b/modules/default/defaultmodules.js @@ -1,4 +1,5 @@ -/* Default Modules List +/* + * Default Modules List * Modules listed below can be loaded without the 'default/' prefix. Omitting the default folder name. */ const defaultModules = ["alert", "calendar", "clock", "compliments", "helloworld", "newsfeed", "updatenotification", "weather"]; diff --git a/modules/default/updatenotification/update_helper.js b/modules/default/updatenotification/update_helper.js index 0bf3868e..122b6b35 100644 --- a/modules/default/updatenotification/update_helper.js +++ b/modules/default/updatenotification/update_helper.js @@ -4,7 +4,8 @@ const fs = require("node:fs"); const Log = require("logger"); -/* class Updater +/* + * class Updater * Allow to self updating 3rd party modules from command defined in config * * [constructor] read value in config: @@ -84,13 +85,15 @@ class Updater { return updater; } - // module updater with his proper command - // return object as result - //{ - // error: , // if error detected - // updated: , // if updated successfully - // needRestart: // if magicmirror restart required - //}; + /* + * module updater with his proper command + * return object as result + * { + * error: , // if error detected + * updated: , // if updated successfully + * needRestart: // if magicmirror restart required + * }; + */ updateProcess (module) { let Result = { error: false, diff --git a/modules/default/weather/providers/envcanada.js b/modules/default/weather/providers/envcanada.js index 7372e176..82558026 100644 --- a/modules/default/weather/providers/envcanada.js +++ b/modules/default/weather/providers/envcanada.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* This class is a provider for Environment Canada MSC Datamart +/* + * This class is a provider for Environment Canada MSC Datamart * Note that this is only for Canadian locations and does not require an API key (access is anonymous) * * EC Documentation at following links: @@ -25,9 +26,7 @@ * * License to use Environment Canada (EC) data is detailed here: * https://eccc-msc.github.io/open-data/licence/readme_en/ - * */ - WeatherProvider.register("envcanada", { // Set the name of the provider for debugging and alerting purposes (eg. provide eye-catcher) providerName: "Environment Canada", @@ -39,10 +38,10 @@ WeatherProvider.register("envcanada", { provCode: "ON" }, - // - // Set config values (equates to weather module config values). Also set values pertaining to caching of - // Today's temperature forecast (for use in the Forecast functions below) - // + /* + * Set config values (equates to weather module config values). Also set values pertaining to caching of + * Today's temperature forecast (for use in the Forecast functions below) + */ setConfig (config) { this.config = config; @@ -52,17 +51,17 @@ WeatherProvider.register("envcanada", { this.cacheCurrentTemp = 999; }, - // - // Called when the weather provider is started - // + /* + * Called when the weather provider is started + */ start () { Log.info(`Weather provider: ${this.providerName} started.`); this.setFetchedLocation(this.config.location); }, - // - // Override the fetchCurrentWeather method to query EC and construct a Current weather object - // + /* + * Override the fetchCurrentWeather method to query EC and construct a Current weather object + */ fetchCurrentWeather () { this.fetchData(this.getUrl(), "xml") .then((data) => { @@ -80,9 +79,9 @@ WeatherProvider.register("envcanada", { .finally(() => this.updateAvailable()); }, - // - // Override the fetchWeatherForecast method to query EC and construct Forecast weather objects - // + /* + * Override the fetchWeatherForecast method to query EC and construct Forecast weather objects + */ fetchWeatherForecast () { this.fetchData(this.getUrl(), "xml") .then((data) => { @@ -100,9 +99,9 @@ WeatherProvider.register("envcanada", { .finally(() => this.updateAvailable()); }, - // - // Override the fetchWeatherHourly method to query EC and construct Forecast weather objects - // + /* + * Override the fetchWeatherHourly method to query EC and construct Forecast weather objects + */ fetchWeatherHourly () { this.fetchData(this.getUrl(), "xml") .then((data) => { @@ -120,36 +119,30 @@ WeatherProvider.register("envcanada", { .finally(() => this.updateAvailable()); }, - ////////////////////////////////////////////////////////////////////////////////// - // - // Environment Canada methods - not part of the standard Provider methods - // - ////////////////////////////////////////////////////////////////////////////////// - - // - // Build the EC URL based on the Site Code and Province Code specified in the config params. Note that the - // URL defaults to the English version simply because there is no language dependency in the data - // being accessed. This is only pertinent when using the EC data elements that contain a textual forecast. - // + /* + * Build the EC URL based on the Site Code and Province Code specified in the config params. Note that the + * URL defaults to the English version simply because there is no language dependency in the data + * being accessed. This is only pertinent when using the EC data elements that contain a textual forecast. + */ getUrl () { return `https://dd.weather.gc.ca/citypage_weather/xml/${this.config.provCode}/${this.config.siteCode}_e.xml`; }, - // - // Generate a WeatherObject based on current EC weather conditions - // - + /* + * Generate a WeatherObject based on current EC weather conditions + */ generateWeatherObjectFromCurrentWeather (ECdoc) { const currentWeather = new WeatherObject(); - // There are instances where EC will update weather data and current temperature will not be - // provided. While this is a defect in the EC systems, we need to accommodate to avoid a current temp - // of NaN being displayed. Therefore... whenever we get a valid current temp from EC, we will cache - // the value. Whenever EC data is missing current temp, we will provide the cached value - // instead. This is reasonable since the cached value will typically be accurate within the previous - // hour. The only time this does not work as expected is when MM is restarted and the first query to - // EC finds no current temp. In this scenario, MM will end up displaying a current temp of null; - + /* + * There are instances where EC will update weather data and current temperature will not be + * provided. While this is a defect in the EC systems, we need to accommodate to avoid a current temp + * of NaN being displayed. Therefore... whenever we get a valid current temp from EC, we will cache + * the value. Whenever EC data is missing current temp, we will provide the cached value + * instead. This is reasonable since the cached value will typically be accurate within the previous + * hour. The only time this does not work as expected is when MM is restarted and the first query to + * EC finds no current temp. In this scenario, MM will end up displaying a current temp of null; + */ if (ECdoc.querySelector("siteData currentConditions temperature").textContent) { currentWeather.temperature = ECdoc.querySelector("siteData currentConditions temperature").textContent; this.cacheCurrentTemp = currentWeather.temperature; @@ -163,19 +156,19 @@ WeatherProvider.register("envcanada", { currentWeather.humidity = ECdoc.querySelector("siteData currentConditions relativeHumidity").textContent; - // Ensure showPrecipitationAmount is forced to false. EC does not really provide POP for current day - // and this feature for the weather module (current only) is sort of broken in that it wants - // to say POP but will display precip as an accumulated amount vs. a percentage. - + /* + * Ensure showPrecipitationAmount is forced to false. EC does not really provide POP for current day + * and this feature for the weather module (current only) is sort of broken in that it wants + * to say POP but will display precip as an accumulated amount vs. a percentage. + */ this.config.showPrecipitationAmount = false; - // - // If the module config wants to showFeelsLike... default to the current temperature. - // Check for EC wind chill and humidex values and overwrite the feelsLikeTemp value. - // This assumes that the EC current conditions will never contain both a wind chill - // and humidex temperature. - // - + /* + * If the module config wants to showFeelsLike... default to the current temperature. + * Check for EC wind chill and humidex values and overwrite the feelsLikeTemp value. + * This assumes that the EC current conditions will never contain both a wind chill + * and humidex temperature. + */ if (this.config.showFeelsLike) { currentWeather.feelsLikeTemp = currentWeather.temperature; @@ -188,16 +181,10 @@ WeatherProvider.register("envcanada", { } } - // // Need to map EC weather icon to MM weatherType values - // - currentWeather.weatherType = this.convertWeatherType(ECdoc.querySelector("siteData currentConditions iconCode").textContent); - // // Capture the sunrise and sunset values from EC data - // - const sunList = ECdoc.querySelectorAll("siteData riseSet dateTime"); currentWeather.sunrise = moment(sunList[1].querySelector("timeStamp").textContent, "YYYYMMDDhhmmss"); @@ -206,13 +193,11 @@ WeatherProvider.register("envcanada", { return currentWeather; }, - // - // Generate an array of WeatherObjects based on EC weather forecast - // - + /* + * Generate an array of WeatherObjects based on EC weather forecast + */ generateWeatherObjectsFromForecast (ECdoc) { // Declare an array to hold each day's forecast object - const days = []; const weather = new WeatherObject(); @@ -226,37 +211,33 @@ WeatherProvider.register("envcanada", { weather.precipitationAmount = null; - // - // The EC forecast is held in a 12-element array - Elements 0 to 11 - with each day encompassing - // 2 elements. the first element for a day details the Today (daytime) forecast while the second - // element details the Tonight (nightime) forecast. Element 0 is always for the current day. - // - // However... the forecast is somewhat 'rolling'. - // - // If the EC forecast is queried in the morning, then Element 0 will contain Current - // Today and Element 1 will contain Current Tonight. From there, the next 5 days of forecast will be - // contained in Elements 2/3, 4/5, 6/7, 8/9, and 10/11. This module will create a 6-day forecast using - // all of these Elements. - // - // But, if the EC forecast is queried in late afternoon, the Current Today forecast will be rolled - // off and Element 0 will contain Current Tonight. From there, the next 5 days will be contained in - // Elements 1/2, 3/4, 5/6, 7/8, and 9/10. As well, Elelement 11 will contain a forecast for a 6th day, - // but only for the Today portion (not Tonight). This module will create a 6-day forecast using - // Elements 0 to 11, and will ignore the additional Todat forecast in Element 11. - // - // We need to determine if Element 0 is showing the forecast for Current Today or Current Tonight. - // This is required to understand how Min and Max temperature will be determined, and to understand - // where the next day's (aka Tomorrow's) forecast is located in the forecast array. - // - + /* + * The EC forecast is held in a 12-element array - Elements 0 to 11 - with each day encompassing + * 2 elements. the first element for a day details the Today (daytime) forecast while the second + * element details the Tonight (nightime) forecast. Element 0 is always for the current day. + * + * However... the forecast is somewhat 'rolling'. + * + * If the EC forecast is queried in the morning, then Element 0 will contain Current + * Today and Element 1 will contain Current Tonight. From there, the next 5 days of forecast will be + * contained in Elements 2/3, 4/5, 6/7, 8/9, and 10/11. This module will create a 6-day forecast using + * all of these Elements. + * + * But, if the EC forecast is queried in late afternoon, the Current Today forecast will be rolled + * off and Element 0 will contain Current Tonight. From there, the next 5 days will be contained in + * Elements 1/2, 3/4, 5/6, 7/8, and 9/10. As well, Elelement 11 will contain a forecast for a 6th day, + * but only for the Today portion (not Tonight). This module will create a 6-day forecast using + * Elements 0 to 11, and will ignore the additional Todat forecast in Element 11. + * + * We need to determine if Element 0 is showing the forecast for Current Today or Current Tonight. + * This is required to understand how Min and Max temperature will be determined, and to understand + * where the next day's (aka Tomorrow's) forecast is located in the forecast array. + */ let nextDay = 0; let lastDay = 0; const currentTemp = ECdoc.querySelector("siteData currentConditions temperature").textContent; - // // If the first Element is Current Today, look at Current Today and Current Tonight for the current day. - // - if (foreGroup[0].querySelector("period[textForecastName='Today']")) { this.todaytempCacheMin = 0; this.todaytempCacheMax = 0; @@ -266,167 +247,144 @@ WeatherProvider.register("envcanada", { this.setPrecipitation(weather, foreGroup, 0); - // - // Set the Element number that will reflect where the next day's forecast is located. Also set - // the Element number where the end of the forecast will be. This is important because of the - // rolling nature of the EC forecast. In the current scenario (Today and Tonight are present - // in elements 0 and 11, we know that we will have 6 full days of forecasts and we will use - // them. We will set lastDay such that we iterate through all 12 elements of the forecast. - // - + /* + * Set the Element number that will reflect where the next day's forecast is located. Also set + * the Element number where the end of the forecast will be. This is important because of the + * rolling nature of the EC forecast. In the current scenario (Today and Tonight are present + * in elements 0 and 11, we know that we will have 6 full days of forecasts and we will use + * them. We will set lastDay such that we iterate through all 12 elements of the forecast. + */ nextDay = 2; lastDay = 12; } - // // If the first Element is Current Tonight, look at Tonight only for the current day. - // if (foreGroup[0].querySelector("period[textForecastName='Tonight']")) { this.setMinMaxTemps(weather, foreGroup, 0, false, currentTemp); this.setPrecipitation(weather, foreGroup, 0); - // - // Set the Element number that will reflect where the next day's forecast is located. Also set - // the Element number where the end of the forecast will be. This is important because of the - // rolling nature of the EC forecast. In the current scenario (only Current Tonight is present - // in Element 0, we know that we will have 6 full days of forecasts PLUS a half-day and - // forecast in the final element. Because we will only use full day forecasts, we set the - // lastDay number to ensure we ignore that final half-day (in forecast Element 11). - // - + /* + * Set the Element number that will reflect where the next day's forecast is located. Also set + * the Element number where the end of the forecast will be. This is important because of the + * rolling nature of the EC forecast. In the current scenario (only Current Tonight is present + * in Element 0, we know that we will have 6 full days of forecasts PLUS a half-day and + * forecast in the final element. Because we will only use full day forecasts, we set the + * lastDay number to ensure we ignore that final half-day (in forecast Element 11). + */ nextDay = 1; lastDay = 11; } - // - // Need to map EC weather icon to MM weatherType values. Always pick the first Element's icon to - // reflect either Today or Tonight depending on what the forecast is showing in Element 0. - // - + /* + * Need to map EC weather icon to MM weatherType values. Always pick the first Element's icon to + * reflect either Today or Tonight depending on what the forecast is showing in Element 0. + */ weather.weatherType = this.convertWeatherType(foreGroup[0].querySelector("abbreviatedForecast iconCode").textContent); // Push the weather object into the forecast array. - days.push(weather); - // - // Now do the rest of the forecast starting at nextDay. We will process each day using 2 EC - // forecast Elements. This will address the fact that the EC forecast always includes Today and - // Tonight for each day. This is why we iterate through the forecast by a a count of 2, with each - // iteration looking at the current Element and the next Element. - // - + /* + * Now do the rest of the forecast starting at nextDay. We will process each day using 2 EC + * forecast Elements. This will address the fact that the EC forecast always includes Today and + * Tonight for each day. This is why we iterate through the forecast by a a count of 2, with each + * iteration looking at the current Element and the next Element. + */ let lastDate = moment(baseDate, "YYYYMMDDhhmmss"); for (let stepDay = nextDay; stepDay < lastDay; stepDay += 2) { let weather = new WeatherObject(); // Add 1 to the date to reflect the current forecast day we are building - lastDate = lastDate.add(1, "day"); weather.date = moment(lastDate); - // Capture the temperatures for the current Element and the next Element in order to set - // the Min and Max temperatures for the forecast - + /* + * Capture the temperatures for the current Element and the next Element in order to set + * the Min and Max temperatures for the forecast + */ this.setMinMaxTemps(weather, foreGroup, stepDay, true, currentTemp); weather.precipitationAmount = null; this.setPrecipitation(weather, foreGroup, stepDay); - // // Need to map EC weather icon to MM weatherType values. Always pick the first Element icon. - // - weather.weatherType = this.convertWeatherType(foreGroup[stepDay].querySelector("abbreviatedForecast iconCode").textContent); // Push the weather object into the forecast array. - days.push(weather); } return days; }, - // - // Generate an array of WeatherObjects based on EC hourly weather forecast - // - + /* + * Generate an array of WeatherObjects based on EC hourly weather forecast + */ generateWeatherObjectsFromHourly (ECdoc) { // Declare an array to hold each hour's forecast object - const hours = []; // Get local timezone UTC offset so that each hourly time can be calculated properly - const baseHours = ECdoc.querySelectorAll("siteData hourlyForecastGroup dateTime"); const hourOffset = baseHours[1].getAttribute("UTCOffset"); - // - // The EC hourly forecast is held in a 24-element array - Elements 0 to 23 - with Element 0 holding - // the forecast for the next 'on the hour' timeslot. This means the array is a rolling 24 hours. - // - + /* + * The EC hourly forecast is held in a 24-element array - Elements 0 to 23 - with Element 0 holding + * the forecast for the next 'on the hour' timeslot. This means the array is a rolling 24 hours. + */ const hourGroup = ECdoc.querySelectorAll("siteData hourlyForecastGroup hourlyForecast"); for (let stepHour = 0; stepHour < 24; stepHour += 1) { const weather = new WeatherObject(); // Determine local time by applying UTC offset to the forecast timestamp - const foreTime = moment(hourGroup[stepHour].getAttribute("dateTimeUTC"), "YYYYMMDDhhmmss"); const currTime = foreTime.add(hourOffset, "hours"); weather.date = moment(currTime); // Capture the temperature - weather.temperature = hourGroup[stepHour].querySelector("temperature").textContent; // Capture Likelihood of Precipitation (LOP) and unit-of-measure values - const precipLOP = hourGroup[stepHour].querySelector("lop").textContent * 1.0; if (precipLOP > 0) { weather.precipitationProbability = precipLOP; } - // // Need to map EC weather icon to MM weatherType values. Always pick the first Element icon. - // - weather.weatherType = this.convertWeatherType(hourGroup[stepHour].querySelector("iconCode").textContent); // Push the weather object into the forecast array. - hours.push(weather); } return hours; }, - // - // Determine Min and Max temp based on a supplied Forecast Element index and a boolen that denotes if - // the next Forecast element should be considered - i.e. look at Today *and* Tonight vs.Tonight-only - // + /* + * Determine Min and Max temp based on a supplied Forecast Element index and a boolen that denotes if + * the next Forecast element should be considered - i.e. look at Today *and* Tonight vs.Tonight-only + */ setMinMaxTemps (weather, foreGroup, today, fullDay, currentTemp) { const todayTemp = foreGroup[today].querySelector("temperatures temperature").textContent; const todayClass = foreGroup[today].querySelector("temperatures temperature").getAttribute("class"); - // - // The following logic is largely aimed at accommodating the Current day's forecast whereby we - // can have either Current Today+Current Tonight or only Current Tonight. - // - // If fullDay is false, then we only have Tonight for the current day's forecast - meaning we have - // lost a min or max temp value for the day. Therefore, we will see if we were able to cache the the - // Today forecast for the current day. If we have, we will use them. If we do not have the cached values, - // it means that MM or the Computer has been restarted since the time EC rolled off Today from the - // forecast. In this scenario, we will simply default to the Current Conditions temperature and then - // check the Tonight temperature. - // - + /* + * The following logic is largely aimed at accommodating the Current day's forecast whereby we + * can have either Current Today+Current Tonight or only Current Tonight. + * + * If fullDay is false, then we only have Tonight for the current day's forecast - meaning we have + * lost a min or max temp value for the day. Therefore, we will see if we were able to cache the the + * Today forecast for the current day. If we have, we will use them. If we do not have the cached values, + * it means that MM or the Computer has been restarted since the time EC rolled off Today from the + * forecast. In this scenario, we will simply default to the Current Conditions temperature and then + * check the Tonight temperature.x + */ if (fullDay === false) { if (this.todayCached === true) { weather.minTemperature = this.todayTempCacheMin; @@ -437,13 +395,12 @@ WeatherProvider.register("envcanada", { } } - // - // We will check to see if the current Element's temperature is Low or High and set weather values - // accordingly. We will also check the condition where fullDay is true *and* we are looking at forecast - // element 0. This is a special case where we will cache temperature values so that we have them later - // in the current day when the Current Today element rolls off and we have Current Tonight only. - // - + /* + * We will check to see if the current Element's temperature is Low or High and set weather values + * accordingly. We will also check the condition where fullDay is true *and* we are looking at forecast + * element 0. This is a special case where we will cache temperature values so that we have them later + * in the current day when the Current Today element rolls off and we have Current Tonight only. + */ if (todayClass === "low") { weather.minTemperature = todayTemp; if (today === 0 && fullDay === true) { @@ -473,25 +430,24 @@ WeatherProvider.register("envcanada", { } }, - // - // Check for a Precipitation forecast. EC can provide a forecast in 2 ways: either an accumulation figure - // or a POP percentage. If there is a POP, then that is what the module will show. If there is an accumulation, - // then it will be displayed ONLY if no POP is present. - // - // POP Logic: By default, we want to show the POP for 'daytime' since we are presuming that is what - // people are more interested in seeing. While EC provides a separate POP for daytime and nightime portions - // of each day, the weather module does not really allow for that view of a daily forecast. There we will - // ignore any nightime portion. There is an exception however! For the Current day, the EC data will only show - // the nightime forecast after a certain point in the afternoon. As such, we will be showing the nightime POP - // (if one exists) in that specific scenario. - // - // Accumulation Logic: Similar to POP, we want to show accumulation for 'daytime' since we presume that is what - // people are interested in seeing. While EC provides a separate accumulation for daytime and nightime portions - // of each day, the weather module does not really allow for that view of a daily forecast. There we will - // ignore any nightime portion. There is an exception however! For the Current day, the EC data will only show - // the nightime forecast after a certain point in that specific scenario. - // - + /* + * Check for a Precipitation forecast. EC can provide a forecast in 2 ways: either an accumulation figure + * or a POP percentage. If there is a POP, then that is what the module will show. If there is an accumulation, + * then it will be displayed ONLY if no POP is present. + * + * POP Logic: By default, we want to show the POP for 'daytime' since we are presuming that is what + * people are more interested in seeing. While EC provides a separate POP for daytime and nightime portions + * of each day, the weather module does not really allow for that view of a daily forecast. There we will + * ignore any nightime portion. There is an exception however! For the Current day, the EC data will only show + * the nightime forecast after a certain point in the afternoon. As such, we will be showing the nightime POP + * (if one exists) in that specific scenario. + * + * Accumulation Logic: Similar to POP, we want to show accumulation for 'daytime' since we presume that is what + * people are interested in seeing. While EC provides a separate accumulation for daytime and nightime portions + * of each day, the weather module does not really allow for that view of a daily forecast. There we will + * ignore any nightime portion. There is an exception however! For the Current day, the EC data will only show + * the nightime forecast after a certain point in that specific scenario. + */ setPrecipitation (weather, foreGroup, today) { if (foreGroup[today].querySelector("precipitation accumulation")) { weather.precipitationAmount = foreGroup[today].querySelector("precipitation accumulation amount").textContent * 1.0; @@ -505,9 +461,9 @@ WeatherProvider.register("envcanada", { } }, - // - // Convert the icons to a more usable name. - // + /* + * Convert the icons to a more usable name. + */ convertWeatherType (weatherType) { const weatherTypes = { "00": "day-sunny", diff --git a/modules/default/weather/providers/openmeteo.js b/modules/default/weather/providers/openmeteo.js index 6acddec7..07f17e93 100644 --- a/modules/default/weather/providers/openmeteo.js +++ b/modules/default/weather/providers/openmeteo.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Open-Meteo, +/* + * This class is a provider for Open-Meteo, * see https://open-meteo.com/ */ @@ -9,8 +10,11 @@ const GEOCODE_BASE = "https://api.bigdatacloud.net/data/reverse-geocode-client"; const OPEN_METEO_BASE = "https://api.open-meteo.com/v1"; WeatherProvider.register("openmeteo", { - // Set the name of the provider. - // Not strictly required, but helps for debugging. + + /* + * Set the name of the provider. + * Not strictly required, but helps for debugging. + */ providerName: "Open-Meteo", // Set the default config properties that is specific to this provider diff --git a/modules/default/weather/providers/openweathermap.js b/modules/default/weather/providers/openweathermap.js index 11504bb5..3f29ed55 100644 --- a/modules/default/weather/providers/openweathermap.js +++ b/modules/default/weather/providers/openweathermap.js @@ -1,12 +1,16 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Openweathermap, +/* + * This class is a provider for Openweathermap, * see https://openweathermap.org/ */ WeatherProvider.register("openweathermap", { - // Set the name of the provider. - // This isn't strictly necessary, since it will fallback to the provider identifier - // But for debugging (and future alerts) it would be nice to have the real name. + + /* + * Set the name of the provider. + * This isn't strictly necessary, since it will fallback to the provider identifier + * But for debugging (and future alerts) it would be nice to have the real name. + */ providerName: "OpenWeatherMap", // Set the default config properties that is specific to this provider @@ -67,8 +71,11 @@ WeatherProvider.register("openweathermap", { this.fetchData(this.getUrl()) .then((data) => { if (!data) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ return; } @@ -206,8 +213,10 @@ WeatherProvider.register("openweathermap", { weather.weatherType = this.convertWeatherType(forecast.weather[0].icon); } - // the same day as before - // add values from forecast to corresponding variables + /* + * the same day as before + * add values from forecast to corresponding variables + */ minTemp.push(forecast.main.temp_min); maxTemp.push(forecast.main.temp_max); @@ -220,8 +229,10 @@ WeatherProvider.register("openweathermap", { } } - // last day - // calculate minimum/maximum temperature, specify rain amount + /* + * last day + * calculate minimum/maximum temperature, specify rain amount + */ weather.minTemperature = Math.min.apply(null, minTemp); weather.maxTemperature = Math.max.apply(null, maxTemp); weather.rain = rain; @@ -250,14 +261,18 @@ WeatherProvider.register("openweathermap", { weather.rain = 0; weather.snow = 0; - // forecast.rain not available if amount is zero - // The API always returns in millimeters + /* + * forecast.rain not available if amount is zero + * The API always returns in millimeters + */ if (forecast.hasOwnProperty("rain") && !isNaN(forecast.rain)) { weather.rain = forecast.rain; } - // forecast.snow not available if amount is zero - // The API always returns in millimeters + /* + * forecast.snow not available if amount is zero + * The API always returns in millimeters + */ if (forecast.hasOwnProperty("snow") && !isNaN(forecast.snow)) { weather.snow = forecast.snow; } @@ -402,7 +417,8 @@ WeatherProvider.register("openweathermap", { return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null; }, - /* getParams(compliments) + /* + * getParams(compliments) * Generates an url with api parameters based on the config. * * return String - URL params. diff --git a/modules/default/weather/providers/pirateweather.js b/modules/default/weather/providers/pirateweather.js index dd20ccf4..969912f4 100644 --- a/modules/default/weather/providers/pirateweather.js +++ b/modules/default/weather/providers/pirateweather.js @@ -1,11 +1,15 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api), +/* + * This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api), * see http://pirateweather.net/en/latest/ */ WeatherProvider.register("pirateweather", { - // Set the name of the provider. - // Not strictly required, but helps for debugging. + + /* + * Set the name of the provider. + * Not strictly required, but helps for debugging. + */ providerName: "pirateweather", // Set the default config properties that is specific to this provider diff --git a/modules/default/weather/providers/smhi.js b/modules/default/weather/providers/smhi.js index d7dcdf1b..14185c86 100644 --- a/modules/default/weather/providers/smhi.js +++ b/modules/default/weather/providers/smhi.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for SMHI (Sweden only). +/* + * This class is a provider for SMHI (Sweden only). * Metric system is the only supported unit, * see https://www.smhi.se/ */ @@ -138,9 +139,11 @@ WeatherProvider.register("smhi", { currentWeather.weatherType = this.convertWeatherType(this.paramValue(weatherData, "Wsymb2"), currentWeather.isDayTime()); currentWeather.feelsLikeTemp = this.calculateApparentTemperature(weatherData); - // Determine the precipitation amount and category and update the - // weatherObject with it, the valuetype to use can be configured or uses - // median as default. + /* + * Determine the precipitation amount and category and update the + * weatherObject with it, the valuetype to use can be configured or uses + * median as default. + */ let precipitationValue = this.paramValue(weatherData, this.config.precipitationValue); switch (this.paramValue(weatherData, "pcat")) { // 0 = No precipitation diff --git a/modules/default/weather/providers/ukmetoffice.js b/modules/default/weather/providers/ukmetoffice.js index c2db4cda..32c1888f 100644 --- a/modules/default/weather/providers/ukmetoffice.js +++ b/modules/default/weather/providers/ukmetoffice.js @@ -1,12 +1,16 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* This class is a provider for UK Met Office Datapoint, +/* + * This class is a provider for UK Met Office Datapoint, * see https://www.metoffice.gov.uk/ */ WeatherProvider.register("ukmetoffice", { - // Set the name of the provider. - // This isn't strictly necessary, since it will fallback to the provider identifier - // But for debugging (and future alerts) it would be nice to have the real name. + + /* + * Set the name of the provider. + * This isn't strictly necessary, since it will fallback to the provider identifier + * But for debugging (and future alerts) it would be nice to have the real name. + */ providerName: "UK Met Office", // Set the default config properties that is specific to this provider @@ -21,8 +25,11 @@ WeatherProvider.register("ukmetoffice", { this.fetchData(this.getUrl("3hourly")) .then((data) => { if (!data || !data.SiteRep || !data.SiteRep.DV || !data.SiteRep.DV.Location || !data.SiteRep.DV.Location.Period || data.SiteRep.DV.Location.Period.length === 0) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ return; } @@ -42,8 +49,11 @@ WeatherProvider.register("ukmetoffice", { this.fetchData(this.getUrl("daily")) .then((data) => { if (!data || !data.SiteRep || !data.SiteRep.DV || !data.SiteRep.DV.Location || !data.SiteRep.DV.Location.Period || data.SiteRep.DV.Location.Period.length === 0) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ return; } @@ -86,8 +96,11 @@ WeatherProvider.register("ukmetoffice", { if (periodDate.isSameOrAfter(moment.utc().startOf("day"))) { // check this is the period we want, after today the diff will be -ve if (moment().diff(periodDate, "minutes") > 0) { - // loop round the reports looking for the one we are in - // $ value specifies the time in minutes-of-the-day: 0, 180, 360,...1260 + + /* + * loop round the reports looking for the one we are in + * $ value specifies the time in minutes-of-the-day: 0, 180, 360,...1260 + */ for (const rep of period.Rep) { const p = rep.$; if (timeInMins >= p && timeInMins - 180 < p) { @@ -117,8 +130,10 @@ WeatherProvider.register("ukmetoffice", { generateWeatherObjectsFromForecast (forecasts) { const days = []; - // loop round the (5) periods getting the data - // for each period array, Day is [0], Night is [1] + /* + * loop round the (5) periods getting the data + * for each period array, Day is [0], Night is [1] + */ for (const period of forecasts.SiteRep.DV.Location.Period) { const weather = new WeatherObject(); diff --git a/modules/default/weather/providers/ukmetofficedatahub.js b/modules/default/weather/providers/ukmetofficedatahub.js index 33e33c50..0a9d872c 100644 --- a/modules/default/weather/providers/ukmetofficedatahub.js +++ b/modules/default/weather/providers/ukmetofficedatahub.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services). +/* + * This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services). * For more information on Data Hub, see https://www.metoffice.gov.uk/services/data/datapoint/notifications/weather-datahub * Data available: * Hourly data for next 2 days ("hourly") - https://www.metoffice.gov.uk/binaries/content/assets/metofficegovuk/pdf/data/global-spot-data-hourly.pdf @@ -54,9 +55,11 @@ WeatherProvider.register("ukmetofficedatahub", { return this.config.apiBase + (this.config.apiBase.endsWith("/") ? "" : "/") + forecastType + queryStrings; }, - // Build the list of headers for the request - // For DataHub requests, the API key/secret are sent in the headers rather than as query strings. - // Headers defined according to Data Hub API (https://datahub.metoffice.gov.uk/docs/f/category/site-specific/type/site-specific/api-documentation#get-/point/hourly) + /* + * Build the list of headers for the request + * For DataHub requests, the API key/secret are sent in the headers rather than as query strings. + * Headers defined according to Data Hub API (https://datahub.metoffice.gov.uk/docs/f/category/site-specific/type/site-specific/api-documentation#get-/point/hourly) + */ getHeaders () { return { accept: "application/json", @@ -78,8 +81,11 @@ WeatherProvider.register("ukmetofficedatahub", { .then((data) => { // Check data is usable if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ Log.error("Possibly bad current/hourly data?"); Log.error(data); return; @@ -127,15 +133,19 @@ WeatherProvider.register("ukmetofficedatahub", { currentWeather.precipitationProbability = forecastDataHours[hour].probOfPrecipitation; currentWeather.feelsLikeTemp = forecastDataHours[hour].feelsLikeTemperature; - // Pass on full details, so they can be used in custom templates - // Note the units of the supplied data when using this (see top of file) + /* + * Pass on full details, so they can be used in custom templates + * Note the units of the supplied data when using this (see top of file) + */ currentWeather.rawData = forecastDataHours[hour]; } } - // Determine the sunrise/sunset times - (still) not supplied in UK Met Office data - // Passes {longitude, latitude} to SunCalc, could pass height to, but - // SunCalc.getTimes doesn't take that into account + /* + * Determine the sunrise/sunset times - (still) not supplied in UK Met Office data + * Passes {longitude, latitude} to SunCalc, could pass height to, but + * SunCalc.getTimes doesn't take that into account + */ currentWeather.updateSunTime(this.config.lat, this.config.lon); return currentWeather; @@ -147,8 +157,11 @@ WeatherProvider.register("ukmetofficedatahub", { .then((data) => { // Check data is usable if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ Log.error("Possibly bad forecast data?"); Log.error(data); return; @@ -203,8 +216,10 @@ WeatherProvider.register("ukmetofficedatahub", { forecastWeather.snow = forecastDataDays[day].dayProbabilityOfSnow; forecastWeather.feelsLikeTemp = forecastDataDays[day].dayMaxFeelsLikeTemp; - // Pass on full details, so they can be used in custom templates - // Note the units of the supplied data when using this (see top of file) + /* + * Pass on full details, so they can be used in custom templates + * Note the units of the supplied data when using this (see top of file) + */ forecastWeather.rawData = forecastDataDays[day]; dailyForecasts.push(forecastWeather); @@ -219,9 +234,11 @@ WeatherProvider.register("ukmetofficedatahub", { this.fetchedLocationName = name; }, - // Match the Met Office "significant weather code" to a weathericons.css icon - // Use: https://metoffice.apiconnect.ibmcloud.com/metoffice/production/node/264 - // and: https://erikflowers.github.io/weather-icons/ + /* + * Match the Met Office "significant weather code" to a weathericons.css icon + * Use: https://metoffice.apiconnect.ibmcloud.com/metoffice/production/node/264 + * and: https://erikflowers.github.io/weather-icons/ + */ convertWeatherType (weatherType) { const weatherTypes = { 0: "night-clear", diff --git a/modules/default/weather/providers/weatherbit.js b/modules/default/weather/providers/weatherbit.js index 7c01f5d6..a36b92bd 100644 --- a/modules/default/weather/providers/weatherbit.js +++ b/modules/default/weather/providers/weatherbit.js @@ -1,11 +1,15 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Weatherbit, +/* + * This class is a provider for Weatherbit, * see https://www.weatherbit.io/ */ WeatherProvider.register("weatherbit", { - // Set the name of the provider. - // Not strictly required, but helps for debugging. + + /* + * Set the name of the provider. + * Not strictly required, but helps for debugging. + */ providerName: "Weatherbit", // Set the default config properties that is specific to this provider diff --git a/modules/default/weather/providers/weatherflow.js b/modules/default/weather/providers/weatherflow.js index 54066d7b..6ffd5b66 100644 --- a/modules/default/weather/providers/weatherflow.js +++ b/modules/default/weather/providers/weatherflow.js @@ -1,11 +1,15 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* This class is a provider for Weatherflow. +/* + * This class is a provider for Weatherflow. * Note that the Weatherflow API does not provide snowfall. */ WeatherProvider.register("weatherflow", { - // Set the name of the provider. - // Not strictly required, but helps for debugging + + /* + * Set the name of the provider. + * Not strictly required, but helps for debugging + */ providerName: "WeatherFlow", // Set the default config properties that is specific to this provider diff --git a/modules/default/weather/providers/weathergov.js b/modules/default/weather/providers/weathergov.js index 8a654784..d8fa621a 100644 --- a/modules/default/weather/providers/weathergov.js +++ b/modules/default/weather/providers/weathergov.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject, WeatherUtils */ -/* Provider: weather.gov +/* + * Provider: weather.gov * https://weather-gov.github.io/api/general-faqs * * This class is a provider for weather.gov. @@ -9,9 +10,12 @@ */ WeatherProvider.register("weathergov", { - // Set the name of the provider. - // This isn't strictly necessary, since it will fallback to the provider identifier - // But for debugging (and future alerts) it would be nice to have the real name. + + /* + * Set the name of the provider. + * This isn't strictly necessary, since it will fallback to the provider identifier + * But for debugging (and future alerts) it would be nice to have the real name. + */ providerName: "Weather.gov", // Set the default config properties that is specific to this provider @@ -98,8 +102,11 @@ WeatherProvider.register("weathergov", { this.fetchData(this.forecastHourlyURL) .then((data) => { if (!data) { - // Did not receive usable new data. - // Maybe this needs a better check? + + /* + * Did not receive usable new data. + * Maybe this needs a better check? + */ return; } const hourly = this.generateWeatherObjectsFromHourly(data.properties.periods); @@ -282,14 +289,18 @@ WeatherProvider.register("weathergov", { weather.weatherType = this.convertWeatherType(forecast.shortForecast, forecast.isDaytime); } - // the same day as before - // add values from forecast to corresponding variables + /* + * the same day as before + * add values from forecast to corresponding variables + */ minTemp.push(forecast.temperature); maxTemp.push(forecast.temperature); } - // last day - // calculate minimum/maximum temperature + /* + * last day + * calculate minimum/maximum temperature + */ weather.minTemperature = Math.min.apply(null, minTemp); weather.maxTemperature = Math.max.apply(null, maxTemp); @@ -302,8 +313,11 @@ WeatherProvider.register("weathergov", { * Convert the icons to a more usable name. */ convertWeatherType (weatherType, isDaytime) { - //https://w1.weather.gov/xml/current_obs/weather.php - // There are way too many types to create, so lets just look for certain strings + + /* + * https://w1.weather.gov/xml/current_obs/weather.php + * There are way too many types to create, so lets just look for certain strings + */ if (weatherType.includes("Cloudy") || weatherType.includes("Partly")) { if (isDaytime) { diff --git a/modules/default/weather/providers/yr.js b/modules/default/weather/providers/yr.js index 35493a16..f305a1c0 100644 --- a/modules/default/weather/providers/yr.js +++ b/modules/default/weather/providers/yr.js @@ -1,6 +1,7 @@ /* global WeatherProvider, WeatherObject */ -/* This class is a provider for Yr.no, a norwegian weather service. +/* + * This class is a provider for Yr.no, a norwegian weather service. * Terms of service: https://developer.yr.no/doc/TermsOfService/ */ WeatherProvider.register("yr", { @@ -67,8 +68,11 @@ WeatherProvider.register("yr", { getWeatherData () { return new Promise((resolve, reject) => { - // If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. - // This is to avoid multiple similar calls to the API. + + /* + * If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. + * This is to avoid multiple similar calls to the API. + */ let shouldWait = localStorage.getItem("yrIsFetchingWeatherData"); if (shouldWait) { const checkForGo = setInterval(function () { @@ -201,8 +205,11 @@ WeatherProvider.register("yr", { }, getStellarData () { - // If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. - // This is to avoid multiple similar calls to the API. + + /* + * If a user has several Yr-modules, for instance one current and one forecast, the API calls must be synchronized across classes. + * This is to avoid multiple similar calls to the API. + */ return new Promise((resolve, reject) => { let shouldWait = localStorage.getItem("yrIsFetchingStellarData"); if (shouldWait) { diff --git a/package-lock.json b/package-lock.json index dfa0d6d8..14bb1e16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,21 +27,21 @@ "pm2": "^5.4.2", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.23.2" + "systeminformation": "^5.23.4" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.8.1", + "@stylistic/eslint-plugin": "^2.6.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.10.2", + "eslint-plugin-jest": "^28.8.0", + "eslint-plugin-jsdoc": "^50.0.0", "eslint-plugin-package-json": "^0.15.2", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.4", "jest": "^29.7.0", "jsdom": "^24.1.1", - "lint-staged": "^15.2.7", - "playwright": "^1.45.3", + "lint-staged": "^15.2.8", + "playwright": "^1.46.0", "prettier": "^3.3.3", "sinon": "^18.0.0", "stylelint": "^16.8.1", @@ -1850,91 +1850,114 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-1.8.1.tgz", - "integrity": "sha512-64My6I7uCcmSQ//427Pfg2vjSf9SDzfsGIWohNFgISMLYdC5BzJqDo647iDDJzSxINh3WTC0Ql46ifiKuOoTyA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.6.2.tgz", + "integrity": "sha512-Ic5oFNM/25iuagob6LiIBkSI/A2y45TsyKtDtODXHRZDy52WfPfeexI6r+OH5+aWN9QGob2Bw+4JRM9/4areWw==", "dev": true, - "license": "MIT", "dependencies": { - "@stylistic/eslint-plugin-js": "1.8.1", - "@stylistic/eslint-plugin-jsx": "1.8.1", - "@stylistic/eslint-plugin-plus": "1.8.1", - "@stylistic/eslint-plugin-ts": "1.8.1", - "@types/eslint": "^8.56.10" + "@stylistic/eslint-plugin-js": "2.6.2", + "@stylistic/eslint-plugin-jsx": "2.6.2", + "@stylistic/eslint-plugin-plus": "2.6.2", + "@stylistic/eslint-plugin-ts": "2.6.2", + "@types/eslint": "^9.6.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.1.tgz", - "integrity": "sha512-c5c2C8Mos5tTQd+NWpqwEu7VT6SSRooAguFPMj1cp2RkTYl1ynKoXo8MWy3k4rkbzoeYHrqC2UlUzsroAN7wtQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.6.2.tgz", + "integrity": "sha512-wCr/kVctAPayMU3pcOI1MKR7MoKIh6VKZU89lPklAqtJoxT+Em6RueiiARbpznUYG5eg3LymiU+aMD+aIZXdqA==", "dev": true, - "license": "MIT", "dependencies": { - "@types/eslint": "^8.56.10", - "acorn": "^8.11.3", - "escape-string-regexp": "^4.0.0", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1" + "@types/eslint": "^9.6.0", + "acorn": "^8.12.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, - "node_modules/@stylistic/eslint-plugin-jsx": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-1.8.1.tgz", - "integrity": "sha512-k1Eb6rcjMP+mmjvj+vd9y5KUdWn1OBkkPLHXhsrHt5lCDFZxJEs0aVQzE5lpYrtVZVkpc5esTtss/cPJux0lfA==", + "node_modules/@stylistic/eslint-plugin-js/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/eslint-plugin-js/node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, - "license": "MIT", "dependencies": { - "@stylistic/eslint-plugin-js": "^1.8.1", - "@types/eslint": "^8.56.10", + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/eslint-plugin-jsx": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-jsx/-/eslint-plugin-jsx-2.6.2.tgz", + "integrity": "sha512-dSXK/fSPA938J1fBi10QmhzLKtZ/2TuyVNHQMk8jUhWfKJDleAogaSqcWNAbN8fwcoe9UWmt/3StiIf2oYC1aQ==", + "dev": true, + "dependencies": { + "@stylistic/eslint-plugin-js": "^2.6.2", + "@types/eslint": "^9.6.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "node_modules/@stylistic/eslint-plugin-plus": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-1.8.1.tgz", - "integrity": "sha512-4+40H3lHYTN8OWz+US8CamVkO+2hxNLp9+CAjorI7top/lHqemhpJvKA1LD9Uh+WMY9DYWiWpL2+SZ2wAXY9fQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-plus/-/eslint-plugin-plus-2.6.2.tgz", + "integrity": "sha512-cANcPASfRvq3VTbbQCrSIXq+2AI0IW68PNYaZoXXS0ENlp7HDB8dmrsJnOgWCcoEvdCB8z/eWcG/eq/v5Qcl+Q==", "dev": true, - "license": "MIT", "dependencies": { - "@types/eslint": "^8.56.10", - "@typescript-eslint/utils": "^6.21.0" + "@types/eslint": "^9.6.0", + "@typescript-eslint/utils": "^8.0.0" }, "peerDependencies": { "eslint": "*" } }, "node_modules/@stylistic/eslint-plugin-ts": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-1.8.1.tgz", - "integrity": "sha512-/q1m+ZuO1JHfiSF16EATFzv7XSJkc5W6DocfvH5o9oB6WWYFMF77fVoBWnKT3wGptPOc2hkRupRKhmeFROdfWA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-ts/-/eslint-plugin-ts-2.6.2.tgz", + "integrity": "sha512-6OEN3VtUNxjgOvWPavnC10MByr1H4zsgwNND3rQXr5lDFv93MLUnTsH+/SH15OkuqdyJgrQILI6b9lYecb1vIg==", "dev": true, - "license": "MIT", "dependencies": { - "@stylistic/eslint-plugin-js": "1.8.1", - "@types/eslint": "^8.56.10", - "@typescript-eslint/utils": "^6.21.0" + "@stylistic/eslint-plugin-js": "2.6.2", + "@types/eslint": "^9.6.0", + "@typescript-eslint/utils": "^8.0.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { "eslint": ">=8.40.0" @@ -2033,11 +2056,10 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", "dev": true, - "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2047,8 +2069,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/glob": { "version": "7.2.0", @@ -2162,13 +2183,6 @@ "@types/node": "*" } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -2204,17 +2218,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", + "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2222,13 +2235,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", + "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", "dev": true, - "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2236,23 +2248,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", + "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2265,43 +2276,38 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.1.tgz", + "integrity": "sha512-CBFR0G0sCt0+fzfnKaciu9IBsKvEKYwN9UZ+eeogK1fYHg4Qxk1yf/wLQkLXlq8wbU2dFlgAesxt8Gi76E8RTA==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "semver": "^7.5.4" + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/typescript-estree": "8.0.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", + "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.21.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.0.1", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2328,10 +2334,9 @@ } }, "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", - "license": "MIT", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { "acorn": "bin/acorn" }, @@ -2967,7 +2972,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -3279,16 +3283,15 @@ } }, "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, - "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3323,7 +3326,6 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, - "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" @@ -3460,8 +3462,7 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/combined-stream": { "version": "1.0.8", @@ -4145,8 +4146,7 @@ "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/encodeurl": { "version": "1.0.2", @@ -4240,6 +4240,18 @@ "node": ">=6" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/envsub": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/envsub/-/envsub-4.1.0.tgz", @@ -4674,19 +4686,18 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", - "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", + "version": "28.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.0.tgz", + "integrity": "sha512-Tubj1hooFxCl52G4qQu0edzV/+EZzPUeN8p2NnW5uu4fbDs+Yo7+qDVDc4/oG3FbCqEBmu/OC3LSsyiU22oghw==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "engines": { "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0 || ^8.0.0", "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", "jest": "*" }, @@ -4700,9 +4711,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.10.2.tgz", - "integrity": "sha512-xTkf/MmEeVrTbezc6kDqCJmK9RcseIKo8X4oyoDCMvV4LY8dqrQi8kmfRrv9n0gNBkCclevaOh2Lkmu6Fs8SLg==", + "version": "50.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.0.0.tgz", + "integrity": "sha512-czyJ5F7/qY2LIhUD5Bl6q1CCZ8mjvfEA9HQN5nvIp/Pb8VLIlUNd+DMZdA2OKN74QQMS3pobC06hFqAOJyOv5Q==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.46.0", @@ -4982,8 +4993,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/execa": { "version": "5.1.1", @@ -5534,7 +5544,6 @@ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -6479,7 +6488,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7692,22 +7700,21 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.7", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz", - "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==", + "version": "15.2.8", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.8.tgz", + "integrity": "sha512-PUWFf2zQzsd9EFU+kM1d7UP+AZDbKFKuj+9JNVTBkhUFhbg4MAt6WfyMMwBfM4lYqd4D2Jwac5iuTu9rVj4zCQ==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "~5.3.0", "commander": "~12.1.0", - "debug": "~4.3.4", + "debug": "~4.3.6", "execa": "~8.0.1", - "lilconfig": "~3.1.1", - "listr2": "~8.2.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", "micromatch": "~4.0.7", "pidtree": "~0.6.0", "string-argv": "~0.3.2", - "yaml": "~2.4.2" + "yaml": "~2.5.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -7887,16 +7894,15 @@ } }, "node_modules/listr2": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz", - "integrity": "sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", + "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", "dev": true, - "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^6.0.0", + "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" }, @@ -7946,15 +7952,14 @@ "license": "MIT" }, "node_modules/log-update": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", - "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-escapes": "^6.2.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^7.0.0", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -7966,13 +7971,15 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", - "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, - "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7983,7 +7990,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -7996,7 +8002,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -8009,7 +8014,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, - "license": "MIT", "dependencies": { "get-east-asian-width": "^1.0.0" }, @@ -8025,7 +8029,6 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -8042,7 +8045,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -8254,6 +8256,18 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -8275,11 +8289,10 @@ } }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -9017,7 +9030,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -9130,12 +9142,12 @@ } }, "node_modules/playwright": { - "version": "1.45.3", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.3.tgz", - "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.0.tgz", + "integrity": "sha512-XYJ5WvfefWONh1uPAUAi0H2xXV5S3vrtcnXe6uAOgdGi3aSpqOSXX08IAjXW34xitfuOJsvXU5anXZxPSEQiJw==", "dev": true, "dependencies": { - "playwright-core": "1.45.3" + "playwright-core": "1.46.0" }, "bin": { "playwright": "cli.js" @@ -9148,9 +9160,9 @@ } }, "node_modules/playwright-core": { - "version": "1.45.3", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.3.tgz", - "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.0.tgz", + "integrity": "sha512-9Y/d5UIwuJk8t3+lhmMSAJyNP1BUC/DqP3cQJDQQL/oWqAiuPTLgy7Q5dzglmTLwcBRdetzgNM/gni7ckfTr6A==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -10051,22 +10063,48 @@ } }, "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, - "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -10081,8 +10119,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/rimraf": { "version": "3.0.2", @@ -10537,7 +10574,6 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -10554,7 +10590,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -10826,11 +10861,10 @@ } }, "node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -10848,7 +10882,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -10861,7 +10894,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -11369,9 +11401,9 @@ "dev": true }, "node_modules/systeminformation": { - "version": "5.23.2", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.2.tgz", - "integrity": "sha512-FoipTSwzZR68ZAjXZ8DRH2DFEErMAOi9JvRMsn6i/hTp6Hd4W4nM1W6a+kUyMrp/pd1SIuUzUZvvkQ21yE6Dig==", + "version": "5.23.4", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.23.4.tgz", + "integrity": "sha512-mD2R9xnOzKOOmIVtxekosf/ghOE/DGLqAPmsEgQMWJK0pMKxBtX19riz1Ss0tN4omcfS2FQ2RDJ4lkxgADxIPw==", "os": [ "darwin", "linux", @@ -11587,7 +11619,6 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=16" }, @@ -12152,7 +12183,6 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -12170,7 +12200,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -12183,7 +12212,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -12196,7 +12224,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -12283,11 +12310,10 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", "dev": true, - "license": "ISC", "bin": { "yaml": "bin.mjs" }, diff --git a/package.json b/package.json index 3048aefa..b0eb77e9 100644 --- a/package.json +++ b/package.json @@ -71,21 +71,21 @@ "pm2": "^5.4.2", "socket.io": "^4.7.5", "suncalc": "^1.9.0", - "systeminformation": "^5.23.2" + "systeminformation": "^5.23.4" }, "devDependencies": { - "@stylistic/eslint-plugin": "^1.8.1", + "@stylistic/eslint-plugin": "^2.6.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.10.2", + "eslint-plugin-jest": "^28.8.0", + "eslint-plugin-jsdoc": "^50.0.0", "eslint-plugin-package-json": "^0.15.2", "eslint-plugin-unicorn": "^55.0.0", "express-basic-auth": "^1.2.1", "husky": "^9.1.4", "jest": "^29.7.0", "jsdom": "^24.1.1", - "lint-staged": "^15.2.7", - "playwright": "^1.45.3", + "lint-staged": "^15.2.8", + "playwright": "^1.46.0", "prettier": "^3.3.3", "sinon": "^18.0.0", "stylelint": "^16.8.1", diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js index 608c71da..fb431ad7 100644 --- a/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_dst.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js index 6128c97f..b6ea3011 100644 --- a/tests/configs/modules/calendar/exdate_la_at_midnight_std.js +++ b/tests/configs/modules/calendar/exdate_la_at_midnight_std.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_la_before_midnight.js b/tests/configs/modules/calendar/exdate_la_before_midnight.js index 8c886f77..e5518df7 100644 --- a/tests/configs/modules/calendar/exdate_la_before_midnight.js +++ b/tests/configs/modules/calendar/exdate_la_before_midnight.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js index f98b75f4..e6287e2b 100644 --- a/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js index 06c7ff53..90003879 100644 --- a/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js +++ b/tests/configs/modules/calendar/exdate_syd_at_midnight_std.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/exdate_syd_before_midnight.js b/tests/configs/modules/calendar/exdate_syd_before_midnight.js index 849c1f53..3b176329 100644 --- a/tests/configs/modules/calendar/exdate_syd_before_midnight.js +++ b/tests/configs/modules/calendar/exdate_syd_before_midnight.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test calendar exdate +/* + * MagicMirror² Test calendar exdate * * By jkriegshauser * MIT Licensed. diff --git a/tests/configs/modules/calendar/long-fullday-event.js b/tests/configs/modules/calendar/long-fullday-event.js index efbc2448..80137810 100644 --- a/tests/configs/modules/calendar/long-fullday-event.js +++ b/tests/configs/modules/calendar/long-fullday-event.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test config for fullday calendar entries over multiple days +/* + * MagicMirror² Test config for fullday calendar entries over multiple days * * By Paranoid93 https://github.com/Paranoid93/ * MIT Licensed. diff --git a/tests/configs/modules/calendar/single-fullday-event.js b/tests/configs/modules/calendar/single-fullday-event.js index 9149d2d9..7dae3611 100644 --- a/tests/configs/modules/calendar/single-fullday-event.js +++ b/tests/configs/modules/calendar/single-fullday-event.js @@ -1,4 +1,5 @@ -/* MagicMirror² Test config for fullday calendar entries over multiple days +/* + * MagicMirror² Test config for fullday calendar entries over multiple days * * By Paranoid93 https://github.com/Paranoid93/ * MIT Licensed. diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js index 4e6aee17..bf10ecd7 100644 --- a/tests/electron/modules/calendar_spec.js +++ b/tests/electron/modules/calendar_spec.js @@ -44,9 +44,10 @@ describe("Calendar module", () => { }); }); - /****************************/ - // RRULE TESTS: - // Add any tests that check rrule functionality here. + /* + * RRULE TESTS: + * Add any tests that check rrule functionality here. + */ describe("rrule", () => { it("Issue #3393 recurrence dates past rrule until date", async () => { await helpers.startApplication("tests/configs/modules/calendar/rrule_until.js", "07 Mar 2024 10:38:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); @@ -60,15 +61,16 @@ describe("Calendar module", () => { }); }); - /****************************/ - // LOS ANGELES TESTS: - // In 2023, DST (GMT-7) was until 5 Nov, after which is standard (STD) (GMT-8) time. - // Test takes place on Thu 19 Oct, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be - // 4 events (25 Oct, 1 Nov, (switch to STD), 8 Nov, Nov 15), but 1 Nov and 8 Nov are excluded. - // There are three separate tests: - // * before midnight GMT (3pm local time) - // * at midnight GMT in STD time (4pm local time) - // * at midnight GMT in DST time (5pm local time) + /* + * LOS ANGELES TESTS: + * In 2023, DST (GMT-7) was until 5 Nov, after which is standard (STD) (GMT-8) time. + * Test takes place on Thu 19 Oct, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be + * 4 events (25 Oct, 1 Nov, (switch to STD), 8 Nov, Nov 15), but 1 Nov and 8 Nov are excluded. + * There are three separate tests: + * * before midnight GMT (3pm local time) + * * at midnight GMT in STD time (4pm local time) + * * at midnight GMT in DST time (5pm local time) + */ describe("Exdate: LA crossover DST before midnight GMT", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_la_before_midnight.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles"); @@ -107,15 +109,16 @@ describe("Calendar module", () => { }); }); - /****************************/ - // SYDNEY TESTS: - // In 2023, standard time (STD) (GMT+10) was until 1 Oct, after which is DST (GMT+11). - // Test takes place on Thu 14 Sep, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be - // 4 events (20 Sep, 27 Sep, (switch to DST), 4 Oct, 11 Oct), but 27 Sep and 4 Oct are excluded. - // There are three separate tests: - // * before midnight GMT (9am local time) - // * at midnight GMT in STD time (10am local time) - // * at midnight GMT in DST time (11am local time) + /* + * SYDNEY TESTS: + * In 2023, standard time (STD) (GMT+10) was until 1 Oct, after which is DST (GMT+11). + * Test takes place on Thu 14 Sep, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be + * 4 events (20 Sep, 27 Sep, (switch to DST), 4 Oct, 11 Oct), but 27 Sep and 4 Oct are excluded. + * There are three separate tests: + * * before midnight GMT (9am local time) + * * at midnight GMT in STD time (10am local time) + * * at midnight GMT in DST time (11am local time) + */ describe("Exdate: SYD crossover DST before midnight GMT", () => { it("LA crossover DST before midnight GMT should have 2 events", async () => { await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_before_midnight.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney");