From d432e183a6e6f4d6715aaaf3252acfe590ff136f Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 18 May 2025 20:24:36 +0100 Subject: [PATCH 01/29] downgrade bluetooth packages to fix child bridge restart issues --- CHANGELOG.md | 8 ++ lib/platform.js | 1 + package-lock.json | 250 ++++++++++++++++++++++++++-------------------- package.json | 4 +- 4 files changed, 155 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b3359ed..63c9be50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ This project tries to adhere to [Semantic Versioning](http://semver.org/). In pr - `MINOR` version when a new device type is added, or when a new feature is added that is backwards-compatible - `PATCH` version when backwards-compatible bug fixes are implemented +## v11.0.1 (2025-05-18) + +⚠️ This plugin no longer officially supports Node 18. Please update to Node 20 or 22. + +### Changed + +- downgrade bluetooth packages to fix child bridge restart issues + ## v11.0.0 (2025-05-18) ⚠️ This plugin no longer officially supports Node 18. Please update to Node 20 or 22. diff --git a/lib/platform.js b/lib/platform.js index 3e752ea2..254ea5ad 100644 --- a/lib/platform.js +++ b/lib/platform.js @@ -790,6 +790,7 @@ export default class { this.lanClient.close() } catch (err) { // No need to show errors at this point + this.log.error('***** %s. *****', parseError(err)) } } diff --git a/package-lock.json b/package-lock.json index 676878a4..9a9b7260 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,8 +43,8 @@ "node": "^20.19.2 || ^22.15.1" }, "optionalDependencies": { - "@stoprocent/bluetooth-hci-socket": "^2.2.1", - "@stoprocent/noble": "^2.3.0" + "@stoprocent/bluetooth-hci-socket": "^1.5.2", + "@stoprocent/noble": "^1.19.1" } }, "node_modules/@antfu/eslint-config": { @@ -763,30 +763,30 @@ } }, "node_modules/@serialport/bindings-cpp": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/bindings-cpp/-/bindings-cpp-13.0.0.tgz", - "integrity": "sha512-r25o4Bk/vaO1LyUfY/ulR6hCg/aWiN6Wo2ljVlb4Pj5bqWGcSRC4Vse4a9AcapuAu/FeBzHCbKMvRQeCuKjzIQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@serialport/bindings-cpp/-/bindings-cpp-12.0.1.tgz", + "integrity": "sha512-r2XOwY2dDvbW7dKqSPIk2gzsr6M6Qpe9+/Ngs94fNaNlcTRCV02PfaoDmRgcubpNVVcLATlxSxPTIDw12dbKOg==", "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { "@serialport/bindings-interface": "1.2.2", - "@serialport/parser-readline": "12.0.0", - "debug": "4.4.0", - "node-addon-api": "8.3.0", - "node-gyp-build": "4.8.4" + "@serialport/parser-readline": "11.0.0", + "debug": "4.3.4", + "node-addon-api": "7.0.0", + "node-gyp-build": "4.6.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=16.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-delimiter": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-12.0.0.tgz", - "integrity": "sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-11.0.0.tgz", + "integrity": "sha512-aZLJhlRTjSmEwllLG7S4J8s8ctRAS0cbvCpO87smLvl3e4BgzbVgF6Z6zaJd3Aji2uSiYgfedCdNc4L6W+1E2g==", "license": "MIT", "optional": true, "engines": { @@ -797,13 +797,13 @@ } }, "node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-readline": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-12.0.0.tgz", - "integrity": "sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-11.0.0.tgz", + "integrity": "sha512-rRAivhRkT3YO28WjmmG4FQX6L+KMb5/ikhyylRfzWPw0nSXy97+u07peS9CbHqaNvJkMhH1locp2H36aGMOEIA==", "license": "MIT", "optional": true, "dependencies": { - "@serialport/parser-delimiter": "12.0.0" + "@serialport/parser-delimiter": "11.0.0" }, "engines": { "node": ">=12.0.0" @@ -813,13 +813,13 @@ } }, "node_modules/@serialport/bindings-cpp/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "license": "MIT", "optional": true, "dependencies": { - "ms": "^2.1.3" + "ms": "2.1.2" }, "engines": { "node": ">=6.0" @@ -830,14 +830,30 @@ } } }, + "node_modules/@serialport/bindings-cpp/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT", + "optional": true + }, "node_modules/@serialport/bindings-cpp/node_modules/node-addon-api": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz", - "integrity": "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", + "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==", + "license": "MIT", + "optional": true + }, + "node_modules/@serialport/bindings-cpp/node_modules/node-gyp-build": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", "license": "MIT", "optional": true, - "engines": { - "node": "^18 || ^20 || >= 21" + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, "node_modules/@serialport/bindings-interface": { @@ -851,61 +867,61 @@ } }, "node_modules/@serialport/parser-byte-length": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-13.0.0.tgz", - "integrity": "sha512-32yvqeTAqJzAEtX5zCrN1Mej56GJ5h/cVFsCDPbF9S1ZSC9FWjOqNAgtByseHfFTSTs/4ZBQZZcZBpolt8sUng==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-12.0.0.tgz", + "integrity": "sha512-0ei0txFAj+s6FTiCJFBJ1T2hpKkX8Md0Pu6dqMrYoirjPskDLJRgZGLqoy3/lnU1bkvHpnJO+9oJ3PB9v8rNlg==", "license": "MIT", "optional": true, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/parser-cctalk": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-13.0.0.tgz", - "integrity": "sha512-RErAe57g9gvnlieVYGIn1xymb1bzNXb2QtUQd14FpmbQQYlcrmuRnJwKa1BgTCujoCkhtaTtgHlbBWOxm8U2uA==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-12.0.0.tgz", + "integrity": "sha512-0PfLzO9t2X5ufKuBO34DQKLXrCCqS9xz2D0pfuaLNeTkyGUBv426zxoMf3rsMRodDOZNbFblu3Ae84MOQXjnZw==", "license": "MIT", "optional": true, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/parser-delimiter": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-13.0.0.tgz", - "integrity": "sha512-Qqyb0FX1avs3XabQqNaZSivyVbl/yl0jywImp7ePvfZKLwx7jBZjvL+Hawt9wIG6tfq6zbFM24vzCCK7REMUig==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-12.0.0.tgz", + "integrity": "sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==", "license": "MIT", "optional": true, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/parser-inter-byte-timeout": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-13.0.0.tgz", - "integrity": "sha512-a0w0WecTW7bD2YHWrpTz1uyiWA2fDNym0kjmPeNSwZ2XCP+JbirZt31l43m2ey6qXItTYVuQBthm75sPVeHnGA==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-12.0.0.tgz", + "integrity": "sha512-GnCh8K0NAESfhCuXAt+FfBRz1Cf9CzIgXfp7SdMgXwrtuUnCC/yuRTUFWRvuzhYKoAo1TL0hhUo77SFHUH1T/w==", "license": "MIT", "optional": true, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/parser-packet-length": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-packet-length/-/parser-packet-length-13.0.0.tgz", - "integrity": "sha512-60ZDDIqYRi0Xs2SPZUo4Jr5LLIjtb+rvzPKMJCohrO6tAqSDponcNpcB1O4W21mKTxYjqInSz+eMrtk0LLfZIg==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-packet-length/-/parser-packet-length-12.0.0.tgz", + "integrity": "sha512-p1hiCRqvGHHLCN/8ZiPUY/G0zrxd7gtZs251n+cfNTn+87rwcdUeu9Dps3Aadx30/sOGGFL6brIRGK4l/t7MuQ==", "license": "MIT", "optional": true, "engines": { @@ -913,98 +929,98 @@ } }, "node_modules/@serialport/parser-readline": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-13.0.0.tgz", - "integrity": "sha512-dov3zYoyf0dt1Sudd1q42VVYQ4WlliF0MYvAMA3MOyiU1IeG4hl0J6buBA2w4gl3DOCC05tGgLDN/3yIL81gsA==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-12.0.0.tgz", + "integrity": "sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==", "license": "MIT", "optional": true, "dependencies": { - "@serialport/parser-delimiter": "13.0.0" + "@serialport/parser-delimiter": "12.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/parser-ready": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-13.0.0.tgz", - "integrity": "sha512-JNUQA+y2Rfs4bU+cGYNqOPnNMAcayhhW+XJZihSLQXOHcZsFnOa2F9YtMg9VXRWIcnHldHYtisp62Etjlw24bw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-12.0.0.tgz", + "integrity": "sha512-ygDwj3O4SDpZlbrRUraoXIoIqb8sM7aMKryGjYTIF0JRnKeB1ys8+wIp0RFMdFbO62YriUDextHB5Um5cKFSWg==", "license": "MIT", "optional": true, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/parser-regex": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-13.0.0.tgz", - "integrity": "sha512-m7HpIf56G5XcuDdA3DB34Z0pJiwxNRakThEHjSa4mG05OnWYv0IG8l2oUyYfuGMowQWaVnQ+8r+brlPxGVH+eA==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-12.0.0.tgz", + "integrity": "sha512-dCAVh4P/pZrLcPv9NJ2mvPRBg64L5jXuiRxIlyxxdZGH4WubwXVXY/kBTihQmiAMPxbT3yshSX8f2+feqWsxqA==", "license": "MIT", "optional": true, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/parser-slip-encoder": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-slip-encoder/-/parser-slip-encoder-13.0.0.tgz", - "integrity": "sha512-fUHZEExm6izJ7rg0A1yjXwu4sOzeBkPAjDZPfb+XQoqgtKAk+s+HfICiYn7N2QU9gyaeCO8VKgWwi+b/DowYOg==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-slip-encoder/-/parser-slip-encoder-12.0.0.tgz", + "integrity": "sha512-0APxDGR9YvJXTRfY+uRGhzOhTpU5akSH183RUcwzN7QXh8/1jwFsFLCu0grmAUfi+fItCkR+Xr1TcNJLR13VNA==", "license": "MIT", "optional": true, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/parser-spacepacket": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/parser-spacepacket/-/parser-spacepacket-13.0.0.tgz", - "integrity": "sha512-DoXJ3mFYmyD8X/8931agJvrBPxqTaYDsPoly9/cwQSeh/q4EjQND9ySXBxpWz5WcpyCU4jOuusqCSAPsbB30Eg==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-spacepacket/-/parser-spacepacket-12.0.0.tgz", + "integrity": "sha512-dozONxhPC/78pntuxpz/NOtVps8qIc/UZzdc/LuPvVsqCoJXiRxOg6ZtCP/W58iibJDKPZPAWPGYeZt9DJxI+Q==", "license": "MIT", "optional": true, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/stream": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-13.0.0.tgz", - "integrity": "sha512-F7xLJKsjGo2WuEWMSEO1SimRcOA+WtWICsY13r0ahx8s2SecPQH06338g28OT7cW7uRXI7oEQAk62qh5gHJW3g==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-12.0.0.tgz", + "integrity": "sha512-9On64rhzuqKdOQyiYLYv2lQOh3TZU/D3+IWCR5gk0alPel2nwpp4YwDEGiUBfrQZEdQ6xww0PWkzqth4wqwX3Q==", "license": "MIT", "optional": true, "dependencies": { "@serialport/bindings-interface": "1.2.2", - "debug": "4.4.0" + "debug": "4.3.4" }, "engines": { - "node": ">=20.0.0" + "node": ">=12.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/@serialport/stream/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "license": "MIT", "optional": true, "dependencies": { - "ms": "^2.1.3" + "ms": "2.1.2" }, "engines": { "node": ">=6.0" @@ -1015,10 +1031,17 @@ } } }, + "node_modules/@serialport/stream/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT", + "optional": true + }, "node_modules/@stoprocent/bluetooth-hci-socket": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@stoprocent/bluetooth-hci-socket/-/bluetooth-hci-socket-2.2.1.tgz", - "integrity": "sha512-qMyzUcaGTZqELQvuKXebpxwE+DT5Tl4CV32D1tLoR6x1i2FKR5AhfCCI5SfY11lHjXTSEtW1y8BaxUukBpL4Og==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@stoprocent/bluetooth-hci-socket/-/bluetooth-hci-socket-1.5.2.tgz", + "integrity": "sha512-O1xOpI5Xf5/VzGlf2Gm9sxrERIKXH0b9h/3BY26xPOAbOk7u6sC+m15cYyUc4GJmcL7UElSSF3QHw+qzvtvQSA==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -1032,24 +1055,25 @@ "dependencies": { "async": "^3.2.6", "debug": "^4.3.7", - "node-addon-api": "^8.3.1", - "node-gyp-build": "^4.8.4", + "node-addon-api": "^8.1.0", + "node-gyp-build": "^4.8.1", "patch-package": "^8.0.0", - "serialport": "^13.0.0" + "serialport": "^12.0.0" }, "optionalDependencies": { "usb": "^2.14.0" } }, "node_modules/@stoprocent/noble": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@stoprocent/noble/-/noble-2.3.0.tgz", - "integrity": "sha512-8A5gYYIJ0+YzQnG3uDQ0r49rLqxSs8WOzqRTHqhdpNht4JOUKEkpEVsw+8ej/V7QKgqw9I3vYFe5VV8gLYpmcw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@stoprocent/noble/-/noble-1.19.1.tgz", + "integrity": "sha512-hgtb7WC1na1HSoJ51IVJZEq8f0cnlI4M+F5tjPcadQV06NPV0V8UoUM57pRZOpYn54qOPccOBc2E+IrpJOn2gQ==", "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { "debug": "^4.3.7", + "napi-thread-safe-callback": "^0.0.6", "node-addon-api": "^8.1.0", "node-gyp-build": "^4.8.1" }, @@ -1057,7 +1081,7 @@ "node": ">=14" }, "optionalDependencies": { - "@stoprocent/bluetooth-hci-socket": "^2.2.1" + "@stoprocent/bluetooth-hci-socket": "^1.5.2" } }, "node_modules/@stylistic/eslint-plugin": { @@ -5413,6 +5437,13 @@ "url": "https://opencollective.com/napi-postinstall" } }, + "node_modules/napi-thread-safe-callback": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/napi-thread-safe-callback/-/napi-thread-safe-callback-0.0.6.tgz", + "integrity": "sha512-X7uHCOCdY4u0yamDxDrv3jF2NtYc8A1nvPzBQgvpoSX+WB3jAe2cVNsY448V1ucq7Whf9Wdy02HEUoLW5rJKWg==", + "license": "ISC", + "optional": true + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6200,42 +6231,42 @@ } }, "node_modules/serialport": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/serialport/-/serialport-13.0.0.tgz", - "integrity": "sha512-PHpnTd8isMGPfFTZNCzOZp9m4mAJSNWle9Jxu6BPTcWq7YXl5qN7tp8Sgn0h+WIGcD6JFz5QDgixC2s4VW7vzg==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-12.0.0.tgz", + "integrity": "sha512-AmH3D9hHPFmnF/oq/rvigfiAouAKyK/TjnrkwZRYSFZxNggJxwvbAbfYrLeuvq7ktUdhuHdVdSjj852Z55R+uA==", "license": "MIT", "optional": true, "dependencies": { "@serialport/binding-mock": "10.2.2", - "@serialport/bindings-cpp": "13.0.0", - "@serialport/parser-byte-length": "13.0.0", - "@serialport/parser-cctalk": "13.0.0", - "@serialport/parser-delimiter": "13.0.0", - "@serialport/parser-inter-byte-timeout": "13.0.0", - "@serialport/parser-packet-length": "13.0.0", - "@serialport/parser-readline": "13.0.0", - "@serialport/parser-ready": "13.0.0", - "@serialport/parser-regex": "13.0.0", - "@serialport/parser-slip-encoder": "13.0.0", - "@serialport/parser-spacepacket": "13.0.0", - "@serialport/stream": "13.0.0", - "debug": "4.4.0" + "@serialport/bindings-cpp": "12.0.1", + "@serialport/parser-byte-length": "12.0.0", + "@serialport/parser-cctalk": "12.0.0", + "@serialport/parser-delimiter": "12.0.0", + "@serialport/parser-inter-byte-timeout": "12.0.0", + "@serialport/parser-packet-length": "12.0.0", + "@serialport/parser-readline": "12.0.0", + "@serialport/parser-ready": "12.0.0", + "@serialport/parser-regex": "12.0.0", + "@serialport/parser-slip-encoder": "12.0.0", + "@serialport/parser-spacepacket": "12.0.0", + "@serialport/stream": "12.0.0", + "debug": "4.3.4" }, "engines": { - "node": ">=20.0.0" + "node": ">=16.0.0" }, "funding": { "url": "https://opencollective.com/serialport/donate" } }, "node_modules/serialport/node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "license": "MIT", "optional": true, "dependencies": { - "ms": "^2.1.3" + "ms": "2.1.2" }, "engines": { "node": ">=6.0" @@ -6246,6 +6277,13 @@ } } }, + "node_modules/serialport/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT", + "optional": true + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", diff --git a/package.json b/package.json index 8934e790..4c89083c 100644 --- a/package.json +++ b/package.json @@ -64,8 +64,8 @@ "pem": "^1.14.8" }, "optionalDependencies": { - "@stoprocent/bluetooth-hci-socket": "^2.2.1", - "@stoprocent/noble": "^2.3.0" + "@stoprocent/bluetooth-hci-socket": "^1.5.2", + "@stoprocent/noble": "^1.19.1" }, "devDependencies": { "@antfu/eslint-config": "^4.13.1" From 35ff21cdc7a086b30d4b39dc5ce6386893ace944 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 18 May 2025 20:24:56 +0100 Subject: [PATCH 02/29] 11.0.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9a9b7260..51664b8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.0.0", + "version": "11.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.0.0", + "version": "11.0.1", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 4c89083c..9d745afe 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@homebridge-plugins/homebridge-govee", "alias": "Govee", "type": "module", - "version": "11.0.0", + "version": "11.0.1", "description": "Homebridge plugin to integrate Govee devices into HomeKit.", "author": { "name": "bwp91", From f44005c33845b3abaea445041149aafac6b8da02 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Tue, 20 May 2025 23:04:12 +0100 Subject: [PATCH 03/29] enable logging for unknown scene codes for the ice maker --- CHANGELOG.md | 8 +++++++- lib/device/ice-maker-H7172.js | 2 +- package-lock.json | 36 ++++++++++++----------------------- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63c9be50..c646e8d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,18 @@ This project tries to adhere to [Semantic Versioning](http://semver.org/). In pr - `MINOR` version when a new device type is added, or when a new feature is added that is backwards-compatible - `PATCH` version when backwards-compatible bug fixes are implemented -## v11.0.1 (2025-05-18) +## v11.0.2 (2025-05-20) ⚠️ This plugin no longer officially supports Node 18. Please update to Node 20 or 22. ### Changed +- enable logging for unknown scene codes for the ice maker + +## v11.0.1 (2025-05-18) + +### Changed + - downgrade bluetooth packages to fix child bridge restart issues ## v11.0.0 (2025-05-18) diff --git a/lib/device/ice-maker-H7172.js b/lib/device/ice-maker-H7172.js index 53fb1709..f82f7298 100644 --- a/lib/device/ice-maker-H7172.js +++ b/lib/device/ice-maker-H7172.js @@ -38,7 +38,7 @@ export default class { switch (deviceFunction) { default: - this.accessory.logDebugWarn(`${platformLang.newScene}: [${command}] [${hexString}]`) + this.accessory.logWarn(`${platformLang.newScene}: [${command}] [${hexString}]`) break } }) diff --git a/package-lock.json b/package-lock.json index 51664b8c..df493667 100644 --- a/package-lock.json +++ b/package-lock.json @@ -284,13 +284,12 @@ } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.50.1", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.50.1.tgz", - "integrity": "sha512-fas3qe1hw38JJgU/0m5sDpcrbZGysBeZcMwW5Ws9brYxY64MJyWLXRZCj18keTycT1LFTrFXdSNMS+GRVaU6Hw==", + "version": "0.50.2", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.50.2.tgz", + "integrity": "sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint": "^9.6.1", "@types/estree": "^1.0.6", "@typescript-eslint/types": "^8.11.0", "comment-parser": "1.4.1", @@ -1125,17 +1124,6 @@ "@types/ms": "*" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, "node_modules/@types/estree": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", @@ -1168,9 +1156,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", - "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", + "version": "22.15.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.20.tgz", + "integrity": "sha512-A6BohGFRGHAscJsTslDCA9JG7qSJr/DWUvrvY8yi9IgnGtMxCyat7vvQ//MFa0DnLsyuS3wYTpLdw4Hf+Q5JXw==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -3626,9 +3614,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6502,9 +6490,9 @@ } }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, "license": "MIT", "engines": { From 303eaa63080bee3c578e190c67121bebbf8757fc Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Tue, 20 May 2025 23:04:41 +0100 Subject: [PATCH 04/29] 11.0.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index df493667..909a3688 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.0.1", + "version": "11.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.0.1", + "version": "11.0.2", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 9d745afe..ccc966f1 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@homebridge-plugins/homebridge-govee", "alias": "Govee", "type": "module", - "version": "11.0.1", + "version": "11.0.2", "description": "Homebridge plugin to integrate Govee devices into HomeKit.", "author": { "name": "bwp91", From 27c5a61193b134653d075b26637195ef89fded70 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 12:12:49 +0100 Subject: [PATCH 05/29] work-in-progress support for ice-makers --- CHANGELOG.md | 8 ++--- lib/device/ice-maker-H7172.js | 65 +++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c646e8d0..2f91b8f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,11 @@ All notable changes to homebridge-govee will be documented in this file. -This project tries to adhere to [Semantic Versioning](http://semver.org/). In practice, this means that the version number will be incremented based on the following: +## v11.1.0 (Unreleased) -- `MAJOR` version when a minimum supported version of `homebridge` or `node` is increased to a new major version, or when a breaking change is made to the plugin config -- `MINOR` version when a new device type is added, or when a new feature is added that is backwards-compatible -- `PATCH` version when backwards-compatible bug fixes are implemented +### Notable Changes + +- work-in-progress support for ice-makers ## v11.0.2 (2025-05-20) diff --git a/lib/device/ice-maker-H7172.js b/lib/device/ice-maker-H7172.js index f82f7298..1b98366c 100644 --- a/lib/device/ice-maker-H7172.js +++ b/lib/device/ice-maker-H7172.js @@ -1,4 +1,4 @@ -import { base64ToHex, getTwoItemPosition, hexToTwoItems } from '../utils/functions.js' +import { base64ToHex, getTwoItemPosition, hexToTwoItems, parseError } from '../utils/functions.js' import platformLang from '../utils/lang-en.js' export default class { @@ -12,17 +12,60 @@ export default class { // Set up variables from the accessory this.accessory = accessory + // Add the main switch service if it doesn't already exist + this.service = this.accessory.getService(this.hapServ.Switch) + || this.accessory.addService(this.hapServ.Switch) + + // Add the set handler to the lightbulb on/off characteristic + this.service.getCharacteristic(this.hapChar.On).onSet(async (value) => { + await this.internalStateUpdate(value) + }) + this.cacheState = this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off' + // Output the customised options to the log const opts = JSON.stringify({}) platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts) } + async internalStateUpdate(value) { + try { + const newState = value ? 'on' : 'off' + + // Don't continue if the new value is the same as before + if (newState === this.cacheState) { + return + } + + // Send the request to the platform sender function + await this.platform.sendDeviceUpdate(this.accessory, { + cmd: 'ptReal', + value: value ? 'MwUCAAAAAAAAAAAAAAAAAAAAADQ=' : 'MxkAAAAAAAAAAAAAAAAAAAAAACo=', + // value: value ? 'MxkBAAAAAAAAAAAAAAAAAAAAACs=' : 'MxkAAAAAAAAAAAAAAAAAAAAAACo=', // on / off (not working) + }) + + // Cache the new state and log if appropriate + if (this.cacheState !== newState) { + this.cacheState = newState + this.accessory.log(`${platformLang.curState} [${this.cacheState}]`) + } + } catch (err) { + // Catch any errors during the process + this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`) + + // Throw a 'no response' error and set a timeout to revert this after 2 seconds + setTimeout(() => { + this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on') + }, 2000) + throw new this.hapErr(-70402) + } + } + externalUpdate(params) { // Update the active characteristic - if (params.state && params.state !== this.cacheState) { - this.cacheState = params.state - this.accessory.log(`${platformLang.curState} [${this.cacheState}]`) - } + // if (params.state && params.state !== this.cacheState) { + // this.cacheState = params.state + // this.accessory.log(`${platformLang.curState} [${this.cacheState}]`) + // } // Check for some other scene/mode change (params.commands || []).forEach((command) => { @@ -34,9 +77,19 @@ export default class { return } - const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}` + const deviceFunction = `${getTwoItemPosition(hexParts, 1)}${getTwoItemPosition(hexParts, 2)}` switch (deviceFunction) { + case 'aa19': { + // On/Off + const newState = getTwoItemPosition(hexParts, 3) === '01' ? 'on' : 'off' + if (this.cacheState !== newState) { + this.cacheState = newState + this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on') + this.accessory.log(`${platformLang.curState} [${this.cacheState}]`) + } + break + } default: this.accessory.logWarn(`${platformLang.newScene}: [${command}] [${hexString}]`) break From 4379db81cfcac2c837fc07678a74f6e66517f7b9 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 12:13:42 +0100 Subject: [PATCH 06/29] allow exposing a temperature sensor as a thermostat --- CHANGELOG.md | 1 + config.schema.json | 11 ++++++- lib/device/index.js | 4 +-- ...hermo-H5109.js => sensor-thermo-switch.js} | 32 ++++++++++++++++--- lib/device/sensor-thermo.js | 17 +++++++--- lib/platform.js | 10 +++--- lib/utils/constants.js | 2 +- 7 files changed, 57 insertions(+), 20 deletions(-) rename lib/device/{sensor-thermo-H5109.js => sensor-thermo-switch.js} (84%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f91b8f7..e9f9f820 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to homebridge-govee will be documented in this file. ### Notable Changes - work-in-progress support for ice-makers +- allow exposing a temperature sensor as a thermostat ## v11.0.2 (2025-05-20) diff --git a/config.schema.json b/config.schema.json index 3713e6a5..88597d90 100644 --- a/config.schema.json +++ b/config.schema.json @@ -1114,6 +1114,14 @@ "condition": { "functionBody": "return (model.thermoDevices && model.thermoDevices[arrayIndices] && model.thermoDevices[arrayIndices].deviceId && [23,26].includes(model.thermoDevices[arrayIndices].deviceId.length) && !model.thermoDevices[arrayIndices].ignoreDevice);" } + }, + "showExtraSwitch": { + "type": "boolean", + "title": "Show Extra Switch", + "description": "If true, a dummy switch will be added so that the temperature appears as a full icon in the Home app, not in the Climate section.", + "condition": { + "functionBody": "return (model.thermoDevices && model.thermoDevices[arrayIndices] && model.thermoDevices[arrayIndices].deviceId && [23,26].includes(model.thermoDevices[arrayIndices].deviceId.length) && !model.thermoDevices[arrayIndices].ignoreDevice);" + } } } } @@ -1576,7 +1584,8 @@ "thermoDevices[].label", "thermoDevices[].deviceId", "thermoDevices[].ignoreDevice", - "thermoDevices[].lowBattThreshold" + "thermoDevices[].lowBattThreshold", + "thermoDevices[].showExtraSwitch" ] } ] diff --git a/lib/device/index.js b/lib/device/index.js index f62e8e19..1d558df9 100644 --- a/lib/device/index.js +++ b/lib/device/index.js @@ -47,7 +47,7 @@ import deviceSensorLeak from './sensor-leak.js' import deviceSensorMonitor from './sensor-monitor.js' import deviceSensorPresence from './sensor-presence.js' import deviceSensorThermo4 from './sensor-thermo4.js' -import deviceSensorThermoH5109 from './sensor-thermo-H5109.js' +import deviceSensorThermoSwitch from './sensor-thermo-switch.js' import deviceSensorThermo from './sensor-thermo.js' import deviceSwitchDouble from './switch-double.js' import deviceSwitchSingle from './switch-single.js' @@ -107,7 +107,7 @@ export default { deviceSensorMonitor, deviceSensorPresence, deviceSensorThermo, - deviceSensorThermoH5109, + deviceSensorThermoSwitch, deviceSensorThermo4, deviceSwitchDouble, deviceSwitchSingle, diff --git a/lib/device/sensor-thermo-H5109.js b/lib/device/sensor-thermo-switch.js similarity index 84% rename from lib/device/sensor-thermo-H5109.js rename to lib/device/sensor-thermo-switch.js index ab97c241..875b07e6 100644 --- a/lib/device/sensor-thermo-H5109.js +++ b/lib/device/sensor-thermo-switch.js @@ -34,6 +34,16 @@ export default class { this.thermoService = this.accessory.getService(this.hapServ.Thermostat) || this.accessory.addService(this.hapServ.Thermostat) + // Add the battery service if it doesn't already exist + this.battService = this.accessory.getService(this.hapServ.Battery) + || this.accessory.addService(this.hapServ.Battery) + this.cacheBatt = this.battService.getCharacteristic(this.hapChar.BatteryLevel).value + + // Add the humidity service if it doesn't already exist + this.humiService = this.accessory.getService(this.hapServ.HumiditySensor) + || this.accessory.addService(this.hapServ.HumiditySensor) + this.cacheHumi = this.humiService.getCharacteristic(this.hapChar.CurrentRelativeHumidity).value + // Set up thermostat characteristics this.cacheTemp = this.thermoService.getCharacteristic(this.hapChar.CurrentTemperature).value || 20 @@ -63,11 +73,6 @@ export default class { this.updateCache() - // Add the battery service if it doesn't already exist - this.battService = this.accessory.getService(this.hapServ.Battery) - || this.accessory.addService(this.hapServ.Battery) - this.cacheBatt = this.battService.getCharacteristic(this.hapChar.BatteryLevel).value - // Pass the accessory to Fakegato to set up with Eve this.accessory.eveService = new platform.eveService('custom', this.accessory, { log: () => {}, @@ -76,6 +81,7 @@ export default class { // Output the customised options to the log const opts = JSON.stringify({ lowBattThreshold: this.lowBattThreshold, + showExtraSwitch: true, }) platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts) } @@ -135,6 +141,22 @@ export default class { this.updateCache() } } + + // Check to see if the provided humidity is different from the cached state + if (hasProperty(params, 'humidity')) { + let newHumi = Number.parseInt(params.humidity + this.accessory.context.offHumi, 10) + newHumi /= 100 + newHumi = Math.max(Math.min(newHumi, 100), 0) + if (newHumi !== this.cacheHumi) { + // Humidity is different so update Homebridge with new values + this.cacheHumi = newHumi + this.humiService.updateCharacteristic(this.hapChar.CurrentRelativeHumidity, this.cacheHumi) + this.accessory.eveService.addEntry({ humidity: this.cacheHumi }) + + // Log the change + this.accessory.log(`${platformLang.curHumi} [${this.cacheHumi}%]`) + } + } } async updateCache() { diff --git a/lib/device/sensor-thermo.js b/lib/device/sensor-thermo.js index 8ddca942..9bb9c68b 100644 --- a/lib/device/sensor-thermo.js +++ b/lib/device/sensor-thermo.js @@ -25,21 +25,27 @@ export default class { ? Math.min(deviceConf.lowBattThreshold, 100) : platformConsts.defaultValues.lowBattThreshold + // Remove any thermostat service if it exists + if (this.accessory.getService(this.hapServ.Thermostat)) { + this.accessory.removeService(this.accessory.getService(this.hapServ.Thermostat)) + } + // Add the temperature service if it doesn't already exist this.tempService = this.accessory.getService(this.hapServ.TemperatureSensor) || this.accessory.addService(this.hapServ.TemperatureSensor) this.cacheTemp = this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).value - this.updateCache() + + // Add the battery service if it doesn't already exist + this.battService = this.accessory.getService(this.hapServ.Battery) + || this.accessory.addService(this.hapServ.Battery) + this.cacheBatt = this.battService.getCharacteristic(this.hapChar.BatteryLevel).value // Add the humidity service if it doesn't already exist this.humiService = this.accessory.getService(this.hapServ.HumiditySensor) || this.accessory.addService(this.hapServ.HumiditySensor) this.cacheHumi = this.humiService.getCharacteristic(this.hapChar.CurrentRelativeHumidity).value - // Add the battery service if it doesn't already exist - this.battService = this.accessory.getService(this.hapServ.Battery) - || this.accessory.addService(this.hapServ.Battery) - this.cacheBatt = this.battService.getCharacteristic(this.hapChar.BatteryLevel).value + this.updateCache() // Pass the accessory to Fakegato to set up with Eve this.accessory.eveService = new platform.eveService('custom', this.accessory, { @@ -49,6 +55,7 @@ export default class { // Output the customised options to the log const opts = JSON.stringify({ lowBattThreshold: this.lowBattThreshold, + showExtraSwitch: false, }) platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts) } diff --git a/lib/platform.js b/lib/platform.js index 254ea5ad..b0bc1687 100644 --- a/lib/platform.js +++ b/lib/platform.js @@ -206,6 +206,7 @@ export default class { case 'hideModeBlackTea': case 'showCustomMode1': case 'showCustomMode2': + case 'showExtraSwitch': case 'tempReporting': if (typeof v === 'string') { logQuotes(`${key}.${id}.${k}`) @@ -941,12 +942,9 @@ export default class { accessory = devicesInHB.get(uuid) || this.addAccessory(device) } else if (platformConsts.models.sensorThermo.includes(device.model)) { // Device is a thermo-hygrometer sensor - if (device.model === 'H5109') { - // Special handling for Gateway H5042+ with Floating Pool Sensor H5109 - devInstance = deviceTypes.deviceSensorThermoH5109 - } else { - devInstance = deviceTypes.deviceSensorThermo - } + devInstance = deviceConf.showExtraSwitch + ? deviceTypes.deviceSensorThermoSwitch + : deviceTypes.deviceSensorThermo accessory = devicesInHB.get(uuid) || this.addAccessory(device) } else if (platformConsts.models.sensorThermo4.includes(device.model)) { // Device is a thermo-hygrometer sensor with 4 prongs and AWS support diff --git a/lib/utils/constants.js b/lib/utils/constants.js index 5c3e8b27..59519884 100644 --- a/lib/utils/constants.js +++ b/lib/utils/constants.js @@ -90,7 +90,7 @@ export default { 'temperatureSource', ], leakDevices: ['label', 'deviceId', 'ignoreDevice', 'lowBattThreshold'], - thermoDevices: ['label', 'deviceId', 'ignoreDevice', 'lowBattThreshold'], + thermoDevices: ['label', 'deviceId', 'ignoreDevice', 'lowBattThreshold', 'showExtraSwitch'], fanDevices: ['label', 'deviceId', 'ignoreDevice'], heaterDevices: ['label', 'deviceId', 'ignoreDevice', 'tempReporting'], humidifierDevices: ['label', 'deviceId', 'ignoreDevice'], From eb8bcc873abb984a433321c1a6fcba81285d583d Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 12:16:33 +0100 Subject: [PATCH 07/29] set `strictValidation` to `true` in the config schema file --- CHANGELOG.md | 1 + config.schema.json | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9f9f820..cbc1abbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to homebridge-govee will be documented in this file. - work-in-progress support for ice-makers - allow exposing a temperature sensor as a thermostat +- set `strictValidation` to `true` in the config schema file ## v11.0.2 (2025-05-20) diff --git a/config.schema.json b/config.schema.json index 88597d90..995aa91d 100644 --- a/config.schema.json +++ b/config.schema.json @@ -2,6 +2,7 @@ "pluginAlias": "Govee", "pluginType": "platform", "singular": true, + "strictValidation": true, "customUi": true, "customUiPath": "./lib/homebridge-ui", "headerDisplay": "

For help and support please visit our GitHub Wiki. We hope you find this plugin useful!

", From be5fd940e580221d68dfcda291b070a565cd715a Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 12:18:57 +0100 Subject: [PATCH 08/29] github repo maintenance --- .github/ISSUE_TEMPLATE.md | 30 - .github/workflows/build.yml | 8 +- .github/workflows/codeql-analysis.yml | 104 ++- .github/workflows/release-beta.yml | 30 + .github/workflows/release-latest.yml | 91 ++ CHANGELOG.md | 4 + LICENSE | 2 +- README.md | 8 +- eslint.config.js | 2 - package-lock.json | 1243 +++++++++---------------- package.json | 12 +- 11 files changed, 672 insertions(+), 862 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/workflows/release-beta.yml create mode 100644 .github/workflows/release-latest.yml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 9b0c3361..00000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,30 +0,0 @@ - - -### What issue do you have? Please be as thorough and explicit as possible. - -### Details of your setup. -* Do you use Homebridge (with config-ui?) or HOOBS? - -* Which version of Homebridge/HOOBS do you have? - -* Which version of this plugin (homebridge-govee) do you have? Has the issue started since upgrading from a previous version? - -* Which Govee devices do you have that are causing issues? Please include product models if applicable. - -### Please paste any relevant logs below. - - -``` - -``` diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e93667f..e226cb21 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,9 @@ name: Build on: [push, pull_request] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest @@ -9,7 +12,7 @@ jobs: strategy: matrix: # the Node.js versions to build on - node-version: [20.x, 22.x] + node-version: [20.x, 22.x, 24.x] steps: - uses: actions/checkout@v4 @@ -21,3 +24,6 @@ jobs: - name: Install dependencies run: npm install + + eslint: + uses: homebridge/.github/.github/workflows/eslint.yml@latest diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 35b2b62c..c106fe1a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,54 +1,100 @@ -name: CodeQL +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: CodeQL Advanced on: push: branches: [latest] pull_request: - # The branches below must be a subset of the branches above branches: [latest] schedule: - - cron: '0 1 * * 5' + - cron: '40 11 * * 1' jobs: analyze: - name: Analyze - runs-on: ubuntu-latest + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: javascript-typescript + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages steps: - name: Checkout repository uses: actions/checkout@v4 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 - # Override language selection by uncommenting this and choosing your languages - # with: - # languages: go, javascript, csharp, python, cpp, java + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - # - run: | - # make bootstrap - # make release + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 + with: + category: '/language:${{matrix.language}}' diff --git a/.github/workflows/release-beta.yml b/.github/workflows/release-beta.yml new file mode 100644 index 00000000..74a4b5c7 --- /dev/null +++ b/.github/workflows/release-beta.yml @@ -0,0 +1,30 @@ +name: Release (Beta) + +# To publish a new plugin version (to the npm 'beta' tag): +# 1. Do not modify any versions in the package.json and package-lock.json +# 2. Instead, create a branch with the name beta-X.Y.Z (e.g. beta-1.0.1, where 1.0.1 is the new version) +# 3. Each commit to the branch will trigger this workflow, which will publish the beta version to npm +# -> the first commit will publish as v1.0.1-beta.0, the second commit will publish as v1.0.1-beta.1, etc. + +on: + push: + branches: [beta-*.*.*] + workflow_dispatch: + +jobs: + eslint: + uses: homebridge/.github/.github/workflows/eslint.yml@latest + + publish: + if: ${{ github.repository == 'homebridge-plugins/homebridge-govee' }} + needs: eslint + permissions: + id-token: write + uses: homebridge/.github/.github/workflows/npm-publish-esm.yml@latest + with: + tag: beta + dynamically_adjust_version: true + npm_version_command: pre + pre_id: beta + secrets: + npm_auth_token: ${{ secrets.npm_token }} diff --git a/.github/workflows/release-latest.yml b/.github/workflows/release-latest.yml new file mode 100644 index 00000000..14a121af --- /dev/null +++ b/.github/workflows/release-latest.yml @@ -0,0 +1,91 @@ +name: Release (Latest) + +# To publish a new plugin version (to the npm 'latest' tag): +# 1. Update the version in package.json and package-lock.json and commit to the 'latest' branch +# 2. Create a new release on GitHub with the tag vX.Y.Z which points to the 'latest' branch +# 3. The release will trigger this workflow, which will publish the new version to npm + +on: + release: + types: [published] + +jobs: + eslint: + uses: homebridge/.github/.github/workflows/eslint.yml@latest + + publish: + if: ${{ github.repository == 'homebridge-plugins/homebridge-govee' }} + needs: eslint + permissions: + id-token: write + uses: homebridge/.github/.github/workflows/npm-publish-esm.yml@latest + secrets: + npm_auth_token: ${{ secrets.npm_token }} + + deprecate-previous-pre-release-data: + if: ${{ github.repository == 'homebridge-plugins/homebridge-govee' }} + runs-on: ubuntu-latest + needs: + - eslint + - publish + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + registry-url: https://registry.npmjs.org/ + + - name: Deprecate previous pre-release NPM versions + run: | + # Read local package version + LATEST_VERSION=$(jq -r .version package.json) + echo "Latest version found in package.json: $LATEST_VERSION" + DEPRECATED_VERSIONS=() + # Get all beta versions (versions with a hyphen) + mapfile -t BETA_VERSIONS < <(npm view @homebridge-plugins/homebridge-govee versions --json | jq -r '.[]' | grep -- '-') + for VERSION in "${BETA_VERSIONS[@]}"; do + BASE_VERSION="${VERSION%%-*}" + # Compare base version to latest version using sort -V + if [ "$(printf "%s\n%s" "$BASE_VERSION" "$LATEST_VERSION" | sort -V | head -n1)" != "$LATEST_VERSION" ]; then + npm deprecate @homebridge-plugins/homebridge-ecovacs@"$VERSION" "This beta version is deprecated in favor of the latest release." + echo "- Deprecated version: $VERSION (base: $BASE_VERSION)" + DEPRECATED_VERSIONS+=("$VERSION") + else + echo "- Skipped version: $VERSION (base: $BASE_VERSION)" + fi + done + if [ ${#DEPRECATED_VERSIONS[@]} -eq 0 ]; then + echo "No versions were deprecated." + else + echo "Deprecated versions:" + for VERSION in "${DEPRECATED_VERSIONS[@]}"; do + echo "- $VERSION" + done + fi + env: + NODE_AUTH_TOKEN: ${{ secrets.npm_token }} + + - name: Delete previous pre-release GitHub releases + run: | + echo "Finding GitHub releases with a hyphen in the tag name..." + gh release list --limit 100 --json tagName,name --jq '.[] | select(.tagName | test("-"; "i")) | .tagName' | while read -r TAG; do + echo "Deleting GitHub release: $TAG" + gh release delete "$TAG" --yes + done + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Delete previous pre-release Git tags + run: | + echo "Fetching tags from origin..." + git fetch --tags + echo "Finding tags with a hyphen in the name..." + git tag -l "*-*" | while read -r TAG; do + echo "Deleting tag: $TAG" + git push origin ":refs/tags/$TAG" + done + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index cbc1abbf..c4a7a82d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ All notable changes to homebridge-govee will be documented in this file. - allow exposing a temperature sensor as a thermostat - set `strictValidation` to `true` in the config schema file +### Other Changes + +- github repo maintenance + ## v11.0.2 (2025-05-20) ⚠️ This plugin no longer officially supports Node 18. Please update to Node 20 or 22. diff --git a/LICENSE b/LICENSE index 571db3e8..20862802 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 - 2025 Ben Potter +Copyright (c) Ben Potter Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a21367d0..a6ac5eee 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,13 @@ Homebridge plugin to integrate Govee devices into HomeKit -[![npm](https://img.shields.io/npm/v/homebridge-govee/latest?label=latest)](https://www.npmjs.com/package/homebridge-govee) -[![npm](https://img.shields.io/npm/v/homebridge-govee/beta?label=beta)](https://github.com/homebridge-plugins/homebridge-govee/wiki/Beta-Version) +[![npm](https://img.shields.io/npm/v/@homebridge-plugins/homebridge-govee/latest?label=latest)](https://www.npmjs.com/package/@homebridge-plugins/homebridge-govee) +[![npm](https://img.shields.io/npm/v/@homebridge-plugins/homebridge-govee/beta?label=beta)](https://github.com/homebridge-plugins/homebridge-govee/wiki/Beta-Version) [![verified-by-homebridge](https://badgen.net/badge/homebridge/verified/purple)](https://github.com/homebridge/homebridge/wiki/Verified-Plugins) [![hoobs-certified](https://badgen.net/badge/HOOBS/certified/yellow?label=hoobs)](https://plugins.hoobs.org/plugin/homebridge-govee) -[![npm](https://img.shields.io/npm/dt/homebridge-govee)](https://www.npmjs.com/package/homebridge-govee) +[![npm](https://img.shields.io/npm/dt/@homebridge-plugins/homebridge-govee)](https://www.npmjs.com/package/@homebridge-plugins/homebridge-govee) [![Discord](https://img.shields.io/discord/432663330281226270?color=728ED5&logo=discord&label=discord)](https://discord.com/channels/432663330281226270/742733745743855627) @@ -28,7 +28,7 @@ Homebridge plugin to integrate Govee devices into HomeKit ### Prerequisites - To use this plugin, you will need to already have: - - [Node](https://nodejs.org): latest version of `v20` or `v22` - any other major version is not supported. + - [Node](https://nodejs.org): latest version of `v20`, `v22` or `v24` - any other major version is not supported. - [Homebridge](https://homebridge.io): `v1.6` or above - refer to link for more information and installation instructions. - For bluetooth connectivity, it may be necessary to install extra packages on your system, see [Bluetooth Control](https://github.com/homebridge-plugins/homebridge-govee/wiki/Bluetooth-Control). Bluetooth works best when using a Raspberry Pi, not been tested on Windows, and Mac devices are unsupported. diff --git a/eslint.config.js b/eslint.config.js index 856f52ad..9237b63d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -8,8 +8,6 @@ export default antfu( rules: { 'curly': ['error', 'multi-line'], 'new-cap': 'off', - 'import/extensions': ['error', 'ignorePackages'], - 'import/order': 0, 'jsdoc/check-alignment': 'warn', 'jsdoc/check-line-alignment': 'warn', 'jsdoc/require-returns-check': 0, diff --git a/package-lock.json b/package-lock.json index 909a3688..5d477754 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,20 +27,20 @@ ], "license": "MIT", "dependencies": { - "@homebridge/plugin-ui-utils": "^2.0.2", + "@homebridge/plugin-ui-utils": "^2.1.0", "aws-iot-device-sdk": "^2.2.15", - "axios": "^1.9.0", + "axios": "^1.10.0", "node-persist": "^4.0.4", "node-rsa": "^1.1.1", "p-queue": "^8.1.0", "pem": "^1.14.8" }, "devDependencies": { - "@antfu/eslint-config": "^4.13.1" + "@antfu/eslint-config": "^4.16.2" }, "engines": { "homebridge": "^1.6.0 || ^2.0.0-beta.0", - "node": "^20.19.2 || ^22.15.1" + "node": "^20 || ^22 || ^24" }, "optionalDependencies": { "@stoprocent/bluetooth-hci-socket": "^1.5.2", @@ -48,47 +48,47 @@ } }, "node_modules/@antfu/eslint-config": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-4.13.1.tgz", - "integrity": "sha512-Ldv0gzQEDH/M+6NfhVBK/9NTDwsYJuHHJBPaFQN9X6LGd927sfEWzMHQdEbrA7f8Rr6abbinReifK7OjDipJ/g==", + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-4.16.2.tgz", + "integrity": "sha512-5KHZR+7ne+HZnOJUKeTTdHKYA/yOygPssaJ7TZOMoBqjSMtVAa7FO5Wvu2dEtkibM6v3emYyKnQnia1S8NHQeA==", "dev": true, "license": "MIT", "dependencies": { "@antfu/install-pkg": "^1.1.0", - "@clack/prompts": "^0.10.1", + "@clack/prompts": "^0.11.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", - "@eslint/markdown": "^6.4.0", - "@stylistic/eslint-plugin": "^4.2.0", - "@typescript-eslint/eslint-plugin": "^8.32.1", - "@typescript-eslint/parser": "^8.32.1", - "@vitest/eslint-plugin": "^1.1.44", - "ansis": "^4.0.0", + "@eslint/markdown": "^6.6.0", + "@stylistic/eslint-plugin": "^5.1.0", + "@typescript-eslint/eslint-plugin": "^8.35.1", + "@typescript-eslint/parser": "^8.35.1", + "@vitest/eslint-plugin": "^1.3.4", + "ansis": "^4.1.0", "cac": "^6.7.14", "eslint-config-flat-gitignore": "^2.1.0", - "eslint-flat-config-utils": "^2.0.1", + "eslint-flat-config-utils": "^2.1.0", "eslint-merge-processors": "^2.0.0", "eslint-plugin-antfu": "^3.1.1", - "eslint-plugin-command": "^3.2.0", - "eslint-plugin-import-x": "^4.11.1", - "eslint-plugin-jsdoc": "^50.6.17", - "eslint-plugin-jsonc": "^2.20.0", - "eslint-plugin-n": "^17.18.0", + "eslint-plugin-command": "^3.3.1", + "eslint-plugin-import-lite": "^0.3.0", + "eslint-plugin-jsdoc": "^51.3.2", + "eslint-plugin-jsonc": "^2.20.1", + "eslint-plugin-n": "^17.20.0", "eslint-plugin-no-only-tests": "^3.3.0", - "eslint-plugin-perfectionist": "^4.13.0", + "eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-pnpm": "^0.3.1", - "eslint-plugin-regexp": "^2.7.0", + "eslint-plugin-regexp": "^2.9.0", "eslint-plugin-toml": "^0.12.0", "eslint-plugin-unicorn": "^59.0.1", "eslint-plugin-unused-imports": "^4.1.4", - "eslint-plugin-vue": "^10.1.0", + "eslint-plugin-vue": "^10.2.0", "eslint-plugin-yml": "^1.18.0", "eslint-processor-vue-blocks": "^2.0.0", - "globals": "^16.1.0", + "globals": "^16.3.0", "jsonc-eslint-parser": "^2.4.0", "local-pkg": "^1.1.1", "parse-gitignore": "^2.0.0", "toml-eslint-parser": "^0.10.0", - "vue-eslint-parser": "^10.1.3", + "vue-eslint-parser": "^10.2.0", "yaml-eslint-parser": "^1.3.0" }, "bin": { @@ -195,14 +195,14 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", - "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.28.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -212,9 +212,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "dev": true, "license": "MIT", "peer": true, @@ -227,9 +227,9 @@ } }, "node_modules/@clack/core": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.4.2.tgz", - "integrity": "sha512-NYQfcEy8MWIxrT5Fj8nIVchfRFA26yYKJcvBS7WlUIlw2OmQOY9DhGGXMovyI5J5PpxrCPGkgUi207EBrjpBvg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.5.0.tgz", + "integrity": "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==", "dev": true, "license": "MIT", "dependencies": { @@ -238,51 +238,17 @@ } }, "node_modules/@clack/prompts": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.10.1.tgz", - "integrity": "sha512-Q0T02vx8ZM9XSv9/Yde0jTmmBQufZhPJfYAg2XrrrxWWaZgq1rr8nU8Hv710BQ1dhoP8rtY7YUdpGej2Qza/cw==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.11.0.tgz", + "integrity": "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==", "dev": true, "license": "MIT", "dependencies": { - "@clack/core": "0.4.2", + "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, - "node_modules/@emnapi/core": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", - "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.0.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", - "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@es-joy/jsdoccomment": { "version": "0.50.2", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.50.2.tgz", @@ -363,16 +329,16 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.9.tgz", - "integrity": "sha512-gCdSY54n7k+driCadyMNv8JSPzYLeDVM/ikZRtvtROBpRdFSkS8W9A82MqsaY7lZuwL0wiapgD0NT1xT0hyJsA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.3.1.tgz", + "integrity": "sha512-k8MHony59I5EPic6EQTCNOuPoVBnoYXkP+20xvwFjN7t0qI3ImyvyBgg+hIVPwC8JaxVjjUZld+cLfBLFDLucg==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": "^9.10.0" + "eslint": "^8.40 || 9" }, "peerDependenciesMeta": { "eslint": { @@ -381,9 +347,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -397,9 +363,9 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -423,9 +389,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", - "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -434,9 +400,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -472,9 +438,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -512,9 +478,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", - "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", + "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", "dev": true, "license": "MIT", "peer": true, @@ -526,14 +492,18 @@ } }, "node_modules/@eslint/markdown": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.4.0.tgz", - "integrity": "sha512-J07rR8uBSNFJ9iliNINrchilpkmCihPmTVotpThUeKEn5G8aBBZnkjNBy/zovhJA5LBk1vWU9UDlhqKSc/dViQ==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.6.0.tgz", + "integrity": "sha512-IsWPy2jU3gaQDlioDC4sT4I4kG1hX1OMWs/q2sWwJrPoMASHW/Z4SDw+6Aql6EsHejGbagYuJbFq9Zvx+Y1b1Q==", "dev": true, "license": "MIT", + "workspaces": [ + "examples/*" + ], "dependencies": { - "@eslint/core": "^0.10.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/core": "^0.14.0", + "@eslint/plugin-kit": "^0.3.1", + "github-slugger": "^2.0.0", "mdast-util-from-markdown": "^2.0.2", "mdast-util-frontmatter": "^2.0.1", "mdast-util-gfm": "^3.0.0", @@ -556,13 +526,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", - "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", + "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.13.0", + "@eslint/core": "^0.15.1", "levn": "^0.4.1" }, "engines": { @@ -570,9 +540,9 @@ } }, "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -583,9 +553,9 @@ } }, "node_modules/@homebridge/plugin-ui-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@homebridge/plugin-ui-utils/-/plugin-ui-utils-2.0.2.tgz", - "integrity": "sha512-2o81veVuJ09GSm/epnw8Mn6CLpyqdqV7AclHt3psTYyaKdwNw3cGLpEyEteVNBwOU/ChMDNMNzJpeQ8pvlLojg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@homebridge/plugin-ui-utils/-/plugin-ui-utils-2.1.0.tgz", + "integrity": "sha512-tv395ATHOk79PHtnpK7xT642B2vGugGXhNv+4MY0J+tPaq+5yLkZAgOErxP7v8Z36xzsN9MEit6uPL52dzhaRQ==", "license": "MIT" }, "node_modules/@httptoolkit/websocket-stream": { @@ -676,26 +646,13 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", "dev": true, "license": "MIT", "peer": true }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz", - "integrity": "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.9.0" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -735,9 +692,9 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", - "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", "dev": true, "license": "MIT", "engines": { @@ -1084,15 +1041,16 @@ } }, "node_modules/@stylistic/eslint-plugin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.2.0.tgz", - "integrity": "sha512-8hXezgz7jexGHdo5WN6JBEIPHCSFyyU4vgbxevu4YLVS5vl+sxqAAGyXSzfNDyR6xMNSH5H1x67nsXcYMOHtZA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.1.0.tgz", + "integrity": "sha512-TJRJul4u/lmry5N/kyCU+7RWWOk0wyXN+BncRlDYBqpLFnzXkd7QGVfN7KewarFIXv0IX0jSF/Ksu7aHWEDeuw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.23.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.34.1", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -1103,17 +1061,6 @@ "eslint": ">=9.0.0" } }, - "node_modules/@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -1125,9 +1072,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, @@ -1156,12 +1103,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.20.tgz", - "integrity": "sha512-A6BohGFRGHAscJsTslDCA9JG7qSJr/DWUvrvY8yi9IgnGtMxCyat7vvQ//MFa0DnLsyuS3wYTpLdw4Hf+Q5JXw==", + "version": "24.0.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.13.tgz", + "integrity": "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/unist": { @@ -1188,17 +1135,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", - "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.36.0.tgz", + "integrity": "sha512-lZNihHUVB6ZZiPBNgOQGSxUASI7UJWhT8nHyUGCnaQ28XFCw98IfrMCG3rUl1uwUWoAvodJQby2KTs79UTcrAg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.32.1", - "@typescript-eslint/type-utils": "8.32.1", - "@typescript-eslint/utils": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1", + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/type-utils": "8.36.0", + "@typescript-eslint/utils": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -1212,15 +1159,15 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.36.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", - "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -1228,16 +1175,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", - "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.36.0.tgz", + "integrity": "sha512-FuYgkHwZLuPbZjQHzJXrtXreJdFMKl16BFYyRrLxDhWr6Qr7Kbcu2s1Yhu8tsiMXw1S0W1pjfFfYEt+R604s+Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.32.1", - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/typescript-estree": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1", + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/typescript-estree": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", "debug": "^4.3.4" }, "engines": { @@ -1252,15 +1199,37 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.36.0.tgz", + "integrity": "sha512-JAhQFIABkWccQYeLMrHadu/fhpzmSQ1F1KXkpzqiVxA/iYI6UnRt2trqXHt1sYEcw1mxLnB9rKMsOxXPxowN/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.36.0", + "@typescript-eslint/types": "^8.36.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", - "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.36.0.tgz", + "integrity": "sha512-wCnapIKnDkN62fYtTGv2+RY8FlnBYA3tNm0fm91kc2BjPhV2vIjwwozJ7LToaLAyb1ca8BxrS7vT+Pvvf7RvqA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1" + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1270,15 +1239,32 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.36.0.tgz", + "integrity": "sha512-Nhh3TIEgN18mNbdXpd5Q8mSCBnrZQeY9V7Ca3dqYvNDStNIGRmJA6dmrIPMJ0kow3C7gcQbpsG2rPzy1Ks/AnA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", - "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.36.0.tgz", + "integrity": "sha512-5aaGYG8cVDd6cxfk/ynpYzxBRZJk7w/ymto6uiyUFtdCozQIsQWh7M28/6r57Fwkbweng8qAzoMCPwSJfWlmsg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.32.1", - "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/typescript-estree": "8.36.0", + "@typescript-eslint/utils": "8.36.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -1295,9 +1281,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", - "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.36.0.tgz", + "integrity": "sha512-xGms6l5cTJKQPZOKM75Dl9yBfNdGeLRsIyufewnxT4vZTrjC0ImQT4fj8QmtJK84F58uSh5HVBSANwcfiXxABQ==", "dev": true, "license": "MIT", "engines": { @@ -1309,14 +1295,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", - "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.36.0.tgz", + "integrity": "sha512-JaS8bDVrfVJX4av0jLpe4ye0BpAaUW7+tnS4Y4ETa3q7NoZgzYbN9zDQTJ8kPb5fQ4n0hliAt9tA4Pfs2zA2Hg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/visitor-keys": "8.32.1", + "@typescript-eslint/project-service": "8.36.0", + "@typescript-eslint/tsconfig-utils": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/visitor-keys": "8.36.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1336,16 +1324,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", - "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.36.0.tgz", + "integrity": "sha512-VOqmHu42aEMT+P2qYjylw6zP/3E/HvptRwdn/PZxyV27KhZg2IOszXod4NcXisWzPAGSS4trE/g4moNj6XmH2g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.1", - "@typescript-eslint/types": "8.32.1", - "@typescript-eslint/typescript-estree": "8.32.1" + "@typescript-eslint/scope-manager": "8.36.0", + "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/typescript-estree": "8.36.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1360,14 +1348,14 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", - "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.36.0.tgz", + "integrity": "sha512-vZrhV2lRPWDuGoxcmrzRZyxAggPL+qp3WzUrlZD+slFueDiYHxeBa34dUXPuC0RmGKzl4lS5kFJYvKCq9cnNDA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.1", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.36.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1377,255 +1365,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.2.tgz", - "integrity": "sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.2.tgz", - "integrity": "sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.2.tgz", - "integrity": "sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.2.tgz", - "integrity": "sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.2.tgz", - "integrity": "sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.2.tgz", - "integrity": "sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.2.tgz", - "integrity": "sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.2.tgz", - "integrity": "sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.2.tgz", - "integrity": "sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.2.tgz", - "integrity": "sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.2.tgz", - "integrity": "sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.2.tgz", - "integrity": "sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.2.tgz", - "integrity": "sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.2.tgz", - "integrity": "sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.9" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.2.tgz", - "integrity": "sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.2.tgz", - "integrity": "sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.2.tgz", - "integrity": "sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@vitest/eslint-plugin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.0.tgz", - "integrity": "sha512-6vn3QDy+ysqHGkbH9fU9uyWptqNc638dgPy0uAlh/XpniTBp+0WeVlXGW74zqggex/CwYOhK8t5GVo/FH3NMPw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.3.4.tgz", + "integrity": "sha512-EOg8d0jn3BAiKnR55WkFxmxfWA3nmzrbIIuOXyTe6A72duryNgyU+bdBEauA97Aab3ho9kLmAwgPX63Ckj4QEg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.24.0" + "@typescript-eslint/utils": "^8.24.1" }, "peerDependencies": { "eslint": ">= 8.57.0", @@ -1642,67 +1389,67 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.14.tgz", - "integrity": "sha512-k7qMHMbKvoCXIxPhquKQVw3Twid3Kg4s7+oYURxLGRd56LiuHJVrvFKI4fm2AM3c8apqODPfVJGoh8nePbXMRA==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz", + "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.27.2", - "@vue/shared": "3.5.14", + "@babel/parser": "^7.27.5", + "@vue/shared": "3.5.17", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.14.tgz", - "integrity": "sha512-1aOCSqxGOea5I80U2hQJvXYpPm/aXo95xL/m/mMhgyPUsKe9jhjwWpziNAw7tYRnbz1I61rd9Mld4W9KmmRoug==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz", + "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-core": "3.5.14", - "@vue/shared": "3.5.14" + "@vue/compiler-core": "3.5.17", + "@vue/shared": "3.5.17" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.14.tgz", - "integrity": "sha512-9T6m/9mMr81Lj58JpzsiSIjBgv2LiVoWjIVa7kuXHICUi8LiDSIotMpPRXYJsXKqyARrzjT24NAwttrMnMaCXA==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz", + "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.27.2", - "@vue/compiler-core": "3.5.14", - "@vue/compiler-dom": "3.5.14", - "@vue/compiler-ssr": "3.5.14", - "@vue/shared": "3.5.14", + "@babel/parser": "^7.27.5", + "@vue/compiler-core": "3.5.17", + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", - "postcss": "^8.5.3", + "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.14.tgz", - "integrity": "sha512-Y0G7PcBxr1yllnHuS/NxNCSPWnRGH4Ogrp0tsLA5QemDZuJLs99YjAKQ7KqkHE0vCg4QTKlQzXLKCMF7WPSl7Q==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz", + "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.5.14", - "@vue/shared": "3.5.14" + "@vue/compiler-dom": "3.5.17", + "@vue/shared": "3.5.17" } }, "node_modules/@vue/shared": { - "version": "3.5.14", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.14.tgz", - "integrity": "sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz", + "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==", "dev": true, "license": "MIT", "peer": true @@ -1715,9 +1462,9 @@ "optional": true }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -1772,9 +1519,9 @@ } }, "node_modules/ansis": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.0.0.tgz", - "integrity": "sha512-P8nrHI1EyW9OfBt1X7hMSwGN2vwRuqHSKJAT1gbLWZRzDa24oHjYwGHvEgHeBepupzk878yS/HBZ0NMPYtbolw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.1.0.tgz", + "integrity": "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==", "dev": true, "license": "ISC", "engines": { @@ -1847,9 +1594,9 @@ } }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -1916,9 +1663,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1939,9 +1686,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", - "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -1959,8 +1706,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001716", - "electron-to-chromium": "^1.5.149", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -2085,9 +1832,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001718", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", - "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", + "version": "1.0.30001727", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", "dev": true, "funding": [ { @@ -2154,9 +1901,9 @@ } }, "node_modules/ci-info": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", - "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, "funding": [ { @@ -2287,13 +2034,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", - "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", + "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.24.4" + "browserslist": "^4.25.1" }, "funding": { "type": "opencollective", @@ -2367,9 +2114,9 @@ } }, "node_modules/decode-named-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", - "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2466,25 +2213,25 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.155", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz", - "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==", + "version": "1.5.182", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz", + "integrity": "sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA==", "dev": true, "license": "ISC" }, "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2587,20 +2334,20 @@ } }, "node_modules/eslint": { - "version": "9.27.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", - "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", + "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.14.0", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.27.0", + "@eslint/js": "9.31.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -2612,9 +2359,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2681,40 +2428,18 @@ } }, "node_modules/eslint-flat-config-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-2.0.1.tgz", - "integrity": "sha512-brf0eAgQ6JlKj3bKfOTuuI7VcCZvi8ZCD1MMTVoEvS/d38j8cByZViLFALH/36+eqB17ukmfmKq3bWzGvizejA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-flat-config-utils/-/eslint-flat-config-utils-2.1.0.tgz", + "integrity": "sha512-6fjOJ9tS0k28ketkUcQ+kKptB4dBZY2VijMZ9rGn8Cwnn1SH0cZBoPXT8AHBFHxmHcLFQK9zbELDinZ2Mr1rng==", "dev": true, "license": "MIT", "dependencies": { - "pathe": "^2.0.2" + "pathe": "^2.0.3" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/eslint-json-compat-utils": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/eslint-json-compat-utils/-/eslint-json-compat-utils-0.2.1.tgz", @@ -2764,13 +2489,13 @@ } }, "node_modules/eslint-plugin-command": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-command/-/eslint-plugin-command-3.2.0.tgz", - "integrity": "sha512-PSDOB9k7Wd57pp4HD/l3C1D93pKX8/wQo0kWDI4q6/UpgrfMTyNsavklipgiZqbXl1+VBABY1buCcQE5LDpg5g==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-command/-/eslint-plugin-command-3.3.1.tgz", + "integrity": "sha512-fBVTXQ2y48TVLT0+4A6PFINp7GcdIailHAXbvPBixE7x+YpYnNQhFZxTdvnb+aWk+COgNebQKen/7m4dmgyWAw==", "dev": true, "license": "MIT", "dependencies": { - "@es-joy/jsdoccomment": "^0.50.0" + "@es-joy/jsdoccomment": "^0.50.2" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -2817,60 +2542,71 @@ "eslint": ">=6.0.0" } }, - "node_modules/eslint-plugin-import-x": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.12.2.tgz", - "integrity": "sha512-0jVUgJQipbs0yUfLe7LwYD6p8rIGqCysWZdyJFgkPzDyJgiKpuCaXlywKUAWgJ6u1nLpfrdt21B60OUkupyBrQ==", + "node_modules/eslint-plugin-import-lite": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-lite/-/eslint-plugin-import-lite-0.3.0.tgz", + "integrity": "sha512-dkNBAL6jcoCsXZsQ/Tt2yXmMDoNt5NaBh/U7yvccjiK8cai6Ay+MK77bMykmqQA2bTF6lngaLCDij6MTO3KkvA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.31.0", - "comment-parser": "^1.4.1", - "debug": "^4.4.0", - "eslint-import-resolver-node": "^0.3.9", - "get-tsconfig": "^4.10.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.3 || ^10.0.1", - "semver": "^7.7.1", - "stable-hash": "^0.0.5", - "tslib": "^2.8.1", - "unrs-resolver": "^1.7.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-import-x" - }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "eslint": ">=9.0.0", + "typescript": ">=4.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.17", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.17.tgz", - "integrity": "sha512-hq+VQylhd12l8qjexyriDsejZhqiP33WgMTy2AmaGZ9+MrMWVqPECsM87GPxgHfQn0zw+YTuhqjUfk1f+q67aQ==", + "version": "51.3.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.3.4.tgz", + "integrity": "sha512-maz6qa95+sAjMr9m5oRyfejc+mnyQWsWSe9oyv9371bh4/T0kWOMryJNO4h8rEd97wo/9lbzwi3OOX4rDhnAzg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.50.1", + "@es-joy/jsdoccomment": "~0.52.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", - "debug": "^4.3.6", + "debug": "^4.4.1", "escape-string-regexp": "^4.0.0", - "espree": "^10.1.0", + "espree": "^10.4.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", - "semver": "^7.6.3", + "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=20.11.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-jsdoc/node_modules/@es-joy/jsdoccomment": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.52.0.tgz", + "integrity": "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.34.1", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=20.11.0" + } + }, "node_modules/eslint-plugin-jsonc": { "version": "2.20.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.20.1.tgz", @@ -2898,9 +2634,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.18.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.18.0.tgz", - "integrity": "sha512-hvZ/HusueqTJ7VDLoCpjN0hx4N4+jHIWTXD4TMLHy9F23XkDagR9v+xQWRWR57yY55GPF8NnD4ox9iGTxirY8A==", + "version": "17.21.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.21.0.tgz", + "integrity": "sha512-1+iZ8We4ZlwVMtb/DcHG3y5/bZOdazIpa/4TySo22MLKdwrLcfrX0hbadnCvykSQCCmkAnWmIP8jZVb2AAq29A==", "dev": true, "license": "MIT", "dependencies": { @@ -2911,7 +2647,8 @@ "globals": "^15.11.0", "ignore": "^5.3.2", "minimatch": "^9.0.5", - "semver": "^7.6.3" + "semver": "^7.6.3", + "ts-declaration-location": "^1.0.6" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2947,14 +2684,14 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.13.0.tgz", - "integrity": "sha512-dsPwXwV7IrG26PJ+h1crQ1f5kxay/gQAU0NJnbVTQc91l5Mz9kPjyIZ7fXgie+QSgi8a+0TwGbfaJx+GIhzuoQ==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.15.0.tgz", + "integrity": "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.32.1", - "@typescript-eslint/utils": "^8.32.1", + "@typescript-eslint/types": "^8.34.1", + "@typescript-eslint/utils": "^8.34.1", "natural-orderby": "^5.0.0" }, "engines": { @@ -2993,9 +2730,9 @@ } }, "node_modules/eslint-plugin-regexp": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.7.0.tgz", - "integrity": "sha512-U8oZI77SBtH8U3ulZ05iu0qEzIizyEDXd+BWHvyVxTOjGwcDcvy/kEpgFG4DYca2ByRLiVPFZ2GeH7j1pdvZTA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.9.0.tgz", + "integrity": "sha512-9WqJMnOq8VlE/cK+YAo9C9YHhkOtcEtEk9d12a+H7OSZFwlpI6stiHmYPGa2VE0QhTzodJyhlyprUaXDZLgHBw==", "dev": true, "license": "MIT", "dependencies": { @@ -3071,6 +2808,33 @@ "eslint": ">=9.22.0" } }, + "node_modules/eslint-plugin-unicorn/node_modules/@eslint/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "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-plugin-unicorn/node_modules/@eslint/plugin-kit": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.13.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint-plugin-unused-imports": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", @@ -3088,9 +2852,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.1.0.tgz", - "integrity": "sha512-/VTiJ1eSfNLw6lvG9ENySbGmcVvz6wZ9nA7ZqXlLBY2RkaF15iViYKxglWiIch12KiLAj0j1iXPYU6W4wTROFA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.3.0.tgz", + "integrity": "sha512-A0u9snqjCfYaPnqqOaH6MBLVWDUIN4trXn8J3x67uDcXvR7X6Ut8p16N+nYhMCQ9Y7edg2BIRGzfyZsY0IdqoQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3105,8 +2869,14 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "vue-eslint-parser": "^10.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/parser": { + "optional": true + } } }, "node_modules/eslint-plugin-yml": { @@ -3147,9 +2917,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -3164,9 +2934,9 @@ } }, "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==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3177,9 +2947,9 @@ } }, "node_modules/eslint/node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -3190,25 +2960,10 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/eslint/node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@eslint/core": "^0.14.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/eslint/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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -3232,15 +2987,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3311,9 +3066,9 @@ "license": "MIT" }, "node_modules/exsolve": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", - "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", "dev": true, "license": "MIT" }, @@ -3396,9 +3151,9 @@ } }, "node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -3522,14 +3277,15 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -3626,6 +3382,13 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true, + "license": "ISC" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -3662,9 +3425,9 @@ } }, "node_modules/glob/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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -3684,9 +3447,9 @@ } }, "node_modules/globals": { - "version": "16.1.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", - "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true, "license": "MIT", "engines": { @@ -3919,22 +3682,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -5409,22 +5156,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/napi-postinstall": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz", - "integrity": "sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==", - "dev": true, - "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, "node_modules/napi-thread-safe-callback": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/napi-thread-safe-callback/-/napi-thread-safe-callback-0.0.6.tgz", @@ -5450,9 +5181,9 @@ } }, "node_modules/node-addon-api": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz", - "integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.4.0.tgz", + "integrity": "sha512-D9DI/gXHvVmjHS08SVch0Em8G5S1P+QWtU31appcKT/8wFSPRcdHadIFSAntdMMVM5zz+/DL+bL/gz3UDppqtg==", "license": "MIT", "optional": true, "engines": { @@ -5761,13 +5492,6 @@ "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -5811,14 +5535,14 @@ } }, "node_modules/pkg-types": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", - "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.2.0.tgz", + "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==", "dev": true, "license": "MIT", "dependencies": { - "confbox": "^0.2.1", - "exsolve": "^1.0.1", + "confbox": "^0.2.2", + "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, @@ -5853,9 +5577,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -5874,7 +5598,7 @@ "license": "MIT", "peer": true, "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5919,9 +5643,9 @@ "license": "MIT" }, "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -6073,27 +5797,6 @@ "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==", "license": "MIT" }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -6389,13 +6092,6 @@ "node": ">= 6" } }, - "node_modules/stable-hash": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", - "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", - "dev": true, - "license": "MIT" - }, "node_modules/stream-shift": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", @@ -6460,23 +6156,10 @@ "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/synckit": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.6.tgz", - "integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", + "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", "dev": true, "license": "MIT", "dependencies": { @@ -6507,9 +6190,9 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6591,12 +6274,28 @@ "typescript": ">=4.8.4" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "node_modules/ts-declaration-location": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz", + "integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==", "dev": true, - "license": "0BSD" + "funding": [ + { + "type": "ko-fi", + "url": "https://ko-fi.com/rebeccastevens" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/ts-declaration-location" + } + ], + "license": "BSD-3-Clause", + "dependencies": { + "picomatch": "^4.0.2" + }, + "peerDependencies": { + "typescript": ">=4.0.0" + } }, "node_modules/type-check": { "version": "0.4.0", @@ -6640,9 +6339,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "license": "MIT" }, "node_modules/unist-util-is": { @@ -6714,39 +6413,6 @@ "node": ">= 10.0.0" } }, - "node_modules/unrs-resolver": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz", - "integrity": "sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/JounQin" - }, - "optionalDependencies": { - "@unrs/resolver-binding-darwin-arm64": "1.7.2", - "@unrs/resolver-binding-darwin-x64": "1.7.2", - "@unrs/resolver-binding-freebsd-x64": "1.7.2", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.2", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.2", - "@unrs/resolver-binding-linux-arm64-gnu": "1.7.2", - "@unrs/resolver-binding-linux-arm64-musl": "1.7.2", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.2", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.2", - "@unrs/resolver-binding-linux-riscv64-musl": "1.7.2", - "@unrs/resolver-binding-linux-s390x-gnu": "1.7.2", - "@unrs/resolver-binding-linux-x64-gnu": "1.7.2", - "@unrs/resolver-binding-linux-x64-musl": "1.7.2", - "@unrs/resolver-binding-wasm32-wasi": "1.7.2", - "@unrs/resolver-binding-win32-arm64-msvc": "1.7.2", - "@unrs/resolver-binding-win32-ia32-msvc": "1.7.2", - "@unrs/resolver-binding-win32-x64-msvc": "1.7.2" - } - }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -6812,9 +6478,9 @@ "license": "MIT" }, "node_modules/vue-eslint-parser": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.3.tgz", - "integrity": "sha512-dbCBnd2e02dYWsXoqX5yKUZlOt+ExIpq7hmHKPb5ZqKcjf++Eo0hMseFTZMLKThrUk61m+Uv6A2YSBve6ZvuDQ==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.2.0.tgz", + "integrity": "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==", "dev": true, "license": "MIT", "dependencies": { @@ -6823,7 +6489,6 @@ "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.6.0", - "lodash": "^4.17.21", "semver": "^7.6.3" }, "engines": { @@ -6869,9 +6534,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", - "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index ccc966f1..2460c448 100644 --- a/package.json +++ b/package.json @@ -48,16 +48,16 @@ "main": "lib/index.js", "engines": { "homebridge": "^1.6.0 || ^2.0.0-beta.0", - "node": "^20.19.2 || ^22.15.1" + "node": "^20 || ^22 || ^24" }, "scripts": { - "lint": "eslint . --fix", - "rebuild": "rm -rf package-lock.json && rm -rf node_modules && npm install" + "lint": "eslint . --max-warnings=0", + "lint:fix": "npm run lint -- --fix" }, "dependencies": { - "@homebridge/plugin-ui-utils": "^2.0.2", + "@homebridge/plugin-ui-utils": "^2.1.0", "aws-iot-device-sdk": "^2.2.15", - "axios": "^1.9.0", + "axios": "^1.10.0", "node-persist": "^4.0.4", "node-rsa": "^1.1.1", "p-queue": "^8.1.0", @@ -68,6 +68,6 @@ "@stoprocent/noble": "^1.19.1" }, "devDependencies": { - "@antfu/eslint-config": "^4.13.1" + "@antfu/eslint-config": "^4.16.2" } } From 941b20c8a881348ccb619324e6c31c10e41f6a48 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 12:34:48 +0100 Subject: [PATCH 09/29] support new govee models --- CHANGELOG.md | 3 +++ lib/utils/constants.js | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4a7a82d..f1e9c4f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ All notable changes to homebridge-govee will be documented in this file. - work-in-progress support for ice-makers - allow exposing a temperature sensor as a thermostat - set `strictValidation` to `true` in the config schema file +- support new govee models + - lights: `H601E` `H6048` `H60A6` `H60B0` `H6630` `H7025` `H7086` `H8022` + - ice-makers: `H717D` (work-in-progress) ### Other Changes diff --git a/lib/utils/constants.js b/lib/utils/constants.js index 59519884..23a51bfe 100644 --- a/lib/utils/constants.js +++ b/lib/utils/constants.js @@ -143,12 +143,14 @@ export default { 'H601B', 'H601C', 'H601D', + 'H601E', 'H6022', 'H6039', 'H6042', 'H6043', 'H6046', 'H6047', + 'H6048', 'H6049', 'H604A', 'H604B', @@ -202,6 +204,8 @@ export default { 'H6099', 'H60A0', 'H60A1', + 'H60A6', + 'H60B0', 'H6101', 'H6102', 'H6104', @@ -330,6 +334,7 @@ export default { 'H6602', 'H6604', 'H6609', + 'H6630', 'H6640', 'H6641', 'H6800', @@ -355,6 +360,7 @@ export default { 'H7022', 'H7023', 'H7024', + 'H7025', 'H7028', 'H7029', 'H7031', @@ -395,6 +401,7 @@ export default { 'H7070', 'H7075', 'H7078', + 'H7086', 'H7090', 'H7092', 'H7093', @@ -419,6 +426,7 @@ export default { 'H70D3', 'H801B', 'H801C', + 'H8022', 'H805A', 'H805B', 'H805C', @@ -465,7 +473,7 @@ export default { humidifier: ['H7140', 'H7141', 'H7142', 'H7143', 'H7145', 'H7147', 'H7148', 'H7149', 'H714E', 'H7160'], purifier: ['H7120', 'H7121', 'H7122', 'H7123', 'H7124', 'H7126', 'H7127', 'H7128', 'H7129', 'H712C'], diffuser: ['H7161', 'H7162'], - iceMaker: ['H7172'], + iceMaker: ['H7172', 'H717D'], sensorButton: ['H5122'], sensorContact: ['H5123'], sensorPresence: ['H5127'], @@ -477,12 +485,16 @@ export default { 'H5043', // https://github.com/homebridge-plugins/homebridge-govee/issues/558 'H5059', // https://github.com/homebridge-plugins/homebridge-govee/issues/1098 'H5085', // https://github.com/homebridge-plugins/homebridge-govee/issues/951 + 'H5110', // https://github.com/homebridge-plugins/homebridge-govee/issues/1116 + 'H5111', // https://github.com/homebridge-plugins/homebridge-govee/issues/1117 'H5121', // https://github.com/homebridge-plugins/homebridge-govee/issues/913 + 'H5124', // https://github.com/homebridge-plugins/homebridge-govee/issues/1119 'H5126', // https://github.com/homebridge-plugins/homebridge-govee/issues/910 'H5129', // https://github.com/homebridge-plugins/homebridge-govee/issues/1084 'H5107', // https://github.com/homebridge-plugins/homebridge-govee/issues/803 'H5125', // https://github.com/homebridge-plugins/homebridge-govee/issues/981 'H5185', // https://github.com/homebridge-plugins/homebridge-govee/issues/804 + 'H5191', // https://github.com/homebridge-plugins/homebridge-govee/issues/1121 ], }, From 759fda7c53108a87e359419c69f7e2186916a670 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 12:36:15 +0100 Subject: [PATCH 10/29] v11.1.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1e9c4f7..29bdb57a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to homebridge-govee will be documented in this file. -## v11.1.0 (Unreleased) +## v11.1.0 (2025-07-12) ### Notable Changes diff --git a/package-lock.json b/package-lock.json index 5d477754..a0b88f78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.0.2", + "version": "11.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.0.2", + "version": "11.1.0", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 2460c448..0abb7374 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@homebridge-plugins/homebridge-govee", "alias": "Govee", "type": "module", - "version": "11.0.2", + "version": "11.1.0", "description": "Homebridge plugin to integrate Govee devices into HomeKit.", "author": { "name": "bwp91", From 06ad8d52caee336bc25fe77bb612c9ecb4f39d08 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 13:09:28 +0100 Subject: [PATCH 11/29] fix plugin name in release workflow --- .github/workflows/release-latest.yml | 2 +- CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-latest.yml b/.github/workflows/release-latest.yml index 14a121af..70eeb517 100644 --- a/.github/workflows/release-latest.yml +++ b/.github/workflows/release-latest.yml @@ -50,7 +50,7 @@ jobs: BASE_VERSION="${VERSION%%-*}" # Compare base version to latest version using sort -V if [ "$(printf "%s\n%s" "$BASE_VERSION" "$LATEST_VERSION" | sort -V | head -n1)" != "$LATEST_VERSION" ]; then - npm deprecate @homebridge-plugins/homebridge-ecovacs@"$VERSION" "This beta version is deprecated in favor of the latest release." + npm deprecate @homebridge-plugins/homebridge-govee@"$VERSION" "This beta version is deprecated in favor of the latest release." echo "- Deprecated version: $VERSION (base: $BASE_VERSION)" DEPRECATED_VERSIONS+=("$VERSION") else diff --git a/CHANGELOG.md b/CHANGELOG.md index 29bdb57a..8ade60b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to homebridge-govee will be documented in this file. +## v11.1.1 (Unreleased) + +### Other Changes + +- fix plugin name in release workflow + ## v11.1.0 (2025-07-12) ### Notable Changes From d9d125cdaa6974d0346e50e772493019ba09b92e Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 13:19:44 +0100 Subject: [PATCH 12/29] support new govee models --- CHANGELOG.md | 7 ++++++- lib/utils/constants.js | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ade60b1..a95f43df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,12 @@ All notable changes to homebridge-govee will be documented in this file. -## v11.1.1 (Unreleased) +## v11.2.0 (Unreleased) + +### Notable Changes + +- support new govee models + - lights: `H60A4` ### Other Changes diff --git a/lib/utils/constants.js b/lib/utils/constants.js index 23a51bfe..75a74cb1 100644 --- a/lib/utils/constants.js +++ b/lib/utils/constants.js @@ -204,6 +204,7 @@ export default { 'H6099', 'H60A0', 'H60A1', + 'H60A4', 'H60A6', 'H60B0', 'H6101', From bdd50d7f9837c58b01baf0413e286b3316b0cfd9 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 13:22:13 +0100 Subject: [PATCH 13/29] add permissions to workflows --- .github/workflows/release-beta.yml | 4 +++- .github/workflows/release-latest.yml | 3 +++ CHANGELOG.md | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-beta.yml b/.github/workflows/release-beta.yml index 74a4b5c7..3bfd6457 100644 --- a/.github/workflows/release-beta.yml +++ b/.github/workflows/release-beta.yml @@ -9,7 +9,9 @@ name: Release (Beta) on: push: branches: [beta-*.*.*] - workflow_dispatch: + +permissions: + contents: read jobs: eslint: diff --git a/.github/workflows/release-latest.yml b/.github/workflows/release-latest.yml index 70eeb517..fc5cf9e1 100644 --- a/.github/workflows/release-latest.yml +++ b/.github/workflows/release-latest.yml @@ -9,6 +9,9 @@ on: release: types: [published] +permissions: + contents: read + jobs: eslint: uses: homebridge/.github/.github/workflows/eslint.yml@latest diff --git a/CHANGELOG.md b/CHANGELOG.md index a95f43df..3e12f5f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to homebridge-govee will be documented in this file. ### Other Changes - fix plugin name in release workflow +- add permissions to workflows ## v11.1.0 (2025-07-12) From 9d71c597a09f8082a892e48324fe34aca0ebcdc5 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 13:22:45 +0100 Subject: [PATCH 14/29] v11.2.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e12f5f0..ff7d30cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to homebridge-govee will be documented in this file. -## v11.2.0 (Unreleased) +## v11.2.0 (2025-07-12) ### Notable Changes diff --git a/package-lock.json b/package-lock.json index a0b88f78..778c2f0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.1.0", + "version": "11.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.1.0", + "version": "11.2.0", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 0abb7374..701d51b5 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@homebridge-plugins/homebridge-govee", "alias": "Govee", "type": "module", - "version": "11.1.0", + "version": "11.2.0", "description": "Homebridge plugin to integrate Govee devices into HomeKit.", "author": { "name": "bwp91", From b90a72583240bba803a9624155d1eb5757a45c18 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 13:42:55 +0100 Subject: [PATCH 15/29] fix permission in release workflow --- .github/workflows/release-latest.yml | 2 +- CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-latest.yml b/.github/workflows/release-latest.yml index fc5cf9e1..8ff3cb9b 100644 --- a/.github/workflows/release-latest.yml +++ b/.github/workflows/release-latest.yml @@ -10,7 +10,7 @@ on: types: [published] permissions: - contents: read + contents: write jobs: eslint: diff --git a/CHANGELOG.md b/CHANGELOG.md index ff7d30cf..a11d9d0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to homebridge-govee will be documented in this file. +## v11.2.1 (Unreleased) + +### Other Changes + +- fix permission in release workflow + ## v11.2.0 (2025-07-12) ### Notable Changes From 1e62e3ee87b168b9ef8a275b42486ad1bfa3ac65 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 12 Jul 2025 23:20:46 +0100 Subject: [PATCH 16/29] improvements to the deprecate workflow --- .github/workflows/deprecate-past-releases.yml | 122 ++++++++++++++++++ .github/workflows/release-latest.yml | 70 +--------- CHANGELOG.md | 1 + 3 files changed, 124 insertions(+), 69 deletions(-) create mode 100644 .github/workflows/deprecate-past-releases.yml diff --git a/.github/workflows/deprecate-past-releases.yml b/.github/workflows/deprecate-past-releases.yml new file mode 100644 index 00000000..fe7a4727 --- /dev/null +++ b/.github/workflows/deprecate-past-releases.yml @@ -0,0 +1,122 @@ +name: Deprecate Past Pre-Releases + +on: + workflow_dispatch: + +permissions: + contents: write + +jobs: + deprecate-previous-pre-release-data: + if: ${{ github.ref == 'refs/heads/latest' && github.repository == 'homebridge-plugins/homebridge-govee' }} + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + registry-url: https://registry.npmjs.org/ + + - name: Update npm to latest version + run: npm install -g npm@latest + + - name: Deprecate previous pre-release npm versions + run: | + HAS_ERROR=0 + # Read local package version + LATEST_VERSION=$(jq -r .version package.json) + echo "Latest version found in package.json: $LATEST_VERSION" + echo "" + DEPRECATED_VERSIONS=() + echo "Fetching pre-release versions of @homebridge-plugins/homebridge-govee from npm..." + # Fetch all non-deprecated pre-release versions from the registry + RESPONSE=$(curl -s -H "accept: application/vnd.npm.install-v1+json" "https://registry.npmjs.org/@homebridge-plugins/homebridge-govee") + BETA_VERSIONS=$(echo "$RESPONSE" | jq -c '[.versions[] | select(.deprecated == null and (.version | test("-"))) | .version]') + echo "Found $(echo "$BETA_VERSIONS" | jq 'length') pre-release versions:" + for VERSION in $(echo "$BETA_VERSIONS" | jq -r '.[]'); do + echo "* Processing version: $VERSION..." + BASE_VERSION="${VERSION%%-*}" # Strip pre-release part + # Deprecate if base version is less than or equal to latest version + if [ "$(printf "%s\n%s" "$BASE_VERSION" "$LATEST_VERSION" | sort -V | tail -n1)" == "$LATEST_VERSION" ]; then + if ! OUTPUT=$(npm deprecate @homebridge-plugins/homebridge-govee@"$VERSION" "This beta version is deprecated in favor of the latest release." 2>&1); then + echo "$OUTPUT" >&2 + if echo "$OUTPUT" | grep -q "E429"; then + echo "* Error: Rate limit exceeded (429). Stopping the step." >&2 + HAS_ERROR=2 + break + exit 1 + else + echo "* Error: failed to deprecate version $VERSION" >&2 + HAS_ERROR=1 + fi + else + echo "* Deprecated version: $VERSION" + DEPRECATED_VERSIONS+=("$VERSION") + fi + else + echo "* Skipped version: $VERSION" + fi + done + echo "" + echo "" + echo "Step Summary" + if [ ${#DEPRECATED_VERSIONS[@]} -eq 0 ]; then + echo "* No versions were deprecated." + else + echo "* Deprecated ${#DEPRECATED_VERSIONS[@]} pre-release versions:" + for VERSION in "${DEPRECATED_VERSIONS[@]}"; do + echo " * $VERSION" + done + fi + if [ $HAS_ERROR -eq 0 ]; then + echo "* No versions reported an error while being deprecated." + elif [ $HAS_ERROR -eq 1 ]; then + echo "* Some versions reported an error while being deprecated - check the logs above." + elif [ $HAS_ERROR -eq 2 ]; then + echo "* The step needed to stop early due to detecting a 429 rate limit - retry the action later." + fi + env: + NODE_AUTH_TOKEN: ${{ secrets.npm_token }} + + - name: Delete previous pre-release GitHub releases + run: | + LATEST_VERSION=$(jq -r .version package.json) + echo "Latest version found in package.json: $LATEST_VERSION" + echo "Finding GitHub releases with a hyphen in the tag name..." + + gh release list --limit 100 --json tagName --jq '.[] | select(.tagName | test("-"; "i")) | .tagName' | while read -r TAG; do + BASE_VERSION="${TAG%%-*}" + + if [ "$(printf "%s\n%s" "$BASE_VERSION" "$LATEST_VERSION" | sort -V | tail -n1)" == "$LATEST_VERSION" ]; then + echo "Deleting GitHub release: $TAG (base version: $BASE_VERSION)" + gh release delete "$TAG" --yes + else + echo "Skipping GitHub release: $TAG (base version: $BASE_VERSION is newer than $LATEST_VERSION)" + fi + done + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Delete previous pre-release Git tags + run: | + LATEST_VERSION=$(jq -r .version package.json) + echo "Latest version found in package.json: $LATEST_VERSION" + echo "Fetching tags from origin..." + git fetch --tags + + echo "Finding pre-release tags with a hyphen in the name..." + git tag -l "*-*" | while read -r TAG; do + BASE_VERSION="${TAG%%-*}" + + if [ "$(printf "%s\n%s" "$BASE_VERSION" "$LATEST_VERSION" | sort -V | tail -n1)" == "$LATEST_VERSION" ]; then + echo "Deleting tag: $TAG (base version: $BASE_VERSION)" + git push origin ":refs/tags/$TAG" + else + echo "Skipping tag: $TAG (base version: $BASE_VERSION is newer than $LATEST_VERSION)" + fi + done + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-latest.yml b/.github/workflows/release-latest.yml index 8ff3cb9b..980b0b25 100644 --- a/.github/workflows/release-latest.yml +++ b/.github/workflows/release-latest.yml @@ -10,7 +10,7 @@ on: types: [published] permissions: - contents: write + contents: read jobs: eslint: @@ -24,71 +24,3 @@ jobs: uses: homebridge/.github/.github/workflows/npm-publish-esm.yml@latest secrets: npm_auth_token: ${{ secrets.npm_token }} - - deprecate-previous-pre-release-data: - if: ${{ github.repository == 'homebridge-plugins/homebridge-govee' }} - runs-on: ubuntu-latest - needs: - - eslint - - publish - steps: - - name: Check out repository - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - registry-url: https://registry.npmjs.org/ - - - name: Deprecate previous pre-release NPM versions - run: | - # Read local package version - LATEST_VERSION=$(jq -r .version package.json) - echo "Latest version found in package.json: $LATEST_VERSION" - DEPRECATED_VERSIONS=() - # Get all beta versions (versions with a hyphen) - mapfile -t BETA_VERSIONS < <(npm view @homebridge-plugins/homebridge-govee versions --json | jq -r '.[]' | grep -- '-') - for VERSION in "${BETA_VERSIONS[@]}"; do - BASE_VERSION="${VERSION%%-*}" - # Compare base version to latest version using sort -V - if [ "$(printf "%s\n%s" "$BASE_VERSION" "$LATEST_VERSION" | sort -V | head -n1)" != "$LATEST_VERSION" ]; then - npm deprecate @homebridge-plugins/homebridge-govee@"$VERSION" "This beta version is deprecated in favor of the latest release." - echo "- Deprecated version: $VERSION (base: $BASE_VERSION)" - DEPRECATED_VERSIONS+=("$VERSION") - else - echo "- Skipped version: $VERSION (base: $BASE_VERSION)" - fi - done - if [ ${#DEPRECATED_VERSIONS[@]} -eq 0 ]; then - echo "No versions were deprecated." - else - echo "Deprecated versions:" - for VERSION in "${DEPRECATED_VERSIONS[@]}"; do - echo "- $VERSION" - done - fi - env: - NODE_AUTH_TOKEN: ${{ secrets.npm_token }} - - - name: Delete previous pre-release GitHub releases - run: | - echo "Finding GitHub releases with a hyphen in the tag name..." - gh release list --limit 100 --json tagName,name --jq '.[] | select(.tagName | test("-"; "i")) | .tagName' | while read -r TAG; do - echo "Deleting GitHub release: $TAG" - gh release delete "$TAG" --yes - done - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Delete previous pre-release Git tags - run: | - echo "Fetching tags from origin..." - git fetch --tags - echo "Finding tags with a hyphen in the name..." - git tag -l "*-*" | while read -r TAG; do - echo "Deleting tag: $TAG" - git push origin ":refs/tags/$TAG" - done - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index a11d9d0d..c3d85fe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to homebridge-govee will be documented in this file. ### Other Changes - fix permission in release workflow +- improvements to the deprecate workflow ## v11.2.0 (2025-07-12) From 843dbcd8f1c6404d2eced205808a92bdc299fb37 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 13 Jul 2025 00:43:07 +0100 Subject: [PATCH 17/29] fix custom plugin config modal styles in ui 5 --- CHANGELOG.md | 4 +++ lib/homebridge-ui/public/index.html | 38 ++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3d85fe5..c9898d3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to homebridge-govee will be documented in this file. ## v11.2.1 (Unreleased) +### Notable Changes + +- fix custom plugin config modal styles in ui 5 + ### Other Changes - fix permission in release workflow diff --git a/lib/homebridge-ui/public/index.html b/lib/homebridge-ui/public/index.html index 94cd2400..21337886 100644 --- a/lib/homebridge-ui/public/index.html +++ b/lib/homebridge-ui/public/index.html @@ -1,3 +1,39 @@ +

- + From 77553e7070da51e00577cb7d1f4f46b1bd196f07 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 13 Jul 2025 22:31:54 +0100 Subject: [PATCH 18/29] fix custom characteristics for hb 2 --- CHANGELOG.md | 1 + lib/utils/custom-chars.js | 387 +++++++++++++++++++++----------------- 2 files changed, 212 insertions(+), 176 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9898d3e..c4e9061c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to homebridge-govee will be documented in this file. ### Notable Changes - fix custom plugin config modal styles in ui 5 +- fix custom characteristics for hb 2 ### Other Changes diff --git a/lib/utils/custom-chars.js b/lib/utils/custom-chars.js index f0bc8727..6d7f4e72 100644 --- a/lib/utils/custom-chars.js +++ b/lib/utils/custom-chars.js @@ -1,9 +1,5 @@ -import { inherits } from 'node:util' - export default class { constructor(api) { - this.hapServ = api.hap.Service - this.hapChar = api.hap.Characteristic this.uuids = { /* deprecated bluetooth: 'E964F001-079E-48FF-8F27-9C2605A29F52' @@ -30,178 +26,217 @@ export default class { nightLight: 'E964F021-079E-48FF-8F27-9C2605A29F52', displayLight: 'E964F022-079E-48FF-8F27-9C2605A29F52', } - const self = this - this.ColourMode = function ColourMode() { - self.hapChar.call(this, 'Colour Mode', self.uuids.colourMode) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.MusicMode = function MusicMode() { - self.hapChar.call(this, 'Music Mode', self.uuids.musicMode) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.MusicModeTwo = function MusicModeTwo() { - self.hapChar.call(this, 'Music Mode 2', self.uuids.musicModeTwo) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.Scene = function Scene() { - self.hapChar.call(this, 'Scene', self.uuids.scene) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.SceneTwo = function SceneTwo() { - self.hapChar.call(this, 'Scene 2', self.uuids.sceneTwo) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.SceneThree = function SceneThree() { - self.hapChar.call(this, 'Scene 3', self.uuids.sceneThree) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.SceneFour = function SceneFour() { - self.hapChar.call(this, 'Scene 4', self.uuids.sceneFour) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.DiyMode = function DiyMode() { - self.hapChar.call(this, 'DIY Mode', self.uuids.diyMode) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.DiyModeTwo = function DiyModeTwo() { - self.hapChar.call(this, 'DIY Mode 2', self.uuids.diyModeTwo) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.DiyModeThree = function DiyModeThree() { - self.hapChar.call(this, 'DIY Mode 3', self.uuids.diyModeThree) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.DiyModeFour = function DiyModeFour() { - self.hapChar.call(this, 'DIY Mode 4', self.uuids.diyModeFour) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.Segmented = function Segmented() { - self.hapChar.call(this, 'Segmented', self.uuids.segmented) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.SegmentedTwo = function SegmentedTwo() { - self.hapChar.call(this, 'Segmented 2', self.uuids.segmentedTwo) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.SegmentedThree = function SegmentedThree() { - self.hapChar.call(this, 'Segmented 3', self.uuids.segmentedThree) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.SegmentedFour = function SegmentedFour() { - self.hapChar.call(this, 'Segmented 4', self.uuids.segmentedFour) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.VideoMode = function VideoMode() { - self.hapChar.call(this, 'Video Mode', self.uuids.videoMode) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.VideoModeTwo = function VideoModeTwo() { - self.hapChar.call(this, 'Video Mode 2', self.uuids.videoModeTwo) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.NightLight = function NightLight() { - self.hapChar.call(this, 'Night Light', self.uuids.nightLight) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - this.DisplayLight = function DisplayLight() { - self.hapChar.call(this, 'Display Light', self.uuids.displayLight) - this.setProps({ - format: api.hap.Formats.BOOL, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() - } - inherits(this.ColourMode, this.hapChar) - inherits(this.MusicMode, this.hapChar) - inherits(this.MusicModeTwo, this.hapChar) - inherits(this.Scene, this.hapChar) - inherits(this.SceneTwo, this.hapChar) - inherits(this.SceneThree, this.hapChar) - inherits(this.SceneFour, this.hapChar) - inherits(this.DiyMode, this.hapChar) - inherits(this.DiyModeTwo, this.hapChar) - inherits(this.DiyModeThree, this.hapChar) - inherits(this.DiyModeFour, this.hapChar) - inherits(this.Segmented, this.hapChar) - inherits(this.SegmentedTwo, this.hapChar) - inherits(this.SegmentedThree, this.hapChar) - inherits(this.SegmentedFour, this.hapChar) - inherits(this.VideoMode, this.hapChar) - inherits(this.VideoModeTwo, this.hapChar) - inherits(this.NightLight, this.hapChar) - inherits(this.DisplayLight, this.hapChar) + const uuids = this.uuids + + this.ColourMode = class extends api.hap.Characteristic { + constructor() { + super('Colour Mode', uuids.colourMode) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.MusicMode = class extends api.hap.Characteristic { + constructor() { + super('Music Mode', uuids.musicMode) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.MusicModeTwo = class extends api.hap.Characteristic { + constructor() { + super('Music Mode 2', uuids.musicModeTwo) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.Scene = class extends api.hap.Characteristic { + constructor() { + super('Scene', uuids.scene) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.SceneTwo = class extends api.hap.Characteristic { + constructor() { + super('Scene 2', uuids.sceneTwo) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.SceneThree = class extends api.hap.Characteristic { + constructor() { + super('Scene 3', uuids.sceneThree) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.SceneFour = class extends api.hap.Characteristic { + constructor() { + super('Scene 4', uuids.sceneFour) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.DiyMode = class extends api.hap.Characteristic { + constructor() { + super('DIY Mode', uuids.diyMode) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.DiyModeTwo = class extends api.hap.Characteristic { + constructor() { + super('DIY Mode 2', uuids.diyModeTwo) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.DiyModeThree = class extends api.hap.Characteristic { + constructor() { + super('DIY Mode 3', uuids.diyModeThree) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.DiyModeFour = class extends api.hap.Characteristic { + constructor() { + super('DIY Mode 4', uuids.diyModeFour) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.Segmented = class extends api.hap.Characteristic { + constructor() { + super('Segmented', uuids.segmented) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.SegmentedTwo = class extends api.hap.Characteristic { + constructor() { + super('Segmented 2', uuids.segmentedTwo) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.SegmentedThree = class extends api.hap.Characteristic { + constructor() { + super('Segmented 3', uuids.segmentedThree) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.SegmentedFour = class extends api.hap.Characteristic { + constructor() { + super('Segmented 4', uuids.segmentedFour) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.VideoMode = class extends api.hap.Characteristic { + constructor() { + super('Video Mode', uuids.videoMode) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.VideoModeTwo = class extends api.hap.Characteristic { + constructor() { + super('Video Mode 2', uuids.videoModeTwo) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.NightLight = class extends api.hap.Characteristic { + constructor() { + super('Night Light', uuids.nightLight) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + + this.DisplayLight = class extends api.hap.Characteristic { + constructor() { + super('Display Light', uuids.displayLight) + this.setProps({ + format: api.hap.Formats.BOOL, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.PAIRED_WRITE, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } + } + this.ColourMode.UUID = this.uuids.colourMode this.MusicMode.UUID = this.uuids.musicMode this.MusicModeTwo.UUID = this.uuids.musicModeTwo From 8fe56f711fe51fc6e0cfddeb9b3d80f2a2f69a52 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 13 Jul 2025 22:33:02 +0100 Subject: [PATCH 19/29] v11.3.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4e9061c..0293b988 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to homebridge-govee will be documented in this file. -## v11.2.1 (Unreleased) +## v11.3.0 (2025-07-13) ### Notable Changes diff --git a/package-lock.json b/package-lock.json index 778c2f0f..4973d1dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.2.0", + "version": "11.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.2.0", + "version": "11.3.0", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 701d51b5..3957e34b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@homebridge-plugins/homebridge-govee", "alias": "Govee", "type": "module", - "version": "11.2.0", + "version": "11.3.0", "description": "Homebridge plugin to integrate Govee devices into HomeKit.", "author": { "name": "bwp91", From 33be5615fe3ebc51dcc25878f18cc94a222c1c47 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 13 Jul 2025 22:39:33 +0100 Subject: [PATCH 20/29] fix eve characteristics for hb 2 --- CHANGELOG.md | 6 +++ lib/utils/eve-chars.js | 106 ++++++++++++++++++++++------------------- 2 files changed, 62 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0293b988..074f4309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to homebridge-govee will be documented in this file. +## v11.3.1 (Unreleased) + +### Notable Changes + +- fix eve characteristics for hb 2 + ## v11.3.0 (2025-07-13) ### Notable Changes diff --git a/lib/utils/eve-chars.js b/lib/utils/eve-chars.js index 2cdb7cdf..0fdfacb0 100644 --- a/lib/utils/eve-chars.js +++ b/lib/utils/eve-chars.js @@ -1,65 +1,71 @@ -import { inherits } from 'node:util' - export default class { constructor(api) { - this.hapServ = api.hap.Service - this.hapChar = api.hap.Characteristic this.uuids = { currentConsumption: 'E863F10D-079E-48FF-8F27-9C2605A29F52', voltage: 'E863F10A-079E-48FF-8F27-9C2605A29F52', electricCurrent: 'E863F126-079E-48FF-8F27-9C2605A29F52', lastActivation: 'E863F11A-079E-48FF-8F27-9C2605A29F52', } - const self = this - this.CurrentConsumption = function CurrentConsumption() { - self.hapChar.call(this, 'Current Consumption', self.uuids.currentConsumption) - this.setProps({ - format: api.hap.Formats.UINT16, - unit: 'W', - maxValue: 100000, - minValue: 0, - minStep: 1, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() + + const uuids = this.uuids + + this.CurrentConsumption = class extends api.hap.Characteristic { + constructor() { + super('Current Consumption', uuids.currentConsumption) + this.setProps({ + format: api.hap.Formats.UINT16, + unit: 'W', + maxValue: 100000, + minValue: 0, + minStep: 1, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } } - this.Voltage = function Voltage() { - self.hapChar.call(this, 'Voltage', self.uuids.voltage) - this.setProps({ - format: api.hap.Formats.FLOAT, - unit: 'V', - maxValue: 100000000000, - minValue: 0, - minStep: 1, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() + + this.Voltage = class extends api.hap.Characteristic { + constructor() { + super('Voltage', uuids.voltage) + this.setProps({ + format: api.hap.Formats.FLOAT, + unit: 'V', + maxValue: 100000000000, + minValue: 0, + minStep: 1, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } } - this.ElectricCurrent = function ElectricCurrent() { - self.hapChar.call(this, 'Electric Current', self.uuids.electricCurrent) - this.setProps({ - format: api.hap.Formats.FLOAT, - unit: 'A', - maxValue: 100000000000, - minValue: 0, - minStep: 0.1, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() + + this.ElectricCurrent = class extends api.hap.Characteristic { + constructor() { + super('Electric Current', uuids.electricCurrent) + this.setProps({ + format: api.hap.Formats.FLOAT, + unit: 'A', + maxValue: 100000000000, + minValue: 0, + minStep: 0.1, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } } - this.LastActivation = function LastActivation() { - self.hapChar.call(this, 'Last Activation', self.uuids.lastActivation) - this.setProps({ - format: api.hap.Formats.UINT32, - unit: api.hap.Units.SECONDS, - perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY], - }) - this.value = this.getDefaultValue() + + this.LastActivation = class extends api.hap.Characteristic { + constructor() { + super('Last Activation', uuids.lastActivation) + this.setProps({ + format: api.hap.Formats.UINT32, + unit: api.hap.Units.SECONDS, + perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY], + }) + this.value = this.getDefaultValue() + } } - inherits(this.CurrentConsumption, this.hapChar) - inherits(this.Voltage, this.hapChar) - inherits(this.ElectricCurrent, this.hapChar) - inherits(this.LastActivation, this.hapChar) + this.CurrentConsumption.UUID = this.uuids.currentConsumption this.Voltage.UUID = this.uuids.voltage this.ElectricCurrent.UUID = this.uuids.electricCurrent From 6f63af45bee0d374c85f012ad4780c5b1cafabe0 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 13 Jul 2025 22:39:51 +0100 Subject: [PATCH 21/29] v11.3.1 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 074f4309..9e7d0c80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to homebridge-govee will be documented in this file. -## v11.3.1 (Unreleased) +## v11.3.1 (2025-07-13) ### Notable Changes diff --git a/package-lock.json b/package-lock.json index 4973d1dd..904463f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.3.0", + "version": "11.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.3.0", + "version": "11.3.1", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 3957e34b..4ad495f4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@homebridge-plugins/homebridge-govee", "alias": "Govee", "type": "module", - "version": "11.3.0", + "version": "11.3.1", "description": "Homebridge plugin to integrate Govee devices into HomeKit.", "author": { "name": "bwp91", From bfe76d0d4729368335933cc8e456958017a7ea42 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Wed, 16 Jul 2025 19:57:56 +0100 Subject: [PATCH 22/29] add option to hide fan light (H7105) --- CHANGELOG.md | 6 ++ config.schema.json | 11 ++- lib/device/fan-H7105.js | 114 +++++++++++++---------- lib/platform.js | 1 + lib/utils/constants.js | 2 +- package-lock.json | 199 ++++++++++++++++++++-------------------- package.json | 2 +- 7 files changed, 185 insertions(+), 150 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e7d0c80..c3f6d354 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to homebridge-govee will be documented in this file. +## v11.4.0 (Unreleased) + +### Notable Changes + +- add option to hide fan light (H7105) + ## v11.3.1 (2025-07-13) ### Notable Changes diff --git a/config.schema.json b/config.schema.json index 995aa91d..28b3dcbb 100644 --- a/config.schema.json +++ b/config.schema.json @@ -1153,6 +1153,14 @@ "condition": { "functionBody": "return (model.fanDevices && model.fanDevices[arrayIndices] && model.fanDevices[arrayIndices].deviceId && model.fanDevices[arrayIndices].deviceId.length === 23);" } + }, + "hideLight": { + "type": "boolean", + "title": "Hide Light", + "description": "Enable this to not expose the light service in Homebridge/Homekit if your fan has one.", + "condition": { + "functionBody": "return (model.fanDevices && model.fanDevices[arrayIndices] && model.fanDevices[arrayIndices].deviceId && model.fanDevices[arrayIndices].deviceId.length === 23 && !model.fanDevices[arrayIndices].ignoreDevice);" + } } } } @@ -1604,7 +1612,8 @@ "items": [ "fanDevices[].label", "fanDevices[].deviceId", - "fanDevices[].ignoreDevice" + "fanDevices[].ignoreDevice", + "fanDevices[].hideLight" ] } ] diff --git a/lib/device/fan-H7105.js b/lib/device/fan-H7105.js index cf71c6ec..9789540a 100644 --- a/lib/device/fan-H7105.js +++ b/lib/device/fan-H7105.js @@ -22,6 +22,10 @@ export default class { // Set up variables from the accessory this.accessory = accessory + // Set up custom variables for this device type + const deviceConf = platform.deviceConf[accessory.context.gvDeviceId] + this.hideLight = deviceConf && deviceConf.hideLight + // Codes etc this.speedCodes = { 7: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=', @@ -46,9 +50,6 @@ export default class { // Add the fan service for the fan if it doesn't already exist this.service = this.accessory.getService(this.hapServ.Fanv2) || this.accessory.addService(this.hapServ.Fanv2) - // Add the night light service if it doesn't already exist - this.lightService = this.accessory.getService(this.hapServ.Lightbulb) || this.accessory.addService(this.hapServ.Lightbulb) - // Add the set handler to the fan on/off characteristic this.service .getCharacteristic(this.hapChar.Active) @@ -73,29 +74,41 @@ export default class { .onSet(async value => this.internalSwingUpdate(value)) this.cacheSwing = this.service.getCharacteristic(this.hapChar.SwingMode).value === 1 ? 'on' : 'off' - // Add the set handler to the lightbulb on/off characteristic - this.lightService.getCharacteristic(this.hapChar.On).onSet(async (value) => { - await this.internalLightStateUpdate(value) - }) - this.cacheLightState = this.lightService.getCharacteristic(this.hapChar.On).value ? 'on' : 'off' + if (this.hideLight) { + if (this.accessory.getService(this.hapServ.Lightbulb)) { + // Remove the light service if it exists + this.accessory.removeService(this.accessory.getService(this.hapServ.Lightbulb)) + } + } else { + // Add the night light service if it doesn't already exist + this.lightService = this.accessory.getService(this.hapServ.Lightbulb) || this.accessory.addService(this.hapServ.Lightbulb) - // Add the set handler to the lightbulb brightness characteristic - this.lightService - .getCharacteristic(this.hapChar.Brightness) - .onSet(async (value) => { - await this.internalBrightnessUpdate(value) + // Add the set handler to the lightbulb on/off characteristic + this.lightService.getCharacteristic(this.hapChar.On).onSet(async (value) => { + await this.internalLightStateUpdate(value) }) - this.cacheBright = this.lightService.getCharacteristic(this.hapChar.Brightness).value - - // Add the set handler to the lightbulb hue characteristic - this.lightService.getCharacteristic(this.hapChar.Hue).onSet(async (value) => { - await this.internalColourUpdate(value) - }) - this.cacheHue = this.lightService.getCharacteristic(this.hapChar.Hue).value - this.cacheSat = this.lightService.getCharacteristic(this.hapChar.Saturation).value + this.cacheLightState = this.lightService.getCharacteristic(this.hapChar.On).value ? 'on' : 'off' + + // Add the set handler to the lightbulb brightness characteristic + this.lightService + .getCharacteristic(this.hapChar.Brightness) + .onSet(async (value) => { + await this.internalBrightnessUpdate(value) + }) + this.cacheBright = this.lightService.getCharacteristic(this.hapChar.Brightness).value + + // Add the set handler to the lightbulb hue characteristic + this.lightService.getCharacteristic(this.hapChar.Hue).onSet(async (value) => { + await this.internalColourUpdate(value) + }) + this.cacheHue = this.lightService.getCharacteristic(this.hapChar.Hue).value + this.cacheSat = this.lightService.getCharacteristic(this.hapChar.Saturation).value + } // Output the customised options to the log - const opts = JSON.stringify({}) + const opts = JSON.stringify({ + hideLight: this.hideLight, + }) platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts) } @@ -450,37 +463,42 @@ export default class { break } case '1b01': { - const newLightState = getTwoItemPosition(hexParts, 4) === '01' ? 'on' : 'off' - if (this.cacheLightState !== newLightState) { - this.cacheLightState = newLightState - this.lightService.updateCharacteristic(this.hapChar.On, this.cacheLightState === 'on') - this.accessory.log(`${platformLang.curLight} [${this.cacheLightState}]`) - } - const newBrightness = hexToDecimal(getTwoItemPosition(hexParts, 5)) - if (this.cacheBright !== newBrightness) { - this.cacheBright = newBrightness - this.lightService.updateCharacteristic(this.hapChar.Brightness, this.cacheBright) - this.accessory.log(`${platformLang.curBright} [${this.cacheBright}%]`) + // Night light on/off + if (!this.hideLight) { + const newLightState = getTwoItemPosition(hexParts, 4) === '01' ? 'on' : 'off' + if (this.cacheLightState !== newLightState) { + this.cacheLightState = newLightState + this.lightService.updateCharacteristic(this.hapChar.On, this.cacheLightState === 'on') + this.accessory.log(`${platformLang.curLight} [${this.cacheLightState}]`) + } + const newBrightness = hexToDecimal(getTwoItemPosition(hexParts, 5)) + if (this.cacheBright !== newBrightness) { + this.cacheBright = newBrightness + this.lightService.updateCharacteristic(this.hapChar.Brightness, this.cacheBright) + this.accessory.log(`${platformLang.curBright} [${this.cacheBright}%]`) + } } break } case '1b05': { // Night light colour - const newR = hexToDecimal(getTwoItemPosition(hexParts, 5)) - const newG = hexToDecimal(getTwoItemPosition(hexParts, 6)) - const newB = hexToDecimal(getTwoItemPosition(hexParts, 7)) - - const hs = rgb2hs(newR, newG, newB) - - // Check for a colour change - if (hs[0] !== this.cacheHue) { - // Colour is different so update Homebridge with new values - this.lightService.updateCharacteristic(this.hapChar.Hue, hs[0]) - this.lightService.updateCharacteristic(this.hapChar.Saturation, hs[1]); - [this.cacheHue] = hs - - // Log the change - this.accessory.log(`${platformLang.curColour} [rgb ${newR} ${newG} ${newB}]`) + if (!this.hideLight) { + const newR = hexToDecimal(getTwoItemPosition(hexParts, 5)) + const newG = hexToDecimal(getTwoItemPosition(hexParts, 6)) + const newB = hexToDecimal(getTwoItemPosition(hexParts, 7)) + + const hs = rgb2hs(newR, newG, newB) + + // Check for a colour change + if (hs[0] !== this.cacheHue) { + // Colour is different so update Homebridge with new values + this.lightService.updateCharacteristic(this.hapChar.Hue, hs[0]) + this.lightService.updateCharacteristic(this.hapChar.Saturation, hs[1]); + [this.cacheHue] = hs + + // Log the change + this.accessory.log(`${platformLang.curColour} [rgb ${newR} ${newG} ${newB}]`) + } } break } diff --git a/lib/platform.js b/lib/platform.js index b0bc1687..efa2158a 100644 --- a/lib/platform.js +++ b/lib/platform.js @@ -200,6 +200,7 @@ export default class { break } case 'awsBrightnessNoScale': + case 'hideLight': case 'hideModeGreenTea': case 'hideModeOolongTea': case 'hideModeCoffee': diff --git a/lib/utils/constants.js b/lib/utils/constants.js index 75a74cb1..2722b537 100644 --- a/lib/utils/constants.js +++ b/lib/utils/constants.js @@ -91,7 +91,7 @@ export default { ], leakDevices: ['label', 'deviceId', 'ignoreDevice', 'lowBattThreshold'], thermoDevices: ['label', 'deviceId', 'ignoreDevice', 'lowBattThreshold', 'showExtraSwitch'], - fanDevices: ['label', 'deviceId', 'ignoreDevice'], + fanDevices: ['label', 'deviceId', 'ignoreDevice', 'hideLight'], heaterDevices: ['label', 'deviceId', 'ignoreDevice', 'tempReporting'], humidifierDevices: ['label', 'deviceId', 'ignoreDevice'], dehumidifierDevices: ['label', 'deviceId', 'ignoreDevice'], diff --git a/package-lock.json b/package-lock.json index 904463f2..9818e112 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "pem": "^1.14.8" }, "devDependencies": { - "@antfu/eslint-config": "^4.16.2" + "@antfu/eslint-config": "^4.17.0" }, "engines": { "homebridge": "^1.6.0 || ^2.0.0-beta.0", @@ -48,19 +48,19 @@ } }, "node_modules/@antfu/eslint-config": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-4.16.2.tgz", - "integrity": "sha512-5KHZR+7ne+HZnOJUKeTTdHKYA/yOygPssaJ7TZOMoBqjSMtVAa7FO5Wvu2dEtkibM6v3emYyKnQnia1S8NHQeA==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-4.17.0.tgz", + "integrity": "sha512-S1y0A1+0DcpV6GmjwB9gQCQc7ni9zlKa3MQRqRCEZ0E1WW+nRL1BUwnbk3DpMJAMsb3UIAt1lsAiIBnvIw2NDw==", "dev": true, "license": "MIT", "dependencies": { "@antfu/install-pkg": "^1.1.0", "@clack/prompts": "^0.11.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", - "@eslint/markdown": "^6.6.0", + "@eslint/markdown": "^7.0.0", "@stylistic/eslint-plugin": "^5.1.0", - "@typescript-eslint/eslint-plugin": "^8.35.1", - "@typescript-eslint/parser": "^8.35.1", + "@typescript-eslint/eslint-plugin": "^8.37.0", + "@typescript-eslint/parser": "^8.37.0", "@vitest/eslint-plugin": "^1.3.4", "ansis": "^4.1.0", "cac": "^6.7.14", @@ -70,17 +70,17 @@ "eslint-plugin-antfu": "^3.1.1", "eslint-plugin-command": "^3.3.1", "eslint-plugin-import-lite": "^0.3.0", - "eslint-plugin-jsdoc": "^51.3.2", + "eslint-plugin-jsdoc": "^51.3.4", "eslint-plugin-jsonc": "^2.20.1", - "eslint-plugin-n": "^17.20.0", + "eslint-plugin-n": "^17.21.0", "eslint-plugin-no-only-tests": "^3.3.0", "eslint-plugin-perfectionist": "^4.15.0", - "eslint-plugin-pnpm": "^0.3.1", + "eslint-plugin-pnpm": "^1.0.0", "eslint-plugin-regexp": "^2.9.0", "eslint-plugin-toml": "^0.12.0", "eslint-plugin-unicorn": "^59.0.1", "eslint-plugin-unused-imports": "^4.1.4", - "eslint-plugin-vue": "^10.2.0", + "eslint-plugin-vue": "^10.3.0", "eslint-plugin-yml": "^1.18.0", "eslint-processor-vue-blocks": "^2.0.0", "globals": "^16.3.0", @@ -492,9 +492,9 @@ } }, "node_modules/@eslint/markdown": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.6.0.tgz", - "integrity": "sha512-IsWPy2jU3gaQDlioDC4sT4I4kG1hX1OMWs/q2sWwJrPoMASHW/Z4SDw+6Aql6EsHejGbagYuJbFq9Zvx+Y1b1Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-7.0.0.tgz", + "integrity": "sha512-0WNH6pSFHNlWSlNaIFQP0sLHpMUJw1FaJtyqapvGqOt0ISRgTUkTLVT0hT/zekDA1QlP2TT8pwjPkqYTu2s8yg==", "dev": true, "license": "MIT", "workspaces": [ @@ -1041,18 +1041,18 @@ } }, "node_modules/@stylistic/eslint-plugin": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.1.0.tgz", - "integrity": "sha512-TJRJul4u/lmry5N/kyCU+7RWWOk0wyXN+BncRlDYBqpLFnzXkd7QGVfN7KewarFIXv0IX0jSF/Ksu7aHWEDeuw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.2.0.tgz", + "integrity": "sha512-RCEdbREv9EBiToUBQTlRhVYKG093I6ZnnQ990j08eJ6uRZh71DXkOnoxtTLfDQ6utVCVQzrhZFHZP0zfrfOIjA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/types": "^8.34.1", + "@typescript-eslint/types": "^8.37.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "estraverse": "^5.3.0", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1103,9 +1103,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.0.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.13.tgz", - "integrity": "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==", + "version": "24.0.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.14.tgz", + "integrity": "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw==", "license": "MIT", "dependencies": { "undici-types": "~7.8.0" @@ -1135,17 +1135,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.36.0.tgz", - "integrity": "sha512-lZNihHUVB6ZZiPBNgOQGSxUASI7UJWhT8nHyUGCnaQ28XFCw98IfrMCG3rUl1uwUWoAvodJQby2KTs79UTcrAg==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.37.0.tgz", + "integrity": "sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.36.0", - "@typescript-eslint/type-utils": "8.36.0", - "@typescript-eslint/utils": "8.36.0", - "@typescript-eslint/visitor-keys": "8.36.0", + "@typescript-eslint/scope-manager": "8.37.0", + "@typescript-eslint/type-utils": "8.37.0", + "@typescript-eslint/utils": "8.37.0", + "@typescript-eslint/visitor-keys": "8.37.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -1159,7 +1159,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.36.0", + "@typescript-eslint/parser": "^8.37.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -1175,16 +1175,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.36.0.tgz", - "integrity": "sha512-FuYgkHwZLuPbZjQHzJXrtXreJdFMKl16BFYyRrLxDhWr6Qr7Kbcu2s1Yhu8tsiMXw1S0W1pjfFfYEt+R604s+Q==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.37.0.tgz", + "integrity": "sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.36.0", - "@typescript-eslint/types": "8.36.0", - "@typescript-eslint/typescript-estree": "8.36.0", - "@typescript-eslint/visitor-keys": "8.36.0", + "@typescript-eslint/scope-manager": "8.37.0", + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/typescript-estree": "8.37.0", + "@typescript-eslint/visitor-keys": "8.37.0", "debug": "^4.3.4" }, "engines": { @@ -1200,14 +1200,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.36.0.tgz", - "integrity": "sha512-JAhQFIABkWccQYeLMrHadu/fhpzmSQ1F1KXkpzqiVxA/iYI6UnRt2trqXHt1sYEcw1mxLnB9rKMsOxXPxowN/g==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.37.0.tgz", + "integrity": "sha512-BIUXYsbkl5A1aJDdYJCBAo8rCEbAvdquQ8AnLb6z5Lp1u3x5PNgSSx9A/zqYc++Xnr/0DVpls8iQ2cJs/izTXA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.36.0", - "@typescript-eslint/types": "^8.36.0", + "@typescript-eslint/tsconfig-utils": "^8.37.0", + "@typescript-eslint/types": "^8.37.0", "debug": "^4.3.4" }, "engines": { @@ -1222,14 +1222,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.36.0.tgz", - "integrity": "sha512-wCnapIKnDkN62fYtTGv2+RY8FlnBYA3tNm0fm91kc2BjPhV2vIjwwozJ7LToaLAyb1ca8BxrS7vT+Pvvf7RvqA==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.37.0.tgz", + "integrity": "sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.36.0", - "@typescript-eslint/visitor-keys": "8.36.0" + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/visitor-keys": "8.37.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1240,9 +1240,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.36.0.tgz", - "integrity": "sha512-Nhh3TIEgN18mNbdXpd5Q8mSCBnrZQeY9V7Ca3dqYvNDStNIGRmJA6dmrIPMJ0kow3C7gcQbpsG2rPzy1Ks/AnA==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.37.0.tgz", + "integrity": "sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg==", "dev": true, "license": "MIT", "engines": { @@ -1257,14 +1257,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.36.0.tgz", - "integrity": "sha512-5aaGYG8cVDd6cxfk/ynpYzxBRZJk7w/ymto6uiyUFtdCozQIsQWh7M28/6r57Fwkbweng8qAzoMCPwSJfWlmsg==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.37.0.tgz", + "integrity": "sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.36.0", - "@typescript-eslint/utils": "8.36.0", + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/typescript-estree": "8.37.0", + "@typescript-eslint/utils": "8.37.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -1281,9 +1282,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.36.0.tgz", - "integrity": "sha512-xGms6l5cTJKQPZOKM75Dl9yBfNdGeLRsIyufewnxT4vZTrjC0ImQT4fj8QmtJK84F58uSh5HVBSANwcfiXxABQ==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.37.0.tgz", + "integrity": "sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ==", "dev": true, "license": "MIT", "engines": { @@ -1295,16 +1296,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.36.0.tgz", - "integrity": "sha512-JaS8bDVrfVJX4av0jLpe4ye0BpAaUW7+tnS4Y4ETa3q7NoZgzYbN9zDQTJ8kPb5fQ4n0hliAt9tA4Pfs2zA2Hg==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.37.0.tgz", + "integrity": "sha512-zuWDMDuzMRbQOM+bHyU4/slw27bAUEcKSKKs3hcv2aNnc/tvE/h7w60dwVw8vnal2Pub6RT1T7BI8tFZ1fE+yg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.36.0", - "@typescript-eslint/tsconfig-utils": "8.36.0", - "@typescript-eslint/types": "8.36.0", - "@typescript-eslint/visitor-keys": "8.36.0", + "@typescript-eslint/project-service": "8.37.0", + "@typescript-eslint/tsconfig-utils": "8.37.0", + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/visitor-keys": "8.37.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1324,16 +1325,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.36.0.tgz", - "integrity": "sha512-VOqmHu42aEMT+P2qYjylw6zP/3E/HvptRwdn/PZxyV27KhZg2IOszXod4NcXisWzPAGSS4trE/g4moNj6XmH2g==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.37.0.tgz", + "integrity": "sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.36.0", - "@typescript-eslint/types": "8.36.0", - "@typescript-eslint/typescript-estree": "8.36.0" + "@typescript-eslint/scope-manager": "8.37.0", + "@typescript-eslint/types": "8.37.0", + "@typescript-eslint/typescript-estree": "8.37.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1348,13 +1349,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.36.0.tgz", - "integrity": "sha512-vZrhV2lRPWDuGoxcmrzRZyxAggPL+qp3WzUrlZD+slFueDiYHxeBa34dUXPuC0RmGKzl4lS5kFJYvKCq9cnNDA==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.37.0.tgz", + "integrity": "sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.36.0", + "@typescript-eslint/types": "8.37.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -2213,9 +2214,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.182", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz", - "integrity": "sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA==", + "version": "1.5.185", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.185.tgz", + "integrity": "sha512-dYOZfUk57hSMPePoIQ1fZWl1Fkj+OshhEVuPacNKWzC1efe56OsHY3l/jCfiAgIICOU3VgOIdoq7ahg7r7n6MQ==", "dev": true, "license": "ISC" }, @@ -2566,9 +2567,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "51.3.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.3.4.tgz", - "integrity": "sha512-maz6qa95+sAjMr9m5oRyfejc+mnyQWsWSe9oyv9371bh4/T0kWOMryJNO4h8rEd97wo/9lbzwi3OOX4rDhnAzg==", + "version": "51.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.4.1.tgz", + "integrity": "sha512-y4CA9OkachG8v5nAtrwvcvjIbdcKgSyS6U//IfQr4FZFFyeBFwZFf/tfSsMr46mWDJgidZjBTqoCRlXywfFBMg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -2702,9 +2703,9 @@ } }, "node_modules/eslint-plugin-pnpm": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-pnpm/-/eslint-plugin-pnpm-0.3.1.tgz", - "integrity": "sha512-vi5iHoELIAlBbX4AW8ZGzU3tUnfxuXhC/NKo3qRcI5o9igbz6zJUqSlQ03bPeMqWIGTPatZnbWsNR1RnlNERNQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-pnpm/-/eslint-plugin-pnpm-1.0.0.tgz", + "integrity": "sha512-tyEA10k7psB9HFCx8R4/bU4JS2tSKfXaCnrCcis+1R4FucfMIc6HgcFl4msZbwY2I0D9Vec3xAEkXV0aPechhQ==", "dev": true, "funding": [ { @@ -2721,8 +2722,8 @@ "find-up-simple": "^1.0.1", "jsonc-eslint-parser": "^2.4.0", "pathe": "^2.0.3", - "pnpm-workspace-yaml": "0.3.1", - "tinyglobby": "^0.2.12", + "pnpm-workspace-yaml": "1.0.0", + "tinyglobby": "^0.2.14", "yaml-eslint-parser": "^1.3.0" }, "peerDependencies": { @@ -5181,9 +5182,9 @@ } }, "node_modules/node-addon-api": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.4.0.tgz", - "integrity": "sha512-D9DI/gXHvVmjHS08SVch0Em8G5S1P+QWtU31appcKT/8wFSPRcdHadIFSAntdMMVM5zz+/DL+bL/gz3UDppqtg==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", "license": "MIT", "optional": true, "engines": { @@ -5522,9 +5523,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -5557,9 +5558,9 @@ } }, "node_modules/pnpm-workspace-yaml": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pnpm-workspace-yaml/-/pnpm-workspace-yaml-0.3.1.tgz", - "integrity": "sha512-3nW5RLmREmZ8Pm8MbPsO2RM+99RRjYd25ynj3NV0cFsN7CcEl4sDFzgoFmSyduFwxFQ2Qbu3y2UdCh6HlyUOeA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pnpm-workspace-yaml/-/pnpm-workspace-yaml-1.0.0.tgz", + "integrity": "sha512-2RKg3khFgX/oeKIQnxxlj+OUoKbaZjBt7EsmQiLfl8AHZKMIpLmXLRPptZ5eq2Rlumh2gILs6OWNky5dzP+f8A==", "dev": true, "funding": [ { @@ -5573,7 +5574,7 @@ ], "license": "MIT", "dependencies": { - "yaml": "^2.7.0" + "yaml": "^2.8.0" } }, "node_modules/postcss": { @@ -6456,9 +6457,9 @@ } }, "node_modules/usb": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/usb/-/usb-2.15.0.tgz", - "integrity": "sha512-BA9r7PFxyYp99wps1N70lIqdPb2Utcl2KkWohDtWUmhDBeM5hDH1Zl/L/CZvWxd5W3RUCNm1g+b+DEKZ6cHzqg==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/usb/-/usb-2.16.0.tgz", + "integrity": "sha512-jD88fvzDViMDH5KmmNJgzMBDj/95bDTt6+kBNaNxP4G98xUTnDMiLUY2CYmToba6JAFhM9VkcaQuxCNRLGR7zg==", "hasInstallScript": true, "license": "MIT", "optional": true, diff --git a/package.json b/package.json index 4ad495f4..c1ce3f63 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,6 @@ "@stoprocent/noble": "^1.19.1" }, "devDependencies": { - "@antfu/eslint-config": "^4.16.2" + "@antfu/eslint-config": "^4.17.0" } } From 891ab583c0cea911c441ee08d1a901ed6d622739 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Wed, 16 Jul 2025 20:14:35 +0100 Subject: [PATCH 23/29] use unitless rotation speed for H7105 --- CHANGELOG.md | 7 ++- lib/device/fan-H7105.js | 128 ++++++++++------------------------------ 2 files changed, 36 insertions(+), 99 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3f6d354..a6bc56d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,14 @@ All notable changes to homebridge-govee will be documented in this file. ## v11.4.0 (Unreleased) +- ⚠️ This update will remove and re-add any H7105 fan accessories in your Homebridge setup. + - It will replace the 0-100% rotation speed with a unitless rotation speed characteristic. + - The new rotation speed values (0-12) will better match the speeds from the Govee app. + ### Notable Changes -- add option to hide fan light (H7105) +- add option to hide fan light for H7105 +- use unitless rotation speed for H7105 ## v11.3.1 (2025-07-13) diff --git a/lib/device/fan-H7105.js b/lib/device/fan-H7105.js index 9789540a..4b64cb22 100644 --- a/lib/device/fan-H7105.js +++ b/lib/device/fan-H7105.js @@ -28,18 +28,18 @@ export default class { // Codes etc this.speedCodes = { - 7: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=', - 14: 'MwUBAgAAAAAAAAAAAAAAAAAAADU=', - 21: 'MwUBAwAAAAAAAAAAAAAAAAAAADQ=', - 28: 'MwUBBAAAAAAAAAAAAAAAAAAAADM=', - 35: 'MwUBBQAAAAAAAAAAAAAAAAAAADI=', - 42: 'MwUBBgAAAAAAAAAAAAAAAAAAADE=', - 49: 'MwUBBwAAAAAAAAAAAAAAAAAAADA=', - 56: 'MwUBCAAAAAAAAAAAAAAAAAAAAD8=', - 63: 'MwUBCQAAAAAAAAAAAAAAAAAAAD4=', - 70: 'MwUBCgAAAAAAAAAAAAAAAAAAAD0=', // guessed - 77: 'MwUBCwAAAAAAAAAAAAAAAAAAADw=', // guessed - 84: 'MwUBDAAAAAAAAAAAAAAAAAAAADs=', // guessed + 1: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=', + 2: 'MwUBAgAAAAAAAAAAAAAAAAAAADU=', + 3: 'MwUBAwAAAAAAAAAAAAAAAAAAADQ=', + 4: 'MwUBBAAAAAAAAAAAAAAAAAAAADM=', + 5: 'MwUBBQAAAAAAAAAAAAAAAAAAADI=', + 6: 'MwUBBgAAAAAAAAAAAAAAAAAAADE=', + 7: 'MwUBBwAAAAAAAAAAAAAAAAAAADA=', + 8: 'MwUBCAAAAAAAAAAAAAAAAAAAAD8=', + 9: 'MwUBCQAAAAAAAAAAAAAAAAAAAD4=', + 10: 'MwUBCgAAAAAAAAAAAAAAAAAAAD0=', + 11: 'MwUBCwAAAAAAAAAAAAAAAAAAADw=', + 12: 'MwUBDAAAAAAAAAAAAAAAAAAAADs=', } // Remove any old original Fan services @@ -47,6 +47,14 @@ export default class { this.accessory.removeService(this.accessory.getService(this.hapServ.Fan)) } + // Migrate old %-rotation speed to unitless + const existingService = this.accessory.getService(this.hapServ.Fanv2) + if (existingService) { + if (existingService.getCharacteristic(this.hapChar.RotationSpeed).props.unit === 'percentage') { + this.accessory.removeService(existingService) + } + } + // Add the fan service for the fan if it doesn't already exist this.service = this.accessory.getService(this.hapServ.Fanv2) || this.accessory.addService(this.hapServ.Fanv2) @@ -60,13 +68,13 @@ export default class { this.service .getCharacteristic(this.hapChar.RotationSpeed) .setProps({ - minStep: 7, + maxValue: 12, + minStep: 1, minValue: 0, - validValues: [0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91], + unit: 'unitless', // This is actually from HAP for Bluetooth LE Specification, but fits }) .onSet(async value => this.internalSpeedUpdate(value)) this.cacheSpeed = this.service.getCharacteristic(this.hapChar.RotationSpeed).value - this.cacheMode = this.cacheSpeed >= 91 ? 'auto' : 'manual' // Add the set handler to the fan swing mode this.service @@ -146,74 +154,20 @@ export default class { async internalSpeedUpdate(value) { try { - if (value < 3) { - return - } - - let newValue - if (value < 10) { - newValue = 7 - } else if (value < 17) { - newValue = 14 - } else if (value < 24) { - newValue = 21 - } else if (value < 31) { - newValue = 28 - } else if (value < 38) { - newValue = 35 - } else if (value < 45) { - newValue = 42 - } else if (value < 52) { - newValue = 49 - } else if (value < 59) { - newValue = 56 - } else if (value < 66) { - newValue = 63 - } else if (value < 73) { - newValue = 70 - } else if (value < 80) { - newValue = 77 - } else if (value < 87) { - newValue = 84 - } else { - newValue = 91 - } - - let newMode = value === 91 ? 'auto' : 'manual' - // Don't continue if the new value is the same as before - if (this.cacheSpeed === newValue) { + if (this.cacheSpeed === value || value === 0) { return } - // Don't continue if trying to access auto mode but there is no sensor attached - let codeToSend - if (newMode === 'auto') { - if (!this.accessory.context.sensorAttached || !this.cacheAutoCode) { - this.accessory.logWarn('auto mode not supported without a linked sensor') - codeToSend = this.speedCodes[84] - newMode = 'manual' - newValue = 84 - } else { - codeToSend = this.cacheAutoCode - } - } else { - codeToSend = this.speedCodes[newValue] - } - await this.platform.sendDeviceUpdate(this.accessory, { cmd: 'ptReal', - value: codeToSend, + value: this.speedCodes[value], }) // Cache the new state and log if appropriate - if (this.cacheMode !== newMode) { - this.cacheMode = newMode - this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`) - } - if (this.cacheSpeed !== newValue) { - this.cacheSpeed = newValue - this.accessory.log(`${platformLang.curSpeed} [${newValue}%]`) + if (this.cacheSpeed !== value) { + this.cacheSpeed = value + this.accessory.log(`${platformLang.curSpeed} [${value}]`) } } catch (err) { // Catch any errors during the process @@ -421,16 +375,11 @@ export default class { case '0501': { // Fan speed const newSpeed = getTwoItemPosition(hexParts, 4) - const newSpeedInt = Number.parseInt(newSpeed, 16) * 7 - const newMode = 'manual' - if (this.cacheMode !== newMode) { - this.cacheMode = newMode - this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`) - } + const newSpeedInt = Number.parseInt(newSpeed, 16) if (this.cacheSpeed !== newSpeedInt) { this.cacheSpeed = newSpeedInt this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed) - this.accessory.log(`${platformLang.curSpeed} [${this.cacheSpeed}%]`) + this.accessory.log(`${platformLang.curSpeed} [${this.cacheSpeed}]`) } break } @@ -443,23 +392,6 @@ export default class { // Sleep: 5 // Nature: 6 // Turbo: 7 - const newMode = getTwoItemPosition(hexParts, 4) === '03' ? 'auto' : 'manual' - if (this.cacheMode !== newMode) { - this.cacheMode = newMode - this.accessory.log(`${platformLang.curMode} [${this.cacheMode}]`) - - if (this.cacheMode === 'auto' && this.cacheSpeed < 91) { - this.cacheSpeed = 91 - this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed) - this.accessory.log(`${platformLang.curSpeed} [${this.cacheSpeed}%]`) - } - } - break - } - case '0503': { - // Auto mode, we need to keep this code to send it back to the device - const code = hexToTwoItems(`33${hexString.substring(2, hexString.length - 2)}`) - this.cacheAutoCode = generateCodeFromHexValues(code.map(p => Number.parseInt(p, 16))) break } case '1b01': { From c1031cd65be89155e1f72083c1d4cc835ebf7e25 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Wed, 16 Jul 2025 20:17:39 +0100 Subject: [PATCH 24/29] fix updating swing mode for H7105 when externally controlled --- CHANGELOG.md | 1 + lib/device/fan-H7105.js | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6bc56d0..21e95e21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to homebridge-govee will be documented in this file. - add option to hide fan light for H7105 - use unitless rotation speed for H7105 +- fix updating swing mode for H7105 when externally controlled ## v11.3.1 (2025-07-13) diff --git a/lib/device/fan-H7105.js b/lib/device/fan-H7105.js index 4b64cb22..09f9d0f3 100644 --- a/lib/device/fan-H7105.js +++ b/lib/device/fan-H7105.js @@ -434,12 +434,22 @@ export default class { } break } - case '1f01': { - // Swing Mode - const newSwing = getTwoItemPosition(hexParts, 4) === '01' ? 'on' : 'off' + case '1d00':{ + // Swing Mode Off + const newSwing = 'off' if (this.cacheSwing !== newSwing) { this.cacheSwing = newSwing - this.service.updateCharacteristic(this.hapChar.SwingMode, this.cacheSwing === 'on' ? 1 : 0) + this.service.updateCharacteristic(this.hapChar.SwingMode, 0) + this.accessory.log(`${platformLang.curSwing} [${this.cacheSwing}]`) + } + break + } + case '1d01':{ + // Swing Mode On + const newSwing = 'on' + if (this.cacheSwing !== newSwing) { + this.cacheSwing = newSwing + this.service.updateCharacteristic(this.hapChar.SwingMode, 1) this.accessory.log(`${platformLang.curSwing} [${this.cacheSwing}]`) } break From fb51519f9bc5e4012c7dab4dfba104cf82a41a77 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Wed, 16 Jul 2025 20:21:07 +0100 Subject: [PATCH 25/29] temporarily disable controlling swing mode for H7105 --- CHANGELOG.md | 1 + lib/device/fan-H7105.js | 32 +++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21e95e21..6b100f70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to homebridge-govee will be documented in this file. - add option to hide fan light for H7105 - use unitless rotation speed for H7105 - fix updating swing mode for H7105 when externally controlled +- temporarily disable controlling swing mode for H7105 ## v11.3.1 (2025-07-13) diff --git a/lib/device/fan-H7105.js b/lib/device/fan-H7105.js index 09f9d0f3..daf85160 100644 --- a/lib/device/fan-H7105.js +++ b/lib/device/fan-H7105.js @@ -81,6 +81,7 @@ export default class { .getCharacteristic(this.hapChar.SwingMode) .onSet(async value => this.internalSwingUpdate(value)) this.cacheSwing = this.service.getCharacteristic(this.hapChar.SwingMode).value === 1 ? 'on' : 'off' + this.cacheSwingCode = '' if (this.hideLight) { if (this.accessory.getService(this.hapServ.Lightbulb)) { @@ -183,22 +184,33 @@ export default class { async internalSwingUpdate(value) { try { - const newValue = value ? 'on' : 'off' // Don't continue if the new value is the same as before if (this.cacheSwing === value) { return } - await this.platform.sendDeviceUpdate(this.accessory, { - cmd: 'ptReal', - value: value ? 'Mx8BAQAAAAAAAAAAAAAAAAAAACw=' : 'Mx8BAAAAAAAAAAAAAAAAAAAAAC0=', - }) + throw new Error('Swing mode update not implemented yet') + + // const newValue = value ? 'on' : 'off' + // The existing cacheSwingCode might be something like aa1d0101960384000000000000000000000000a6 + // We need to change the third hex value to 00 for off or 01 for on + // const hexValues = [ + // 0x3A, + // 0x1D, + // value ? 0x01 : 0x00, + // ...this.cacheSwingCode.slice(6, 14).match(/.{1,2}/g).map(byte => Number.parseInt(byte, 16)), + // ] + // + // await this.platform.sendDeviceUpdate(this.accessory, { + // cmd: 'multiSync', + // value: generateCodeFromHexValues(hexValues), + // }) // Cache the new state and log if appropriate - if (this.cacheSwing !== newValue) { - this.cacheSwing = newValue - this.accessory.log(`${platformLang.curSwing} [${newValue}]`) - } + // if (this.cacheSwing !== newValue) { + // this.cacheSwing = newValue + // this.accessory.log(`${platformLang.curSwing} [${newValue}]`) + // } } catch (err) { // Catch any errors during the process this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`) @@ -437,6 +449,7 @@ export default class { case '1d00':{ // Swing Mode Off const newSwing = 'off' + this.cacheSwingCode = hexString if (this.cacheSwing !== newSwing) { this.cacheSwing = newSwing this.service.updateCharacteristic(this.hapChar.SwingMode, 0) @@ -447,6 +460,7 @@ export default class { case '1d01':{ // Swing Mode On const newSwing = 'on' + this.cacheSwingCode = hexString if (this.cacheSwing !== newSwing) { this.cacheSwing = newSwing this.service.updateCharacteristic(this.hapChar.SwingMode, 1) From 04f9056a3fb88e98483788f3cd5629453985fd6c Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Fri, 18 Jul 2025 08:11:52 +0100 Subject: [PATCH 26/29] add maintainer message --- CHANGELOG.md | 4 ++++ README.md | 2 ++ lib/utils/lang-en.js | 2 +- package-lock.json | 12 ++++++------ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b100f70..2ba4b838 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ All notable changes to homebridge-govee will be documented in this file. - fix updating swing mode for H7105 when externally controlled - temporarily disable controlling swing mode for H7105 +### Other Changes + +- add maintainer message + ## v11.3.1 (2025-07-13) ### Notable Changes diff --git a/README.md b/README.md index a6ac5eee..e60586dc 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Homebridge plugin to integrate Govee devices into HomeKit - can control certain models locally via LAN control without any Govee credentials - does **not** make use of the Govee API key +> I'm looking for some lovely people to help maintain this plugin, please get in touch on GitHub or Discord if you'd like to help out 😄 + ### Prerequisites - To use this plugin, you will need to already have: diff --git a/lib/utils/lang-en.js b/lib/utils/lang-en.js index 94d83e24..fb43f806 100644 --- a/lib/utils/lang-en.js +++ b/lib/utils/lang-en.js @@ -123,6 +123,6 @@ export default { storageWriteErr: 'could not save accessory to file as', syncFail: 'sync failed as', viaAL: 'via adaptive lighting', - welcome: 'This plugin has been made with ♥ by bwp91, please consider a ☆ on GitHub if you are finding it useful!', + welcome: 'I\'m looking for some lovely people to help maintain this plugin, please get in touch on GitHub or Discord if you\'d like to help out 😄', unknownCommand: 'unknown command in payload received', } diff --git a/package-lock.json b/package-lock.json index 9818e112..c6892e63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2214,9 +2214,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.185", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.185.tgz", - "integrity": "sha512-dYOZfUk57hSMPePoIQ1fZWl1Fkj+OshhEVuPacNKWzC1efe56OsHY3l/jCfiAgIICOU3VgOIdoq7ahg7r7n6MQ==", + "version": "1.5.187", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.187.tgz", + "integrity": "sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA==", "dev": true, "license": "ISC" }, @@ -3278,9 +3278,9 @@ } }, "node_modules/form-data": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", - "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", From 5a598431ae1423c44842a2b4570fd9b555b57c07 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Fri, 18 Jul 2025 08:14:44 +0100 Subject: [PATCH 27/29] v11.4.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ba4b838..e34f8593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to homebridge-govee will be documented in this file. -## v11.4.0 (Unreleased) +## v11.4.0 (2025-07-18) - ⚠️ This update will remove and re-add any H7105 fan accessories in your Homebridge setup. - It will replace the 0-100% rotation speed with a unitless rotation speed characteristic. diff --git a/package-lock.json b/package-lock.json index c6892e63..438619af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.3.1", + "version": "11.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.3.1", + "version": "11.4.0", "funding": [ { "type": "github", diff --git a/package.json b/package.json index c1ce3f63..ae811061 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@homebridge-plugins/homebridge-govee", "alias": "Govee", "type": "module", - "version": "11.3.1", + "version": "11.4.0", "description": "Homebridge plugin to integrate Govee devices into HomeKit.", "author": { "name": "bwp91", From 57070c1300cc073581491d13b31b17c24a7780a1 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Fri, 18 Jul 2025 19:45:59 +0100 Subject: [PATCH 28/29] added light models: `H6038`, `H60B1` & `H60B2` --- CHANGELOG.md | 6 ++++++ lib/utils/constants.js | 3 +++ package-lock.json | 14 ++++++++------ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e34f8593..729666e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to homebridge-govee will be documented in this file. +## v11.5.0 (Unreleased) + +### Notable Changes + +- added light models: `H6038`, `H60B1` & `H60B2` + ## v11.4.0 (2025-07-18) - ⚠️ This update will remove and re-add any H7105 fan accessories in your Homebridge setup. diff --git a/lib/utils/constants.js b/lib/utils/constants.js index 2722b537..228a4d58 100644 --- a/lib/utils/constants.js +++ b/lib/utils/constants.js @@ -145,6 +145,7 @@ export default { 'H601D', 'H601E', 'H6022', + 'H6038', 'H6039', 'H6042', 'H6043', @@ -207,6 +208,8 @@ export default { 'H60A4', 'H60A6', 'H60B0', + 'H60B1', + 'H60B2', 'H6101', 'H6102', 'H6104', diff --git a/package-lock.json b/package-lock.json index 438619af..5893ab6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -692,10 +692,11 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", - "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.8.tgz", + "integrity": "sha512-Yd820OqLNN/Rpyod/2uGB+SdiFXVDfI/bylOMvtvpl0nIjRRovXIfek65CwWUewOhTi+m2jjRruPbttcbkd1VA==", "dev": true, + "hasInstallScript": true, "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" @@ -6158,10 +6159,11 @@ } }, "node_modules/synckit": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", - "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", + "version": "0.11.9", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.9.tgz", + "integrity": "sha512-02JE2dOputr8ku4SNqAnqhGo0FaHcvSvAuzXMLdvygH4dqu3PXyUdePefNozFcCznNtQwf6Wn98ZSLa+ArRqZQ==", "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { "@pkgr/core": "^0.2.4" From b7500e6c0623fc5bb83bbff5b7fedaba876c93ac Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Fri, 18 Jul 2025 19:47:23 +0100 Subject: [PATCH 29/29] v11.5.0 --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 729666e3..0770f41b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to homebridge-govee will be documented in this file. -## v11.5.0 (Unreleased) +## v11.5.0 (2025-07-18) ### Notable Changes diff --git a/package-lock.json b/package-lock.json index 5893ab6b..10d5f923 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.4.0", + "version": "11.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@homebridge-plugins/homebridge-govee", - "version": "11.4.0", + "version": "11.5.0", "funding": [ { "type": "github", diff --git a/package.json b/package.json index ae811061..0b325a3b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@homebridge-plugins/homebridge-govee", "alias": "Govee", "type": "module", - "version": "11.4.0", + "version": "11.5.0", "description": "Homebridge plugin to integrate Govee devices into HomeKit.", "author": { "name": "bwp91", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy