From f911f420632f8262990ee8adb613e18c0eb0dcee Mon Sep 17 00:00:00 2001 From: Parnic Date: Sat, 4 Jan 2025 19:28:53 -0600 Subject: [PATCH] Initial commit, WIP This gets the module far enough along that it can use the library, find and connect to a unit, and issue requests to it. This is a copy/paste of the ScreenLogic version, so I expect a lot of changes/renames will need to happen still. --- .github/workflows/nodejs.yml | 25 + .gitignore | 58 + .markdownlint.json | 8 + .stylelintrc | 10 + .vscode/launch.json | 16 + CHANGELOG.md | 10 + LICENSE | 21 + MMM-IntelliCenter.js | 332 +++++ README.md | 76 ++ eslint.config.mjs | 8 + intellicenter.css | 165 +++ node_helper.js | 283 ++++ package-lock.json | 2413 ++++++++++++++++++++++++++++++++++ package.json | 24 + screenshot.png | Bin 0 -> 39262 bytes 15 files changed, 3449 insertions(+) create mode 100644 .github/workflows/nodejs.yml create mode 100644 .gitignore create mode 100644 .markdownlint.json create mode 100644 .stylelintrc create mode 100644 .vscode/launch.json create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 MMM-IntelliCenter.js create mode 100644 README.md create mode 100644 eslint.config.mjs create mode 100644 intellicenter.css create mode 100644 node_helper.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 screenshot.png diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 0000000..45381f0 --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,25 @@ +name: Node.js CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18.x, 20.x, 22.x] + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm run build --if-present + - run: npm run lint diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..621038f --- /dev/null +++ b/.gitignore @@ -0,0 +1,58 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..9166b4c --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,8 @@ +{ + "default": true, + "no-duplicate-header": { + "siblings_only": true + }, + "line-length": false, + "no-inline-html": false +} diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000..35f4025 --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,10 @@ +{ + "extends": "stylelint-config-standard", + "plugins": ["stylelint-prettier"], + "rules": { + "selector-class-pattern": [ + "^([a-z][a-z0-9]*|MMM-IntelliCenter)(-[a-z0-9]+)*$", + { "message": "Expected class selector to be kebab-case" } + ] + } +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b21a73b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": ["/**"], + "cwd": "${workspaceFolder}/../../", + "args": ["serveronly"] + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1213294 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.0] - 2025-01-04 + +- Initial release. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7c92913 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 parnic + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/MMM-IntelliCenter.js b/MMM-IntelliCenter.js new file mode 100644 index 0000000..5674fde --- /dev/null +++ b/MMM-IntelliCenter.js @@ -0,0 +1,332 @@ +/* global Module Log document */ + +let poolData = {}; + +Module.register("MMM-IntelliCenter", { + defaults: { + showPoolTemp: true, + showSpaTemp: true, + showPH: true, + showOrp: true, + showSaltLevel: true, + showSaturation: true, + showFreezeMode: true, + showControls: false, + controls: [], + colored: true, + coldTemp: 84, + hotTemp: 90, + columns: 3, + contentClass: "light", + showPHTankLevel: true, + pHTankLevelMax: 6, + serverAddress: "", + serverPort: 0, + multicastInterface: "" + }, + + start() { + if ( + this.config.showControls && + (!this.config.controls || this.config.controls.length === 0) + ) { + Log.warn( + "Controls are enabled, but no controls are configured. See README for info on setting up controls." + ); + this.config.showControls = false; + } + + this.sendSocketNotification("INTELLICENTER_CONFIG", this.config); + }, + + getStyles() { + return ["intellicenter.css"]; + }, + + getDom() { + if (!poolData.status) { + const wrapper = document.createElement("div"); + wrapper.innerHTML = "Loading IntelliCenter..."; + wrapper.className += "dimmed light small text-center"; + + return wrapper; + } + const outermost = document.createElement("div"); + outermost.classList.add("container"); + + const reconnectDiv = document.createElement("div"); + reconnectDiv.classList.add("overlay", "reconnecting", "d-none"); + + const reconnectLabel = document.createElement("div"); + reconnectLabel.classList.add("margin-auto", "bg-blur"); + reconnectLabel.innerHTML = "Reconnecting..."; + reconnectDiv.appendChild(reconnectLabel); + + const table = document.createElement("table"); + table.classList.add("base-content", "small"); + if (this.config.colored) { + table.classList.add("colored"); + } + + outermost.appendChild(reconnectDiv); + outermost.appendChild(table); + + const contents = []; + + if (this.config.showPoolTemp) { + let className = ""; + if (poolData.status.currentTemp[0] <= this.config.coldTemp) { + className += " cold-temp"; + } else if (poolData.status.currentTemp[0] >= this.config.hotTemp) { + className += " hot-temp"; + } + + contents.push({ + header: "Pool temp", + data: `${poolData.status.currentTemp[0]}°${!isPoolActive(poolData.status) ? " (last)" : ""}`, + class: this.config.contentClass + className + }); + } + if (this.config.showSpaTemp) { + let className = ""; + if (poolData.status.currentTemp[1] <= this.config.coldTemp) { + className = " cold-temp"; + } else if (poolData.status.currentTemp[1] >= this.config.hotTemp) { + className = " hot-temp"; + } + + contents.push({ + header: "Spa temp", + data: `${poolData.status.currentTemp[1]}°${!isSpaActive(poolData.status) ? " (last)" : ""}`, + class: this.config.contentClass + className + }); + } + if (this.config.showPH) { + let dataStr = poolData.status.pH; + if (this.config.showPHTankLevel) { + const percent = Math.round( + ((poolData.status.pHTank - 1) / this.config.pHTankLevelMax) * 100 + ); + let cls = ""; + if (this.config.colored) { + if (percent <= 17) { + cls = "progress-bar-danger"; + } else if (percent <= 33) { + cls = "progress-bar-warning"; + } else { + cls = "progress-bar-success"; + } + } + const progBarDiv = `
+
+
+
`; + + dataStr = `${dataStr} ${progBarDiv}`; + } + + contents.push({ + header: "pH", + data: dataStr, + class: this.config.contentClass + }); + } + if (this.config.showOrp) { + contents.push({ + header: "ORP", + data: poolData.status.orp, + class: this.config.contentClass + }); + } + if (this.config.showSaltLevel) { + contents.push({ + header: "Salt PPM", + data: poolData.status.saltPPM, + class: this.config.contentClass + }); + } + if (this.config.showSaturation) { + contents.push({ + header: "Saturation", + data: poolData.status.saturation, + class: this.config.contentClass + }); + } + if (this.config.showControls) { + for (const control in this.config.controls) { + const controlObj = this.config.controls[control]; + + if (controlObj.type === "circuit") { + let { name } = controlObj; + for (const circuit in poolData.controllerConfig.bodyArray) { + if ( + poolData.controllerConfig.bodyArray[circuit].circuitId === + controlObj.id + ) { + if (!name) { + name = poolData.controllerConfig.bodyArray[circuit].name; + } + } + } + + let on = false; + for (const circuit in poolData.status.circuitArray) { + if (poolData.status.circuitArray[circuit].id === controlObj.id) { + on = poolData.status.circuitArray[circuit].state !== 0; + } + } + + let cls = ""; + if (this.config.colored) { + cls = on ? "control-on" : "control-off"; + } + + contents.push({ + data: ``, + class: this.config.contentClass + }); + } else if (controlObj.type === "heatpoint") { + if ( + controlObj.body < 0 || + controlObj.body > poolData.status.setPoint.length + ) { + Log.warn("Invalid body specified for heatpoint"); + continue; + } + + const temperature = poolData.status.setPoint[controlObj.body]; + + let dataHtml = '
'; + dataHtml += ``; + dataHtml += `
${controlObj.name}: ${temperature}°
`; + dataHtml += ``; + + contents.push({ + data: dataHtml, + class: this.config.contentClass + }); + } else if (controlObj.type === "heatmode") { + if ( + controlObj.body < 0 || + controlObj.body > poolData.status.heatMode.length + ) { + Log.warn("Invalid body specified for heatmode"); + continue; + } + + const on = poolData.status.heatMode[controlObj.body] !== 0; + const mode = + typeof controlObj.heatMode === "number" ? controlObj.heatMode : 3; + + let cls = ""; + if (this.config.colored) { + cls = on ? "control-on" : "control-off"; + } + + contents.push({ + data: ``, + class: this.config.contentClass + }); + } else { + Log.warn("circuit with unknown type, unable to display:"); + Log.warn(controlObj); + } + } + } + + let headerRow = null; + let contentRow = null; + + if (this.config.showFreezeMode && poolData.status.freezeMode !== 0) { + const row = document.createElement("tr"); + table.appendChild(row); + row.className = "cold-temp"; + const cell = document.createElement("th"); + row.appendChild(cell); + cell.colSpan = this.config.columns; + cell.innerHTML = "
FREEZE MODE
"; + } + + let cols = -1; + for (const item in contents) { + cols++; + if (cols % this.config.columns === 0) { + headerRow = document.createElement("tr"); + contentRow = document.createElement("tr"); + table.appendChild(headerRow); + table.appendChild(contentRow); + } + + if (contents[item].header) { + const headerCell = document.createElement("th"); + headerCell.innerHTML = contents[item].header; + headerRow.appendChild(headerCell); + } + + const contentCell = document.createElement("td"); + contentCell.innerHTML = contents[item].data; + contentCell.className = contents[item].class; + contentRow.appendChild(contentCell); + } + + return outermost; + }, + + socketNotificationReceived(notification, payload) { + if (notification === "INTELLICENTER_RESULT") { + poolData = payload; + this.updateDom(); + showReconnectOverlay(false); + } else if ( + notification === "INTELLICENTER_CIRCUIT_DONE" || + notification === "INTELLICENTER_HEATSTATE_DONE" || + notification === "INTELLICENTER_HEATPOINT_DONE" + ) { + poolData.status = payload.status; + this.updateDom(); + showReconnectOverlay(false); + } else if (notification === "INTELLICENTER_RECONNECTING") { + showReconnectOverlay(true); + } + } +}); + +function showReconnectOverlay(show) { + const element = document.querySelector(".MMM-IntelliCenter .reconnecting"); + if (!element || !element.classList) { + return; + } + + if (show) { + element.classList.remove("d-none"); + } else { + element.classList.add("d-none"); + } +} + +const SPA_CIRCUIT_ID = 500; +const POOL_CIRCUIT_ID = 505; + +function isPoolActive(status) { + for (let i = 0; i < status.circuitArray.length; i += 1) { + if (status.circuitArray[i].id === POOL_CIRCUIT_ID) { + return status.circuitArray[i].state === 1; + } + } +} + +function isSpaActive(status) { + for (let i = 0; i < status.circuitArray.length; i += 1) { + if (status.circuitArray[i].id === SPA_CIRCUIT_ID) { + return status.circuitArray[i].state === 1; + } + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..811485e --- /dev/null +++ b/README.md @@ -0,0 +1,76 @@ +# MMM-IntelliCenter + +[MagicMirror²](https://github.com/MichMich/MagicMirror) module used to connect to a local Pentair IntelliCenter pool controller system. + +## Installation + +1. Navigate into your MagicMirror's `modules` folder and execute `git clone https://github.com/parnic/MMM-IntelliCenter.git`. +2. `cd MMM-IntelliCenter` +3. Execute `npm install --production` to install the node dependencies. +4. Add the module inside `config.js` placing it where you prefer. + +## Config + +| Option | Type | Description | Default | +| ----------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | +| `coldTemp` | Integer | Show the temperature colored blue if it's at or below this level for pool/spa (requires option `colored`). This is in whatever scale your system is set to (Fahrenheit/Celsius). | `84` | +| `colored` | Boolean | Whether you'd like colored output or not. | `true` | +| `columns` | Integer | How many columns to use to display the data before starting a new row. | `3` | +| `contentClass` | String | The CSS class used to display content values (beneath the header). | `"light"` | +| `controls` | Array | List of controls to show buttons for. Must also set `showControls` to `true`.

Each entry in this list is an object with a `type` string property and a `name` string to display.

Valid `type`s:
`"circuit"` - toggle a circuit on or off. Must also have an `id` number property defining the circuit ID to set (see [node-intellicenter](https://github.com/parnic/node-intellicenter) documentation for circuit IDs). `name` is an optional string; if not specified, the name of the equipment in the IntelliCenter system will be used.
`"heatmode"` - enable or disable the heater for the pool or spa. Must also have a `body` number property that defines which body to toggle the heater for (`0` is the pool, `1` is the spa). Can optionally have a `heatMode` number property that defines which heat mode to set; if not present, defaults to 3 ("heat pump").
`"heatpoint"` - set the heat temperature for the pool or spa. Must also have a `body` number property that defines which body to set the heat point for (`0` is the pool, `1` is the spa) | `[]` | +| `hotTemp` | Integer | Show the temperature colored red if it's at or above this level for pool/spa (requires option `colored`). This is in whatever scale your system is set to (Fahrenheit/Celsius). | `90` | +| `serverAddress` | String | The IPv4 address of a IntelliCenter unit to connect to. If not set, the system will search for a unit to connect to. If set, `serverPort` must also be set. | | +| `serverPort` | Integer | The port of a IntelliCenter unit to connect to (usually 6680). If not set, the system will search for a unit to connect to. If set, `serverAddress` must also be set. | | +| `showControls` | Boolean | Whether you'd like to show buttons for controlling pool equipment. Must also setup the `controls` array. | `false` | +| `showFreezeMode` | Boolean | Whether you'd like to show a banner when the pool is in freeze mode or not. [added in v1.0.1] | `true` | +| `showOrp` | Boolean | Whether you'd like to show ORP level or not. | `true` | +| `showPH` | Boolean | Whether you'd like to show pH level or not. | `true` | +| `showPHTankLevel` | Boolean | Whether you'd like to show how much pH balancer is in the tank or not. Only functions if `showPH` is also on. | `true` | +| `pHTankLevelMax` | Boolean | If `showPHTankLevel` is enabled, this is the maximum value that the system returns for a full tank. My systems has this always set to 6, but maybe it differs based on what type of pH balancer you're using. | `6` | +| `showPoolTemp` | Boolean | Whether you'd like to show pool temperature or not. | `true` | +| `showSaltLevel` | Boolean | Whether you'd like to show salt level (in PPM) or not. | `true` | +| `showSaturation` | Boolean | Whether you'd like to show saturation/balance or not. | `true` | +| `showSpaTemp` | Boolean | Whether you'd like to show spa temperature or not. | `true` | + +Here is an example of an entry in config.js + +```js +{ + module: 'MMM-IntelliCenter', + header: 'Pool info', + position: 'top_left', + config: { + showSpaTemp: false, + columns: 2, + contentClass: 'thin', + showControls: true, + controls: [ + {type: 'circuit', id: 500}, + {type: 'circuit', id: 505, name: 'Pool'}, + {type: 'heatmode', body: 0, name: 'Pool heater'}, + {type: 'heatpoint', body: 0, name: 'Pool'}, + {type: 'heatmode', body: 1, heatMode: 2, name: 'Spa heater'}, + ] + } +}, +``` + +## Screenshot + +### With color + +![Screenshot with color](/screenshot.png?raw=true "colored: true") + +## Notes + +Pull requests are very welcome! If you'd like to see any additional functionality, don't hesitate to let me know. + +This module only works with IntelliCenter controllers on the local network via either a UDP broadcast on 255.255.255.255 or a direct connection if you've specified an address and port in the configuration. + +The data is updated when the pool equipment sends an update (which typically happens 0-10 seconds after anything changes), and direct updates are requested after any control is toggled/changed. + +When toggling a circuit or changing heat mode, sometimes other circuits are affected. For example, some pools share the same pump for the pool and spa, so when the pool is toggled on the spa must be toggled off. Unfortunately the IntelliCenter system doesn't update its internal status at any predictable rate, so the data on the screen can be wrong immediately after toggling a circuit until the next periodic update runs. If you know of a reliable way around this, please open a pull request! + +## Libraries + +This uses a Node.JS library I created for interfacing with IntelliCenter controllers over the network: [node-intellicenter](https://github.com/parnic/node-intellicenter), so feel free to check that out for more information. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..86c466c --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,8 @@ +import eslint from "@eslint/js"; + +export default [ + eslint.configs.recommended, + { + ignores: ["eslint.config.mjs"] + } +]; diff --git a/intellicenter.css b/intellicenter.css new file mode 100644 index 0000000..c1a77c3 --- /dev/null +++ b/intellicenter.css @@ -0,0 +1,165 @@ +.MMM-IntelliCenter table.colored .cold-temp { + color: #bcddff; +} + +.MMM-IntelliCenter table.colored .hot-temp { + color: #ff8e99; +} + +.MMM-IntelliCenter td { + width: 33%; +} + +.MMM-IntelliCenter .control { + background: #000; + border: 1px solid #6c757d; + font-size: 0.8rem; + color: #fff; + display: block; + text-align: center; + line-height: 1.5; + transition: + color 0.15s ease-in-out, + background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, + box-shadow 0.15s ease-in-out; + box-sizing: border-box; + position: relative; + width: 80%; + height: 5rem; + margin: auto; + font-weight: bold; + user-select: none; + cursor: none; + outline: none; +} + +.MMM-IntelliCenter .control::after { + padding-bottom: 100%; + content: ""; + display: block; +} + +.MMM-IntelliCenter .content { + position: absolute; + width: 90%; + height: 90%; + left: 0; + top: 0; + padding: 5%; + display: flex; + justify-content: center; + align-items: center; +} + +.MMM-IntelliCenter .control-on { + background: #28a745 !important; + border-color: #28a745 !important; +} + +.MMM-IntelliCenter .control-off { + background: transparent !important; + border-color: #6c757d !important; +} + +.MMM-IntelliCenter .temperature-container { + font-size: 0.9rem; + font-weight: bold; + color: #fff; + text-align: center; + line-height: 1; + border: 1px solid #6c757d; + width: 80%; + margin: auto; +} + +.MMM-IntelliCenter .temperature-label { + height: 0; + transform: translateY(-0.5em); +} + +.MMM-IntelliCenter .temperature { + background: #000; + border: 0 solid #6c757d; + color: #fff; + position: relative; + width: 80%; + height: 2.45rem; + margin: auto; + font-weight: bold; + user-select: none; + cursor: none; + outline: none; +} + +.MMM-IntelliCenter .vertical { + display: inline-block; + width: 20%; + height: 0.7em; + transform: rotate(-90deg); + box-shadow: inset 0 0 3px #ccc; +} + +.MMM-IntelliCenter .progress-bar { + box-shadow: inset 0 0 3px rgb(100 100 100 / 60%); + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #fff; + transition: width 0.6s ease; +} + +.MMM-IntelliCenter .progress-bar-success { + background-color: #5cb85c; +} + +.MMM-IntelliCenter .progress-bar-warning { + background-color: #ffc107; +} + +.MMM-IntelliCenter .progress-bar-danger { + background-color: #dc3545; +} + +.MMM-IntelliCenter .text-center { + text-align: center; +} + +.MMM-IntelliCenter .container { + display: grid; +} + +.MMM-IntelliCenter .base-content, +.overlay { + grid-area: 1 / 1; +} + +.MMM-IntelliCenter .overlay { + z-index: 9; +} + +.MMM-IntelliCenter .reconnecting { + text-align: center; + align-items: center; + display: grid; +} + +.MMM-IntelliCenter .margin-auto { + margin: auto; +} + +.MMM-IntelliCenter .bg-blur { + border-radius: 10px; + padding: 18%; + background: #fff6; + color: white; + backdrop-filter: blur(4px); +} + +.MMM-IntelliCenter .d-none { + display: none !important; +} diff --git a/node_helper.js b/node_helper.js new file mode 100644 index 0000000..763f5d3 --- /dev/null +++ b/node_helper.js @@ -0,0 +1,283 @@ +/* global module require clearInterval clearTimeout setTimeout setInterval config */ + +var NodeHelper = require("node_helper"); + +let FindUnits; +let Unit; +import("node-intellicenter").then((x) => { + FindUnits = x.FindUnits; + Unit = x.Unit; +}); +let messages; +import("node-intellicenter/messages").then((x) => { + messages = x.messages; +}); +const Log = require("logger"); + +const reconnectDelayMs = 10 * 1000; +const unitFinderTimeoutMs = 5 * 1000; +let foundUnit = false; +const poolData = {}; +let refreshTimer; +let unitFinderRetry; +let unitReconnectTimer; + +module.exports = NodeHelper.create({ + setCircuit(circuitState) { + this.setCircuitState(circuitState, (poolStatus) => { + this.sendSocketNotification("INTELLICENTER_CIRCUIT_DONE", { + circuitState, + status: poolStatus + }); + }); + }, + + setHeatpoint(heatpoint) { + this.setHeatpointState(heatpoint, (poolStatus) => { + this.sendSocketNotification("INTELLICENTER_HEATPOINT_DONE", { + heatpoint, + status: poolStatus + }); + }); + }, + + setHeatstate(heatstate) { + this.setHeatstateState(heatstate, (poolStatus) => { + this.sendSocketNotification("INTELLICENTER_HEATSTATE_DONE", { + heatstate, + status: poolStatus + }); + }); + }, + + setLightcmd(lightCmd) { + this.setLights(lightCmd, (poolStatus) => { + this.sendSocketNotification("INTELLICENTER_LIGHTCMD_DONE", { + lightCmd, + status: poolStatus + }); + }); + }, + + notifyReconnecting() { + this.sendSocketNotification("INTELLICENTER_RECONNECTING"); + }, + + socketNotificationReceived(notification, payload) { + if (notification === "INTELLICENTER_CONFIG") { + if (!this.config) { + this.config = payload; + this.connect( + (status) => { + this.sendSocketNotification("INTELLICENTER_RESULT", status); + }, + () => { + this.notifyReconnecting(); + } + ); + } else if (poolData.status) { + this.sendSocketNotification("INTELLICENTER_RESULT", poolData); + } + // If we don't have a status yet, assume the initial connection is still in progress and this socket notification will be delivered when setup is done + } + if (notification === "INTELLICENTER_CIRCUIT") { + this.setCircuit(payload); + } + if (notification === "INTELLICENTER_HEATPOINT") { + this.setHeatpoint(payload); + } + if (notification === "INTELLICENTER_HEATSTATE") { + this.setHeatstate(payload); + } + if (notification === "INTELLICENTER_LIGHTCMD") { + this.setLightcmd(payload); + } + }, + + resetFoundUnit() { + foundUnit = null; + if (refreshTimer) { + clearInterval(refreshTimer); + refreshTimer = null; + } + if (unitFinderRetry) { + clearInterval(unitFinderRetry); + unitFinderRetry = null; + } + if (unitReconnectTimer) { + clearTimeout(unitReconnectTimer); + unitReconnectTimer = null; + } + }, + + setupUnit(cb, reconnectCb) { + Log.info("[MMM-IntelliCenter] initial connection to unit..."); + + foundUnit + .on("error", (e) => { + Log.error( + `[MMM-IntelliCenter] error in unit connection. restarting the connection process in ${reconnectDelayMs / 1000} seconds` + ); + Log.error(e); + + reconnectCb(); + this.resetFoundUnit(); + unitReconnectTimer = setTimeout(() => { + this.connect(cb, reconnectCb); + }, reconnectDelayMs); + }) + .on("close", () => { + Log.error( + `[MMM-IntelliCenter] unit connection closed unexpectedly. restarting the connection process in ${reconnectDelayMs / 1000} seconds` + ); + + reconnectCb(); + this.resetFoundUnit(); + unitReconnectTimer = setTimeout(() => { + this.connect(cb, reconnectCb); + }, reconnectDelayMs); + }) + .once("connected", () => { + Log.info( + "[MMM-IntelliCenter] logged into unit. getting basic configuration..." + ); + foundUnit.send(new messages.GetSystemInformation()).then(() => { + Log.info("[MMM-IntelliCenter] got it!"); + }); + }) + .once("controllerConfig", (config) => { + Log.info( + "[MMM-IntelliCenter] configuration received. adding client..." + ); + poolData.controllerConfig = config; + poolData.degStr = this.config.degC ? "C" : "F"; + foundUnit.addClient(1234); + }) + .once("addClient", () => { + Log.info( + "[MMM-IntelliCenter] client added successfully and listening for changes" + ); + foundUnit.getPoolStatus(); + // Connection seems to time out every 10 minutes without some sort of request made + refreshTimer = setInterval( + () => { + foundUnit.pingServer(); + }, + 1 * 60 * 1000 + ); + }) + .on("poolStatus", (status) => { + Log.info("[MMM-IntelliCenter] received pool status update"); + poolData.status = status; + cb(poolData); + }); + + foundUnit.connect(); + }, + + findServer(cb, reconnectCb) { + Log.info("[MMM-IntelliCenter] starting search for local units"); + const finder = new FindUnits(this.config.multicastInterface); + finder + .on("serverFound", (server) => { + finder.close(); + Log.info( + `[MMM-IntelliCenter] local unit found at ${server.addressStr}:${server.port}` + ); + + foundUnit = new Unit(server.addressStr, server.port); + this.setupUnit(cb, reconnectCb); + + clearInterval(unitFinderRetry); + unitFinderRetry = null; + }) + .on("error", (e) => { + Log.error( + `[MMM-IntelliCenter] error trying to find a server. scheduling a retry in ${reconnectDelayMs / 1000} seconds` + ); + Log.error(e); + this.resetFoundUnit(); + setTimeout(() => { + this.findServer(cb); + }, reconnectDelayMs); + }); + + finder.search(); + unitFinderRetry = setInterval(() => { + Log.info( + `[MMM-IntelliCenter] didn't find any units within ${unitFinderTimeoutMs / 1000} seconds, trying again...` + ); + finder.search(); + }, unitFinderTimeoutMs); + }, + + connect(cb, reconnectCb) { + if ( + !foundUnit && + typeof config !== "undefined" && + this.config.serverAddress && + this.config.serverPort + ) { + Log.info( + `[MMM-IntelliCenter] connecting directly to configured unit at ${this.config.serverAddress}:${this.config.serverPort}` + ); + foundUnit = new Unit(this.config.serverAddress, this.config.serverPort); + } + + if (foundUnit) { + this.setupUnit(cb, reconnectCb); + } else { + this.findServer(cb, reconnectCb); + } + }, + + setCircuitState(circuitState, cb) { + if (!foundUnit) { + cb(); + return; + } + + Log.info( + `[MMM-IntelliCenter] setting circuit ${circuitState.id} to ${circuitState.state}` + ); + foundUnit.setCircuitState(0, circuitState.id, circuitState.state); + foundUnit.getPoolStatus(); + }, + + setHeatpointState(heatpoint, cb) { + if (!foundUnit) { + cb(); + return; + } + + Log.info( + `[MMM-IntelliCenter] setting heatpoint for body ${heatpoint.body} to ${heatpoint.temperature} deg` + ); + foundUnit.setSetPoint(0, heatpoint.body, heatpoint.temperature); + foundUnit.getPoolStatus(); + }, + + setHeatstateState(heatstate, cb) { + if (!foundUnit) { + cb(); + return; + } + + Log.info( + `[MMM-IntelliCenter] setting heat state for body ${heatstate.body} to ${heatstate.state}` + ); + foundUnit.setHeatMode(0, heatstate.body, heatstate.state); + foundUnit.getPoolStatus(); + }, + + setLights(lightCmd, cb) { + if (!foundUnit) { + cb(); + return; + } + + Log.info(`[MMM-IntelliCenter] sending light command ${lightCmd}`); + foundUnit.sendLightCommand(0, lightCmd); + foundUnit.getPoolStatus(); + } +}); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ddf6258 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2413 @@ +{ + "name": "mmm-intellicenter", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mmm-intellicenter", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "node-intellicenter": "^0.0.2" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "eslint": "^9.17.0", + "prettier": "^3.4.2", + "stylelint": "^16.12.0", + "stylelint-config-standard": "^36.0.1", + "stylelint-prettier": "^5.0.2" + } + }, + "../../../node-intellicenter": { + "version": "0.0.2", + "extraneous": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "uuid": "^11.0.3", + "ws": "^8.18.0" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "@types/debug": "^4.1.12", + "@types/ws": "^8.5.13", + "eslint": "^9.17.0", + "prettier": "3.4.2", + "supports-color": "^10.0.0", + "typescript": "^5.7.2", + "typescript-eslint": "^8.19.0" + }, + "optionalDependencies": { + "bufferutil": "^4.0.9" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", + "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@dual-bundle/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.5", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", + "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", + "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bufferutil": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", + "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-functions-list": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", + "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12 || >=16" + } + }, + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", + "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.17.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, + "license": "ISC" + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", + "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", + "dev": true, + "license": "MIT" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-intellicenter": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/node-intellicenter/-/node-intellicenter-0.0.2.tgz", + "integrity": "sha512-znpXLoQsDmOdm+vy4vUMwqSkN+kmIISlCbhDE5KmoY1Js4d+jObkmmYo2VHoUPeCFGFBE3vdYw0Nn80484EfVw==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "uuid": "^11.0.3", + "ws": "^8.18.0" + }, + "optionalDependencies": { + "bufferutil": "^4.0.9" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss-safe-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", + "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylelint": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.12.0.tgz", + "integrity": "sha512-F8zZ3L/rBpuoBZRvI4JVT20ZanPLXfQLzMOZg1tzPflRVh9mKpOZ8qcSIhh1my3FjAjZWG4T2POwGnmn6a6hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2", + "@csstools/selector-specificity": "^5.0.0", + "@dual-bundle/import-meta-resolve": "^4.1.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^9.0.0", + "css-functions-list": "^3.2.3", + "css-tree": "^3.0.1", + "debug": "^4.3.7", + "fast-glob": "^3.3.2", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^9.1.0", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^6.0.2", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.35.0", + "mathml-tag-names": "^2.1.3", + "meow": "^13.2.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.49", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-safe-parser": "^7.0.1", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "supports-hyperlinks": "^3.1.0", + "svg-tags": "^1.0.0", + "table": "^6.9.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", + "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.1.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "36.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz", + "integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "dependencies": { + "stylelint-config-recommended": "^14.0.1" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.1.0" + } + }, + "node_modules/stylelint-prettier": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.2.tgz", + "integrity": "sha512-qJ+BN+1T2ZcKz9WIrv0x+eFGHzSUnXfXd5gL///T6XoJvr3D8/ztzz2fhtmXef7Vb8P33zBXmLTTveByr0nwBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "prettier": ">=3.0.0", + "stylelint": ">=16.0.0" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/stylelint/node_modules/flat-cache": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.3.1", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/stylelint/node_modules/ignore": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", + "integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylelint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", + "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7194bf0 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "mmm-intellicenter", + "version": "1.0.0", + "description": "Show data from Pentair IntelliCenter systems", + "main": "MMM-IntelliCenter.js", + "author": "parnic", + "repository": "https://github.com/parnic/MMM-IntelliCenter.git", + "license": "MIT", + "dependencies": { + "node-intellicenter": "^0.0.2" + }, + "devDependencies": { + "@eslint/js": "^9.17.0", + "eslint": "^9.17.0", + "prettier": "^3.4.2", + "stylelint": "^16.12.0", + "stylelint-config-standard": "^36.0.1", + "stylelint-prettier": "^5.0.2" + }, + "scripts": { + "lint": "eslint . && stylelint intellicenter.css && prettier . --check", + "lint:fix": "eslint . --fix && stylelint intellicenter.css --fix && prettier . --write" + } +} diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..b28f3e815097ce353c30486bfb29b5c4658b4990 GIT binary patch literal 39262 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 z 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 literal 0 HcmV?d00001