From e1e3468c5eed4b93dd2ea99de010f43580e4a98d Mon Sep 17 00:00:00 2001 From: Donavan Becker Date: Sun, 3 Nov 2024 22:04:23 -0600 Subject: [PATCH] v2.1.7 (#845) ## [2.1.7](https://github.com/homebridge-plugins/homebridge-resideo/releases/tag/v2.1.7) (2024-11-03) ### What's Changes - Revert to using `axios` instead of `undici` - Housekeeping and updated dependencies. **Full Changelog**: https://github.com/homebridge-plugins/homebridge-resideo/compare/v2.1.6...v2.1.7 --- .github/ISSUE_TEMPLATE.md | 24 +- .github/auto-merge.yml | 3 - .github/workflows/beta-release.yml | 18 +- .github/workflows/build.yml | 6 +- .github/workflows/changerelease.yml | 2 +- .github/workflows/dependabot.yml | 13 - .github/workflows/labeler.yml | 2 +- .github/workflows/release-drafter.yml | 2 +- .github/workflows/release.yml | 14 +- .github/workflows/stale.yml | 2 +- CHANGELOG.md | 8 + config.schema.json | 9 +- docs/assets/icons.js | 2 +- docs/assets/icons.svg | 2 +- docs/assets/main.js | 2 +- docs/assets/style.css | 87 ++- docs/functions/default.html | 2 +- docs/index.html | 30 +- docs/modules.html | 4 +- package-lock.json | 946 ++++++++++++-------------- package.json | 30 +- src/devices/device.ts | 12 +- src/devices/leaksensors.ts | 42 +- src/devices/roomsensors.ts | 24 +- src/devices/roomsensorthermostats.ts | 74 +- src/devices/thermostats.ts | 256 +++---- src/devices/valve.ts | 44 +- src/index.ts | 12 +- src/platform.ts | 256 ++++--- src/settings.ts | 14 +- 30 files changed, 962 insertions(+), 980 deletions(-) delete mode 100644 .github/auto-merge.yml delete mode 100644 .github/workflows/dependabot.yml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 75ba08d6..2b5de006 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -10,15 +10,19 @@ assignees: '' **Describe The Bug:** + **To Reproduce:** + **Expected behavior:** + **Logs:** + ``` @@ -27,22 +31,22 @@ Show the Homebridge / Homebridge Config UI X logs here. **Homebridge Config:** -```json +\```json Show your homebridge config.json here -``` +\``` **Screenshots:** + **Environment:** -* **Node.js Version**: -* **NPM Version**: -* **Homebridge Version**: -* **Homebridge Resideo Plugin Version**: -* **Homebridge Config UI X Version**: -* **Operating System**: Raspbian / Ubuntu / Debian / Windows / macOS / Docker -* **Process Supervisor**: Docker / Systemd / init.d / pm2 / launchctl / hb-service / other / none - +- **Node.js Version**: +- **NPM Version**: +- **Homebridge Version**: +- **Homebridge Resideo Plugin Version**: +- **Homebridge Config UI X Version**: +- **Operating System**: Raspbian / Ubuntu / Debian / Windows / macOS / Docker +- **Process Supervisor**: Docker / Systemd / init.d / pm2 / launchctl / hb-service / other / none diff --git a/.github/auto-merge.yml b/.github/auto-merge.yml deleted file mode 100644 index 9a6f2f89..00000000 --- a/.github/auto-merge.yml +++ /dev/null @@ -1,3 +0,0 @@ -- match: - dependency_type: all - update_type: all \ No newline at end of file diff --git a/.github/workflows/beta-release.yml b/.github/workflows/beta-release.yml index 5071b9e6..cc6b9ab8 100644 --- a/.github/workflows/beta-release.yml +++ b/.github/workflows/beta-release.yml @@ -1,4 +1,4 @@ -name: Node-CI Beta +name: Beta Release on: push: @@ -7,21 +7,21 @@ on: jobs: build_and_test: - uses: donavanbecker/.github/.github/workflows/nodejs-build-and-test.yml@latest + uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest with: - enable_coverage: true + enable_coverage: false secrets: token: ${{ secrets.GITHUB_TOKEN }} lint: needs: build_and_test - uses: donavanbecker/.github/.github/workflows/eslint.yml@latest + uses: homebridge/.github/.github/workflows/eslint.yml@latest publish: needs: lint - if: ${{ github.repository == 'homebridge-plugins/homebridge-resideo' }} - - uses: donavanbecker/.github/.github/workflows/npm-publish.yml@latest + permissions: + id-token: write + uses: homebridge/.github/.github/workflows/npm-publish-esm.yml@latest with: tag: 'beta' dynamically_adjust_version: true @@ -33,7 +33,7 @@ jobs: pre-release: needs: publish if: ${{ github.repository == 'homebridge-plugins/homebridge-resideo' }} - uses: donavanbecker/.github/.github/workflows/pre-release.yml@latest + uses: homebridge/.github/.github/workflows/pre-release.yml@latest with: npm_version: ${{ needs.publish.outputs.NPM_VERSION }} body: | @@ -45,7 +45,7 @@ jobs: name: Discord Webhooks needs: [build_and_test,publish] if: ${{ github.repository == 'homebridge-plugins/homebridge-resideo' }} - uses: donavanbecker/.github/.github/workflows/discord-webhooks.yml@latest + uses: homebridge/.github/.github/workflows/discord-webhooks.yml@latest with: title: "Resideo Beta Release" description: | diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 842fa205..7087a780 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,11 +8,11 @@ on: jobs: build_and_test: - uses: donavanbecker/.github/.github/workflows/nodejs-build-and-test.yml@latest + uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest with: - enable_coverage: true + enable_coverage: false secrets: token: ${{ secrets.GITHUB_TOKEN }} lint: needs: build_and_test - uses: donavanbecker/.github/.github/workflows/eslint.yml@latest + uses: homebridge/.github/.github/workflows/eslint.yml@latest diff --git a/.github/workflows/changerelease.yml b/.github/workflows/changerelease.yml index 111ba973..135b42de 100644 --- a/.github/workflows/changerelease.yml +++ b/.github/workflows/changerelease.yml @@ -6,6 +6,6 @@ on: jobs: changerelease: - uses: donavanbecker/.github/.github/workflows/changerelease.yml@latest + uses: homebridge/.github/.github/workflows/change-release.yml@latest secrets: token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml deleted file mode 100644 index 525d2b26..00000000 --- a/.github/workflows/dependabot.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: AutoDependabot - -on: - pull_request: - branches: [ beta, latest ] - pull_request_target: - branches: [ beta, latest ] - -jobs: - dependabot: - uses: donavanbecker/.github/.github/workflows/dependabot.yml@latest - secrets: - token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 6eb3c01b..d3af51cd 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -4,6 +4,6 @@ on: [pull_request] jobs: labeler: - uses: donavanbecker/.github/.github/workflows/labeler.yml@latest + uses: homebridge/.github/.github/workflows/labeler.yml@latest secrets: token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 48588fcb..6037deca 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -9,6 +9,6 @@ on: jobs: release-drafter: - uses: donavanbecker/.github/.github/workflows/release-drafter.yml@latest + uses: homebridge/.github/.github/workflows/release-drafter.yml@latest secrets: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3327fee4..3ff521a9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Node Release +name: Release on: release: @@ -6,18 +6,18 @@ on: jobs: build_and_test: - uses: donavanbecker/.github/.github/workflows/nodejs-build-and-test.yml@latest + uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest with: - enable_coverage: true + enable_coverage: false secrets: token: ${{ secrets.GITHUB_TOKEN }} publish: needs: build_and_test - if: ${{ github.repository == 'homebridge-plugins/homebridge-resideo' }} - - uses: donavanbecker/.github/.github/workflows/npm-publish.yml@latest + permissions: + id-token: write + uses: homebridge/.github/.github/workflows/npm-publish-esm.yml@latest secrets: npm_auth_token: ${{ secrets.npm_token }} @@ -25,7 +25,7 @@ jobs: name: Discord Webhooks needs: [build_and_test,publish] if: ${{ github.repository == 'homebridge-plugins/homebridge-resideo' }} - uses: donavanbecker/.github/.github/workflows/discord-webhooks.yml@latest + uses: homebridge/.github/.github/workflows/discord-webhooks.yml@latest with: title: "Resideo Release" description: | diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f07b2341..2683a78a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,6 +7,6 @@ on: jobs: stale: - uses: donavanbecker/.github/.github/workflows/stale.yml@latest + uses: homebridge/.github/.github/workflows/stale.yml@latest secrets: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e5d1464..8688f0e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/) +## [2.1.7](https://github.com/homebridge-plugins/homebridge-resideo/releases/tag/v2.1.7) (2024-11-03) + +### What's Changes +- Revert to using `axios` instead of `undici` +- Housekeeping and updated dependencies. + +**Full Changelog**: https://github.com/homebridge-plugins/homebridge-resideo/compare/v2.1.6...v2.1.7 + ## [2.1.6](https://github.com/homebridge-plugins/homebridge-resideo/releases/tag/v2.1.6) (2024-10-24) ### What's Changes diff --git a/config.schema.json b/config.schema.json index d14c3a7f..a4bad6a1 100644 --- a/config.schema.json +++ b/config.schema.json @@ -63,6 +63,7 @@ "configDeviceName": { "title": "Device Name", "type": "string", + "pattern": "^[a-zA-Z0-9]+([a-zA-Z0-9 ]*[a-zA-Z0-9]+)?$", "placeholder": "Hallway Thermostat", "condition": { "functionBody": "return (model.options && model.options.devices && model.options.devices[arrayIndices].deviceID);" @@ -477,6 +478,11 @@ "enum": ["debug"] } ] + }, + "allowInvalidCharacters": { + "title": "Allow Invalid Characters", + "type": "boolean", + "description": "If true, invalid characters will be allowed in the device name." } }, "required": ["logging"] @@ -597,7 +603,8 @@ "key": "options.pushRate", "description": "Specifies the interval, in seconds, between pushes to the Resideo API." }, - "options.logging" + "options.logging", + "options.allowInvalidCharacters" ] } ] diff --git a/docs/assets/icons.js b/docs/assets/icons.js index e88e8ca7..3dfbd322 100644 --- a/docs/assets/icons.js +++ b/docs/assets/icons.js @@ -3,7 +3,7 @@ function addIcons() { if (document.readyState === "loading") return document.addEventListener("DOMContentLoaded", addIcons); const svg = document.body.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg")); - svg.innerHTML = `""`; + svg.innerHTML = `MMNEPVFCICPMFPCPTTAAATR`; svg.style.display = "none"; if (location.protocol === "file:") updateUseElements(); } diff --git a/docs/assets/icons.svg b/docs/assets/icons.svg index e371b8b5..a19417dc 100644 --- a/docs/assets/icons.svg +++ b/docs/assets/icons.svg @@ -1 +1 @@ - \ No newline at end of file +MMNEPVFCICPMFPCPTTAAATR \ No newline at end of file diff --git a/docs/assets/main.js b/docs/assets/main.js index 35728810..99097a05 100644 --- a/docs/assets/main.js +++ b/docs/assets/main.js @@ -3,7 +3,7 @@ window.translations={"copy":"Copy","copied":"Copied!","normally_hidden":"This me "use strict";(()=>{var Pe=Object.create;var ie=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var _e=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,Me=Object.prototype.hasOwnProperty;var Fe=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var De=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of _e(e))!Me.call(t,i)&&i!==n&&ie(t,i,{get:()=>e[i],enumerable:!(r=Oe(e,i))||r.enumerable});return t};var Ae=(t,e,n)=>(n=t!=null?Pe(Re(t)):{},De(e||!t||!t.__esModule?ie(n,"default",{value:t,enumerable:!0}):n,t));var ue=Fe((ae,le)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,u],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. `,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?d+=2:a==l&&(n+=r[u+1]*i[d+1],u+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),m=s.str.charAt(1),p;m in s.node.edges?p=s.node.edges[m]:(p=new t.TokenSet,s.node.edges[m]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof ae=="object"?le.exports=n():e.lunr=n()}(this,function(){return t})})()});var se=[];function G(t,e){se.push({selector:e,constructor:t})}var U=class{constructor(){this.alwaysVisibleMember=null;this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){se.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!Ve(e)){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r,document.querySelector(".col-sidebar").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(!n)return;let r=n.offsetParent==null,i=n;for(;i!==document.body;)i instanceof HTMLDetailsElement&&(i.open=!0),i=i.parentElement;if(n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let s=document.createElement("p");s.classList.add("warning"),s.textContent=window.translations.normally_hidden,n.prepend(s)}r&&e.scrollIntoView()}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent=window.translations.copied,e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent=window.translations.copy},100)},1e3)})})}};function Ve(t){let e=t.getBoundingClientRect(),n=Math.max(document.documentElement.clientHeight,window.innerHeight);return!(e.bottom<0||e.top-n>=0)}var oe=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var pe=Ae(ue());async function ce(t,e){if(!window.searchData)return;let n=await fetch(window.searchData),r=new Blob([await n.arrayBuffer()]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();t.data=i,t.index=pe.Index.load(i.index),e.classList.remove("loading"),e.classList.add("ready")}function fe(){let t=document.getElementById("tsd-search");if(!t)return;let e={base:t.dataset.base+"/"},n=document.getElementById("tsd-search-script");t.classList.add("loading"),n&&(n.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),n.addEventListener("load",()=>{ce(e,t)}),ce(e,t));let r=document.querySelector("#tsd-search input"),i=document.querySelector("#tsd-search .results");if(!r||!i)throw new Error("The input field or the result list wrapper was not found");i.addEventListener("mouseup",()=>{te(t)}),r.addEventListener("focus",()=>t.classList.add("has-focus")),He(t,i,r,e)}function He(t,e,n,r){n.addEventListener("input",oe(()=>{Ne(t,e,n,r)},200)),n.addEventListener("keydown",i=>{i.key=="Enter"?Be(e,t):i.key=="ArrowUp"?(de(e,n,-1),i.preventDefault()):i.key==="ArrowDown"&&(de(e,n,1),i.preventDefault())}),document.body.addEventListener("keypress",i=>{i.altKey||i.ctrlKey||i.metaKey||!n.matches(":focus")&&i.key==="/"&&(i.preventDefault(),n.focus())}),document.body.addEventListener("keyup",i=>{t.classList.contains("has-focus")&&(i.key==="Escape"||!e.matches(":focus-within")&&!n.matches(":focus"))&&(n.blur(),te(t))})}function te(t){t.classList.remove("has-focus")}function Ne(t,e,n,r){if(!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s;if(i){let o=i.split(" ").map(a=>a.length?`*${a}*`:"").join(" ");s=r.index.search(o)}else s=[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o`,d=he(l.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(d+=` (score: ${s[o].score.toFixed(2)})`),l.parent&&(d=` ${he(l.parent,i)}.${d}`);let m=document.createElement("li");m.classList.value=l.classes??"";let p=document.createElement("a");p.href=r.base+l.url,p.innerHTML=u+d,m.append(p),p.addEventListener("focus",()=>{e.querySelector(".current")?.classList.remove("current"),m.classList.add("current")}),e.appendChild(m)}}function de(t,e,n){let r=t.querySelector(".current");if(!r)r=t.querySelector(n==1?"li:first-child":"li:last-child"),r&&r.classList.add("current");else{let i=r;if(n===1)do i=i.nextElementSibling??void 0;while(i instanceof HTMLElement&&i.offsetParent==null);else do i=i.previousElementSibling??void 0;while(i instanceof HTMLElement&&i.offsetParent==null);i?(r.classList.remove("current"),i.classList.add("current")):n===-1&&(r.classList.remove("current"),e.focus())}}function Be(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),te(e)}}function he(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(ee(t.substring(s,o)),`${ee(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(ee(t.substring(s))),i.join("")}var je={"&":"&","<":"<",">":">","'":"'",'"':"""};function ee(t){return t.replace(/[&<>"'"]/g,e=>je[e])}var I=class{constructor(e){this.el=e.el,this.app=e.app}};var F="mousedown",ye="mousemove",N="mouseup",J={x:0,y:0},me=!1,ne=!1,qe=!1,D=!1,ve=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(ve?"is-mobile":"not-mobile");ve&&"ontouchstart"in document.documentElement&&(qe=!0,F="touchstart",ye="touchmove",N="touchend");document.addEventListener(F,t=>{ne=!0,D=!1;let e=F=="touchstart"?t.targetTouches[0]:t;J.y=e.pageY||0,J.x=e.pageX||0});document.addEventListener(ye,t=>{if(ne&&!D){let e=F=="touchstart"?t.targetTouches[0]:t,n=J.x-(e.pageX||0),r=J.y-(e.pageY||0);D=Math.sqrt(n*n+r*r)>10}});document.addEventListener(N,()=>{ne=!1});document.addEventListener("click",t=>{me&&(t.preventDefault(),t.stopImmediatePropagation(),me=!1)});var X=class extends I{constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener(N,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(F,n=>this.onDocumentPointerDown(n)),document.addEventListener(N,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){D||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!D&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var re;try{re=localStorage}catch{re={getItem(){return null},setItem(){}}}var Q=re;var ge=document.head.appendChild(document.createElement("style"));ge.dataset.for="filters";var Y=class extends I{constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),ge.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } -`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=Q.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){Q.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),this.app.updateIndexVisibility()}};var Z=class extends I{constructor(e){super(e),this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.dataset.key??this.summary.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`;let n=Q.getItem(this.key);this.el.open=n?n==="true":this.el.open,this.el.addEventListener("toggle",()=>this.update());let r=this.summary.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)}),this.update()}update(){this.icon.style.transform=`rotate(${this.el.open?0:-90}deg)`,Q.setItem(this.key,this.el.open.toString())}};function Ee(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,xe(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),xe(t.value)})}function xe(t){document.documentElement.dataset.theme=t}var K;function we(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Le),Le())}async function Le(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let n=await(await fetch(window.navigationData)).arrayBuffer(),r=new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();K=t.dataset.base,K.endsWith("/")||(K+="/"),t.innerHTML="";for(let s of i)Se(s,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Se(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML='',be(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let l=a.appendChild(document.createElement("ul"));l.className="tsd-nested-navigation";for(let u of t.children)Se(u,l,i)}else be(t,r,t.class)}function be(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));r.href=K+t.path,n&&(r.className=n),location.pathname===r.pathname&&r.classList.add("current"),t.kind&&(r.innerHTML=``),r.appendChild(document.createElement("span")).textContent=t.text}else e.appendChild(document.createElement("span")).textContent=t.text}G(X,"a[data-toggle]");G(Z,".tsd-accordion");G(Y,".tsd-filter-item input[type=checkbox]");var Te=document.getElementById("tsd-theme");Te&&Ee(Te);var $e=new U;Object.defineProperty(window,"app",{value:$e});fe();we();})(); +`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=Q.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){Q.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),this.app.updateIndexVisibility()}};var Z=class extends I{constructor(e){super(e),this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.dataset.key??this.summary.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`;let n=Q.getItem(this.key);this.el.open=n?n==="true":this.el.open,this.el.addEventListener("toggle",()=>this.update());let r=this.summary.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)}),this.update()}update(){this.icon.style.transform=`rotate(${this.el.open?0:-90}deg)`,Q.setItem(this.key,this.el.open.toString())}};function Ee(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,xe(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),xe(t.value)})}function xe(t){document.documentElement.dataset.theme=t}var K;function we(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Le),Le())}async function Le(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let n=await(await fetch(window.navigationData)).arrayBuffer(),r=new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();K=t.dataset.base,K.endsWith("/")||(K+="/"),t.innerHTML="";for(let s of i)Se(s,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Se(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML='',be(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let l=a.appendChild(document.createElement("ul"));l.className="tsd-nested-navigation";for(let u of t.children)Se(u,l,i)}else be(t,r,t.class)}function be(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));r.href=K+t.path,n&&(r.className=n),location.pathname===r.pathname&&!r.href.includes("#")&&r.classList.add("current"),t.kind&&(r.innerHTML=``),r.appendChild(document.createElement("span")).textContent=t.text}else{let r=e.appendChild(document.createElement("span"));r.innerHTML='',r.appendChild(document.createElement("span")).textContent=t.text}}G(X,"a[data-toggle]");G(Z,".tsd-accordion");G(Y,".tsd-filter-item input[type=checkbox]");var Te=document.getElementById("tsd-theme");Te&&Ee(Te);var $e=new U;Object.defineProperty(window,"app",{value:$e});fe();we();})(); /*! Bundled license information: lunr/lunr.js: diff --git a/docs/assets/style.css b/docs/assets/style.css index 9d619a64..178bfb02 100644 --- a/docs/assets/style.css +++ b/docs/assets/style.css @@ -4,11 +4,17 @@ --light-color-background-secondary: #eff0f1; --light-color-warning-text: #222; --light-color-background-warning: #e6e600; - --light-color-icon-background: var(--light-color-background); --light-color-accent: #c5c7c9; --light-color-active-menu-item: var(--light-color-accent); --light-color-text: #222; --light-color-text-aside: #6e6e6e; + + --light-color-icon-background: var(--light-color-background); + --light-color-icon-text: var(--light-color-text); + + --light-color-comment-tag-text: var(--light-color-text); + --light-color-comment-tag: var(--light-color-background); + --light-color-link: #1f70c2; --light-color-focus-outline: #3584e4; @@ -22,16 +28,17 @@ --light-color-ts-function: #572be7; --light-color-ts-class: #1f70c2; --light-color-ts-interface: #108024; - --light-color-ts-constructor: var(--light-color-ts-class); - --light-color-ts-property: var(--light-color-ts-variable); - --light-color-ts-method: var(--light-color-ts-function); + --light-color-ts-constructor: #4d7fff; + --light-color-ts-property: #ff984d; + --light-color-ts-method: #ff4db8; + --light-color-ts-reference: #ff4d82; --light-color-ts-call-signature: var(--light-color-ts-method); --light-color-ts-index-signature: var(--light-color-ts-property); --light-color-ts-constructor-signature: var(--light-color-ts-constructor); --light-color-ts-parameter: var(--light-color-ts-variable); /* type literal not included as links will never be generated to it */ --light-color-ts-type-parameter: #a55c0e; - --light-color-ts-accessor: var(--light-color-ts-property); + --light-color-ts-accessor: #ff4d4d; --light-color-ts-get-signature: var(--light-color-ts-accessor); --light-color-ts-set-signature: var(--light-color-ts-accessor); --light-color-ts-type-alias: #d51270; @@ -46,11 +53,17 @@ --dark-color-background-secondary: #1e2024; --dark-color-background-warning: #bebe00; --dark-color-warning-text: #222; - --dark-color-icon-background: var(--dark-color-background-secondary); --dark-color-accent: #9096a2; --dark-color-active-menu-item: #5d5d6a; --dark-color-text: #f5f5f5; --dark-color-text-aside: #dddddd; + + --dark-color-icon-background: var(--dark-color-background-secondary); + --dark-color-icon-text: var(--dark-color-text); + + --dark-color-comment-tag-text: var(--dark-color-text); + --dark-color-comment-tag: var(--dark-color-background); + --dark-color-link: #00aff4; --dark-color-focus-outline: #4c97f2; @@ -64,16 +77,17 @@ --dark-color-ts-function: #a280ff; --dark-color-ts-class: #8ac4ff; --dark-color-ts-interface: #6cff87; - --dark-color-ts-constructor: var(--dark-color-ts-class); - --dark-color-ts-property: var(--dark-color-ts-variable); - --dark-color-ts-method: var(--dark-color-ts-function); + --dark-color-ts-constructor: #4d7fff; + --dark-color-ts-property: #ff984d; + --dark-color-ts-method: #ff4db8; + --dark-color-ts-reference: #ff4d82; --dark-color-ts-call-signature: var(--dark-color-ts-method); --dark-color-ts-index-signature: var(--dark-color-ts-property); --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); --dark-color-ts-parameter: var(--dark-color-ts-variable); /* type literal not included as links will never be generated to it */ --dark-color-ts-type-parameter: #e07d13; - --dark-color-ts-accessor: var(--dark-color-ts-property); + --dark-color-ts-accessor: #ff4d4d; --dark-color-ts-get-signature: var(--dark-color-ts-accessor); --dark-color-ts-set-signature: var(--dark-color-ts-accessor); --dark-color-ts-type-alias: #ff6492; @@ -90,15 +104,22 @@ --color-background-secondary: var(--light-color-background-secondary); --color-background-warning: var(--light-color-background-warning); --color-warning-text: var(--light-color-warning-text); - --color-icon-background: var(--light-color-icon-background); --color-accent: var(--light-color-accent); --color-active-menu-item: var(--light-color-active-menu-item); --color-text: var(--light-color-text); --color-text-aside: var(--light-color-text-aside); + + --color-icon-background: var(--light-color-icon-background); + --color-icon-text: var(--light-color-icon-text); + + --color-comment-tag-text: var(--light-color-text); + --color-comment-tag: var(--light-color-background); + --color-link: var(--light-color-link); --color-focus-outline: var(--light-color-focus-outline); --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-project: var(--light-color-ts-project); --color-ts-module: var(--light-color-ts-module); --color-ts-namespace: var(--light-color-ts-namespace); --color-ts-enum: var(--light-color-ts-enum); @@ -110,6 +131,7 @@ --color-ts-constructor: var(--light-color-ts-constructor); --color-ts-property: var(--light-color-ts-property); --color-ts-method: var(--light-color-ts-method); + --color-ts-reference: var(--light-color-ts-reference); --color-ts-call-signature: var(--light-color-ts-call-signature); --color-ts-index-signature: var(--light-color-ts-index-signature); --color-ts-constructor-signature: var( @@ -134,15 +156,22 @@ --color-background-secondary: var(--dark-color-background-secondary); --color-background-warning: var(--dark-color-background-warning); --color-warning-text: var(--dark-color-warning-text); - --color-icon-background: var(--dark-color-icon-background); --color-accent: var(--dark-color-accent); --color-active-menu-item: var(--dark-color-active-menu-item); --color-text: var(--dark-color-text); --color-text-aside: var(--dark-color-text-aside); + + --color-icon-background: var(--dark-color-icon-background); + --color-icon-text: var(--dark-color-icon-text); + + --color-comment-tag-text: var(--dark-color-text); + --color-comment-tag: var(--dark-color-background); + --color-link: var(--dark-color-link); --color-focus-outline: var(--dark-color-focus-outline); --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-project: var(--dark-color-ts-project); --color-ts-module: var(--dark-color-ts-module); --color-ts-namespace: var(--dark-color-ts-namespace); --color-ts-enum: var(--dark-color-ts-enum); @@ -154,6 +183,7 @@ --color-ts-constructor: var(--dark-color-ts-constructor); --color-ts-property: var(--dark-color-ts-property); --color-ts-method: var(--dark-color-ts-method); + --color-ts-reference: var(--dark-color-ts-reference); --color-ts-call-signature: var(--dark-color-ts-call-signature); --color-ts-index-signature: var(--dark-color-ts-index-signature); --color-ts-constructor-signature: var( @@ -190,10 +220,16 @@ body { --color-active-menu-item: var(--light-color-active-menu-item); --color-text: var(--light-color-text); --color-text-aside: var(--light-color-text-aside); + --color-icon-text: var(--light-color-icon-text); + + --color-comment-tag-text: var(--light-color-text); + --color-comment-tag: var(--light-color-background); + --color-link: var(--light-color-link); --color-focus-outline: var(--light-color-focus-outline); --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-project: var(--light-color-ts-project); --color-ts-module: var(--light-color-ts-module); --color-ts-namespace: var(--light-color-ts-namespace); --color-ts-enum: var(--light-color-ts-enum); @@ -205,6 +241,7 @@ body { --color-ts-constructor: var(--light-color-ts-constructor); --color-ts-property: var(--light-color-ts-property); --color-ts-method: var(--light-color-ts-method); + --color-ts-reference: var(--light-color-ts-reference); --color-ts-call-signature: var(--light-color-ts-call-signature); --color-ts-index-signature: var(--light-color-ts-index-signature); --color-ts-constructor-signature: var( @@ -232,10 +269,16 @@ body { --color-active-menu-item: var(--dark-color-active-menu-item); --color-text: var(--dark-color-text); --color-text-aside: var(--dark-color-text-aside); + --color-icon-text: var(--dark-color-icon-text); + + --color-comment-tag-text: var(--dark-color-text); + --color-comment-tag: var(--dark-color-background); + --color-link: var(--dark-color-link); --color-focus-outline: var(--dark-color-focus-outline); --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-project: var(--dark-color-ts-project); --color-ts-module: var(--dark-color-ts-module); --color-ts-namespace: var(--dark-color-ts-namespace); --color-ts-enum: var(--dark-color-ts-enum); @@ -247,6 +290,7 @@ body { --color-ts-constructor: var(--dark-color-ts-constructor); --color-ts-property: var(--dark-color-ts-property); --color-ts-method: var(--dark-color-ts-method); + --color-ts-reference: var(--dark-color-ts-reference); --color-ts-call-signature: var(--dark-color-ts-call-signature); --color-ts-index-signature: var(--dark-color-ts-index-signature); --color-ts-constructor-signature: var( @@ -439,7 +483,6 @@ pre { pre { position: relative; - white-space: pre; white-space: pre-wrap; word-wrap: break-word; padding: 10px; @@ -860,6 +903,12 @@ a.tsd-index-link { margin-bottom: 0.75rem; } +.tsd-no-select { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} .tsd-kind-icon { margin-right: 0.5rem; width: 1.25rem; @@ -867,10 +916,6 @@ a.tsd-index-link { min-width: 1.25rem; min-height: 1.25rem; } -.tsd-kind-icon path { - transform-origin: center; - transform: scale(1.1); -} .tsd-signature > .tsd-kind-icon { margin-right: 0.8rem; } @@ -1242,6 +1287,9 @@ img { .tsd-kind-method { color: var(--color-ts-method); } +.tsd-kind-reference { + color: var(--color-ts-reference); +} .tsd-kind-call-signature { color: var(--color-ts-call-signature); } @@ -1254,9 +1302,6 @@ img { .tsd-kind-parameter { color: var(--color-ts-parameter); } -.tsd-kind-type-literal { - color: var(--color-ts-type-literal); -} .tsd-kind-type-parameter { color: var(--color-ts-type-parameter); } @@ -1435,7 +1480,7 @@ img { } .site-menu { - margin-top: 1rem 0; + margin-top: 1rem; } .page-menu, diff --git a/docs/functions/default.html b/docs/functions/default.html index 80c5e373..a09d34c6 100644 --- a/docs/functions/default.html +++ b/docs/functions/default.html @@ -1 +1 @@ -default | homebridge-resideo
  • Parameters

    • api: API

    Returns void

+default | @homebridge-plugins/homebridge-resideo
  • Parameters

    • api: API

    Returns void

diff --git a/docs/index.html b/docs/index.html index a6e593a1..9030335c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,20 +1,20 @@ -homebridge-resideo

homebridge-resideo

+@homebridge-plugins/homebridge-resideo

@homebridge-plugins/homebridge-resideo

homebridge-verified

Homebridge Resideo

-

The Homebridge Resideo +

The Homebridge Resideo plugin allows you to access your Resideo Device(s) from HomeKit with - Homebridge. + Homebridge.

    -
  1. Search for "Resideo" on the plugin screen of Homebridge Config UI X.
  2. +
  3. Search for "Resideo" on the plugin screen of Homebridge Config UI X.
  4. Click Install.
    -
  1. Login / create an account at https://developer.honeywellhome.com/user +
  2. Login / create an account at https://developer.honeywellhome.com/user
    • Your Resideo Developer Account, this account is different then your Resideo Account that you log into the Resideo App with
    @@ -27,14 +27,14 @@

      -
    1. Enter the generated consumer key and secret into the plugin settings screen of Homebridge Config UI X
    2. +
    3. Enter the generated consumer key and secret into the plugin settings screen of Homebridge Config UI X
    4. Click Link Account

      -
    1. Login to your https://www.resideo.com.
    2. +
    3. Login to your https://www.resideo.com.
    4. Click Allow
    5. Select Devices
        @@ -54,20 +54,20 @@
      • Restart Homebridge
    -
+
diff --git a/docs/modules.html b/docs/modules.html index b72cdab7..16dfa21a 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -1,2 +1,2 @@ -homebridge-resideo

homebridge-resideo

Index

Functions

+@homebridge-plugins/homebridge-resideo

@homebridge-plugins/homebridge-resideo

Index

Functions

diff --git a/package-lock.json b/package-lock.json index 2b7b7632..9db49532 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "homebridge-resideo", - "version": "2.1.6", + "version": "2.1.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "homebridge-resideo", - "version": "2.1.6", + "version": "2.1.7", "funding": [ { "type": "Paypal", @@ -20,8 +20,8 @@ "license": "ISC", "dependencies": { "@homebridge/plugin-ui-utils": "^1.0.3", - "rxjs": "^7.8.1", - "undici": "^6.20.1" + "axios": "1.7.7", + "rxjs": "^7.8.1" }, "devDependencies": { "@antfu/eslint-config": "^3.8.0", @@ -30,27 +30,26 @@ "@types/fs-extra": "^11.0.4", "@types/jest": "^29.5.14", "@types/mdast": "^4.0.4", - "@types/node": "^22.7.9", + "@types/node": "^22.8.7", "@types/semver": "^7.5.8", "@types/source-map-support": "^0.5.10", - "@vitest/coverage-v8": "^2.1.3", - "eslint": "^9.13.0", + "@vitest/coverage-v8": "^2.1.4", + "eslint": "^9.14.0", "eslint-plugin-format": "^0.1.2", - "homebridge": "^1.8.4", + "homebridge": "^1.8.5", "homebridge-config-ui-x": "4.62.0", "jest": "^29.7.0", "nodemon": "^3.1.7", - "npm-check-updates": "^17.1.4", "shx": "^0.3.4", "ts-node": "^10.9.2", - "typedoc": "^0.26.10", + "typedoc": "^0.26.11", "typescript": "^5.6.3", "typescript-axios-wb": "^1.0.3", - "vitest": "^2.1.3" + "vitest": "^2.1.4" }, "engines": { - "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.21 || ^2.0.0-alpha.37", - "node": "^18 || ^20 || ^22" + "homebridge": "^1.8.5 || ^2.0.0 || ^2.0.0-beta.23 || ^2.0.0-alpha.37", + "node": "^20 || ^22" } }, "node_modules/@ampproject/remapping": { @@ -199,13 +198,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz", - "integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -213,9 +213,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.9.tgz", - "integrity": "sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", "dev": true, "license": "MIT", "engines": { @@ -223,22 +223,22 @@ } }, "node_modules/@babel/core": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.9.tgz", - "integrity": "sha512-WYvQviPw+Qyib0v92AwNIrdLISTp7RfDkM7bPqBvpbnhY4wq8HvHBZREVdYDXk98C8BkOIVnHAY3yvj7AVISxQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helpers": "^7.25.9", - "@babel/parser": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", "@babel/template": "^7.25.9", "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -264,13 +264,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.9.tgz", - "integrity": "sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.9", + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -321,14 +322,13 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.9.tgz", - "integrity": "sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-simple-access": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, @@ -349,20 +349,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", - "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", @@ -394,121 +380,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.9.tgz", - "integrity": "sha512-oKWp3+usOJSzDZOucZUAMayhPz/xVjzymyDzUN8dk0Wd3RWMlGLXi07UCQ/CgQVb8LvXx3XBajJH4XGgkt7H7g==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", - "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz", - "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.9" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -573,9 +465,9 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.9.tgz", - "integrity": "sha512-u3EN9ub8LyYvgTnrgp8gboElouayiwPdnM7x5tcnW3iSt09/lQYPwMNK40I9IUxo7QOZhAsPHCmmuO7EPdruqg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { @@ -801,9 +693,9 @@ } }, "node_modules/@babel/types": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz", - "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, "license": "MIT", "dependencies": { @@ -850,7 +742,6 @@ }, "node_modules/@clack/prompts/node_modules/is-unicode-supported": { "version": "1.3.0", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -1312,9 +1203,9 @@ } }, "node_modules/@eslint-community/eslint-plugin-eslint-comments": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-4.4.0.tgz", - "integrity": "sha512-yljsWl5Qv3IkIRmJ38h3NrHXFCm4EUl55M8doGTF6hvzvFF8kRpextgSrg2dwHev9lzBZyafCr9RelGIyQm6fw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-4.4.1.tgz", + "integrity": "sha512-lb/Z/MzbTf7CaVYM9WCFNQZ4L1yi3ev2fsFPF99h31ljhSEyUoyEsKsNWiU+qD1glbYTDJdqgyaLKtyTkkqtuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1332,17 +1223,20 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } @@ -1361,9 +1255,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -1371,9 +1265,9 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.1.tgz", - "integrity": "sha512-JbHG2TWuCeNzh87fXo+/46Z1LEo9DBA9T188d0fZgGxAD+cNyS6sx9fdiyxjGPBMyQVRlCutTByZ6a5+YMkF7g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.2.tgz", + "integrity": "sha512-jhgiIrsw+tRfcBQ4BFl2C3vCrIUw2trCY0cnDvGZpwTtKCEDmZhAtMfrEUP/KpnwM6PrO0T+Ltm+ccW74olG3Q==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1499,9 +1393,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, "license": "MIT", "engines": { @@ -1535,9 +1429,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz", - "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", + "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1841,9 +1735,9 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1851,19 +1745,33 @@ } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1879,9 +1787,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz", + "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2937,9 +2845,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", - "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz", + "integrity": "sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ==", "cpu": [ "arm" ], @@ -2951,9 +2859,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", - "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.3.tgz", + "integrity": "sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q==", "cpu": [ "arm64" ], @@ -2965,9 +2873,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", - "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.3.tgz", + "integrity": "sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w==", "cpu": [ "arm64" ], @@ -2979,9 +2887,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", - "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.3.tgz", + "integrity": "sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow==", "cpu": [ "x64" ], @@ -2992,10 +2900,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.3.tgz", + "integrity": "sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.3.tgz", + "integrity": "sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", - "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.3.tgz", + "integrity": "sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A==", "cpu": [ "arm" ], @@ -3007,9 +2943,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", - "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.3.tgz", + "integrity": "sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw==", "cpu": [ "arm" ], @@ -3021,9 +2957,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", - "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.3.tgz", + "integrity": "sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ==", "cpu": [ "arm64" ], @@ -3035,9 +2971,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", - "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.3.tgz", + "integrity": "sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw==", "cpu": [ "arm64" ], @@ -3049,9 +2985,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.3.tgz", + "integrity": "sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g==", "cpu": [ "ppc64" ], @@ -3063,9 +2999,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.3.tgz", + "integrity": "sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA==", "cpu": [ "riscv64" ], @@ -3077,9 +3013,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.3.tgz", + "integrity": "sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw==", "cpu": [ "s390x" ], @@ -3091,9 +3027,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.3.tgz", + "integrity": "sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ==", "cpu": [ "x64" ], @@ -3105,9 +3041,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.3.tgz", + "integrity": "sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw==", "cpu": [ "x64" ], @@ -3119,9 +3055,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.3.tgz", + "integrity": "sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA==", "cpu": [ "arm64" ], @@ -3133,9 +3069,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.3.tgz", + "integrity": "sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ==", "cpu": [ "ia32" ], @@ -3147,9 +3083,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.3.tgz", + "integrity": "sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ==", "cpu": [ "x64" ], @@ -3161,47 +3097,47 @@ ] }, "node_modules/@shikijs/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", - "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz", + "integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", + "@shikijs/engine-javascript": "1.22.2", + "@shikijs/engine-oniguruma": "1.22.2", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.3" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", - "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz", + "integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.22.0", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "oniguruma-to-js": "0.4.3" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", - "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz", + "integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.22.0", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0" } }, "node_modules/@shikijs/types": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", - "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz", + "integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==", "dev": true, "license": "MIT", "dependencies": { @@ -3251,15 +3187,15 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.9.0.tgz", - "integrity": "sha512-OrDyFAYjBT61122MIY1a3SfEgy3YCMgt2vL4eoPmvTwDBwyQhAXurxNQznlRD/jESNfYWfID8Ej+31LljvF7Xg==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.10.1.tgz", + "integrity": "sha512-U+4yzNXElTf9q0kEfnloI9XbOyD4cnEQCxjUI94q0+W++0GAEQvJ/slwEj9lwjDHfGADRSr+Tco/z0XJvmDfCQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.8.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "@typescript-eslint/utils": "^8.12.2", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -3498,13 +3434,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.7.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.9.tgz", - "integrity": "sha512-jrTfRC7FM6nChvU7X2KqcrgquofrWLFDeYC1hKfwNWomVvrn7JIksqf344WN2X/y8xrgqBd2dJATZV4GbatBfg==", + "version": "22.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", + "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/normalize-package-data": { @@ -3570,17 +3506,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", - "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz", + "integrity": "sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/type-utils": "8.11.0", - "@typescript-eslint/utils": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/type-utils": "8.12.2", + "@typescript-eslint/utils": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -3604,16 +3540,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", - "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz", + "integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/typescript-estree": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", "debug": "^4.3.4" }, "engines": { @@ -3633,14 +3569,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", - "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", + "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0" + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3651,14 +3587,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.11.0.tgz", - "integrity": "sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz", + "integrity": "sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.11.0", - "@typescript-eslint/utils": "8.11.0", + "@typescript-eslint/typescript-estree": "8.12.2", + "@typescript-eslint/utils": "8.12.2", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -3676,9 +3612,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", - "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", + "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", "dev": true, "license": "MIT", "engines": { @@ -3690,14 +3626,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", - "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", + "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/visitor-keys": "8.11.0", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3719,16 +3655,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", - "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", + "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.11.0", - "@typescript-eslint/types": "8.11.0", - "@typescript-eslint/typescript-estree": "8.11.0" + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/typescript-estree": "8.12.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3742,13 +3678,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", - "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", + "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/types": "8.12.2", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3780,21 +3716,21 @@ "license": "ISC" }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", - "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.4.tgz", + "integrity": "sha512-FPKQuJfR6VTfcNMcGpqInmtJuVXFSCd9HQltYncfR01AzXhLucMEtQ5SinPdZxsT5x/5BK7I5qFJ5/ApGCmyTQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", + "debug": "^4.3.7", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.11", - "magicast": "^0.3.4", + "magic-string": "^0.30.12", + "magicast": "^0.3.5", "std-env": "^3.7.0", "test-exclude": "^7.0.1", "tinyrainbow": "^1.2.0" @@ -3803,8 +3739,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.3", - "vitest": "2.1.3" + "@vitest/browser": "2.1.4", + "vitest": "2.1.4" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -3834,15 +3770,15 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", - "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.4.tgz", + "integrity": "sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", + "@vitest/spy": "2.1.4", + "@vitest/utils": "2.1.4", + "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -3850,22 +3786,21 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", - "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.4.tgz", + "integrity": "sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.3", + "@vitest/spy": "2.1.4", "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" + "magic-string": "^0.30.12" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.3", - "msw": "^2.3.5", + "msw": "^2.4.9", "vite": "^5.0.0" }, "peerDependenciesMeta": { @@ -3888,9 +3823,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", - "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.4.tgz", + "integrity": "sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==", "dev": true, "license": "MIT", "dependencies": { @@ -3901,13 +3836,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", - "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.4.tgz", + "integrity": "sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.3", + "@vitest/utils": "2.1.4", "pathe": "^1.1.2" }, "funding": { @@ -3915,14 +3850,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", - "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.4.tgz", + "integrity": "sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "magic-string": "^0.30.11", + "@vitest/pretty-format": "2.1.4", + "magic-string": "^0.30.12", "pathe": "^1.1.2" }, "funding": { @@ -3930,27 +3865,27 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", - "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.4.tgz", + "integrity": "sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^3.0.0" + "tinyspy": "^3.0.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", - "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.4.tgz", + "integrity": "sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.3", - "loupe": "^3.1.1", + "@vitest/pretty-format": "2.1.4", + "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" }, "funding": { @@ -4045,9 +3980,9 @@ } }, "node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { @@ -4280,7 +4215,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, "license": "MIT" }, "node_modules/atomic-sleep": { @@ -4324,7 +4258,6 @@ "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dev": true, "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -4803,9 +4736,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001669", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", - "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", + "version": "1.0.30001676", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001676.tgz", + "integrity": "sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==", "dev": true, "funding": [ { @@ -5190,7 +5123,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -5282,13 +5214,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", - "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", + "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.23.3" + "browserslist": "^4.24.2" }, "funding": { "type": "opencollective", @@ -5602,7 +5534,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -5783,9 +5714,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.45", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.45.tgz", - "integrity": "sha512-vOzZS6uZwhhbkZbcRyiy99Wg+pYFV5hk+5YaECvx0+Z31NR3Tt5zS6dze2OepT6PCTzVzT0dIJItti+uAW5zmw==", + "version": "1.5.50", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz", + "integrity": "sha512-eMVObiUQ2LdgeO1F/ySTXsvqvxb6ZH2zPGaMYsWzRDdOddUa77tdmI0ltg+L16UpbWdhPmuF3wIQYyQq65WfZw==", "dev": true, "license": "ISC" }, @@ -6019,22 +5950,22 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -6042,9 +5973,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -6260,9 +6191,9 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.3.1.tgz", - "integrity": "sha512-5TriWkXulDl486XnYYRgsL+VQoS/7mhN/2ci02iLCuL7gdhbiWxnsuL/NTcaKY9fpMgsMFjWZBtIGW7pb+RX0g==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.4.0.tgz", + "integrity": "sha512-me58aWTjdkPtgmOzPe+uP0bebpN5etH4bJRnYzy85Rn9g/3QyASg6kTCqdwNzyaJRqMI2ii2o8s01P2LZpREHg==", "dev": true, "license": "MIT", "dependencies": { @@ -6395,20 +6326,20 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.11.1.tgz", - "integrity": "sha512-93IUD82N6tIEgjztVI/l3ElHtC2wTa9boJHrD8iN+NyDxjxz/daZUZKfkedjBZNdg6EqDk4irybUsiPwDqXAEA==", + "version": "17.12.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.12.0.tgz", + "integrity": "sha512-zNAtz/erDn0v78bIY3MASSQlyaarV4IOTvP5ldHsqblRFrXriikB6ghkDTkHjUad+nMRrIbOy9euod2azjRfBg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "enhanced-resolve": "^5.17.0", - "eslint-plugin-es-x": "^7.5.0", - "get-tsconfig": "^4.7.0", - "globals": "^15.8.0", - "ignore": "^5.2.4", + "enhanced-resolve": "^5.17.1", + "eslint-plugin-es-x": "^7.8.0", + "get-tsconfig": "^4.8.1", + "globals": "^15.11.0", + "ignore": "^5.3.2", "minimatch": "^9.0.5", - "semver": "^7.5.3" + "semver": "^7.6.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6562,9 +6493,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.29.1.tgz", - "integrity": "sha512-MH/MbVae4HV/tM8gKAVWMPJbYgW04CK7SuzYRrlNERpxbO0P3+Zdsa2oAcFBW6xNu7W6lIkGOsFAMCRTYmrlWQ==", + "version": "9.30.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.30.0.tgz", + "integrity": "sha512-CyqlRgShvljFkOeYK8wN5frh/OGTvkj1S7wlr2Q2pUvwq+X5VYiLd6ZjujpgSgLnys2W8qrBLkXQ41SUYaoPIQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6614,9 +6545,9 @@ } }, "node_modules/eslint-plugin-yml": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.14.0.tgz", - "integrity": "sha512-ESUpgYPOcAYQO9czugcX5OqRvn/ydDVwGCPXY4YjPqc09rHaUVUA6IE6HLQys4rXk/S+qx3EwTd1wHCwam/OWQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.15.0.tgz", + "integrity": "sha512-leC8APYVOsKyWUlvRwVhewytK5wS70BfMqIaUplFstRfzCoVp0YoEroV4cUEvQrBj93tQ3M9LcjO/ewr6D4kjA==", "dev": true, "license": "MIT", "dependencies": { @@ -6651,9 +6582,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -6668,9 +6599,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -6705,15 +6636,15 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6873,6 +6804,16 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/expect-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-content-type-parse": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz", @@ -7224,7 +7165,6 @@ "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "dev": true, "funding": [ { "type": "individual", @@ -7272,7 +7212,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -7565,25 +7504,25 @@ "license": "MIT" }, "node_modules/hap-nodejs": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/hap-nodejs/-/hap-nodejs-0.12.2.tgz", - "integrity": "sha512-EAgcBOxxMaWKkRfuGc8FBVJO5/OCFM2jMt5+szkqazWLKANkRLrvf/GtQnPsl6GUuLiWYddLZ/zwasayU8ljQQ==", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/hap-nodejs/-/hap-nodejs-0.12.3.tgz", + "integrity": "sha512-E6uEwSmDejvzaSAHosjjbWp7/YNo0o+LZtcbH2KoediVOHGG1tYRDGEMyOiG7ZtZn6CwXwr6xqSZTnXTzQCImQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@homebridge/ciao": "^1.2.0", + "@homebridge/ciao": "^1.3.1", "@homebridge/dbus-native": "^0.6.0", - "bonjour-hap": "^3.7.2", - "debug": "^4.3.5", + "bonjour-hap": "^3.8.0", + "debug": "^4.3.7", "fast-srp-hap": "^2.0.4", "futoin-hkdf": "^1.5.3", "node-persist": "^0.0.12", "source-map-support": "^0.5.21", - "tslib": "^2.6.2", + "tslib": "^2.8.0", "tweetnacl": "^1.0.3" }, "engines": { - "node": "^18 || ^20" + "node": "^18 || ^20 || ^22" } }, "node_modules/has-bigints": { @@ -7736,16 +7675,16 @@ } }, "node_modules/homebridge": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/homebridge/-/homebridge-1.8.4.tgz", - "integrity": "sha512-Wr5QdI/OCpxCM3rdXyuPUxNlbuwiFngnuj+ZsrCbg5cMwKRMfN+RRGiW2LUSY2BDGQC0cSUt/9TF6tIlov16Qw==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/homebridge/-/homebridge-1.8.5.tgz", + "integrity": "sha512-ovqAI1BopsD0XwE1gZoWZYroLn2nINnQ8TwHeKjqSPPDK5SG0SlhbC5ppcmcjn9SU9xIsSKOcZ9QunPxpT7Vxw==", "dev": true, "license": "Apache-2.0", "dependencies": { "chalk": "4.1.2", "commander": "12.1.0", "fs-extra": "11.2.0", - "hap-nodejs": "0.12.2", + "hap-nodejs": "0.12.3", "qrcode-terminal": "0.12.0", "semver": "7.6.3", "source-map-support": "0.5.21" @@ -7754,7 +7693,7 @@ "homebridge": "bin/homebridge" }, "engines": { - "node": "^18.15.0 || ^20.7.0" + "node": "^18.15.0 || ^20.7.0 || ^22" } }, "node_modules/homebridge-config-ui-x": { @@ -9864,9 +9803,9 @@ } }, "node_modules/mdast-util-from-markdown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", - "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", "dev": true, "license": "MIT", "dependencies": { @@ -10033,9 +9972,9 @@ } }, "node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.1.tgz", + "integrity": "sha512-OrkcCoqAkEg9b1ykXBrA0ehRc8H4fGU/03cACmW2xXzau1+dIdS+qJugh1Cqex3hMumSBgSE/5pc7uqP12nLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -10044,6 +9983,7 @@ "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" @@ -10726,7 +10666,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -10736,7 +10675,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -11172,21 +11110,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm-check-updates": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.4.tgz", - "integrity": "sha512-crOUeN2GngqlkRCFQ/zi1zsneWd9IGZgIfAWYGAuhYiPnfbBTmJBL7Yq1wI0e1dsW8CfWc+h348WmfCREqeOBA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "ncu": "build/cli.js", - "npm-check-updates": "build/cli.js" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0", - "npm": ">=8.12.1" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -12052,7 +11975,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true, "license": "MIT" }, "node_modules/pstree.remy": { @@ -12386,9 +12308,9 @@ "license": "Apache-2.0" }, "node_modules/regex": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", - "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.4.0.tgz", + "integrity": "sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==", "dev": true, "license": "MIT" }, @@ -12598,9 +12520,9 @@ "license": "MIT" }, "node_modules/rollup": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", - "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.3.tgz", + "integrity": "sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==", "dev": true, "license": "MIT", "dependencies": { @@ -12614,22 +12536,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.0", - "@rollup/rollup-android-arm64": "4.24.0", - "@rollup/rollup-darwin-arm64": "4.24.0", - "@rollup/rollup-darwin-x64": "4.24.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", - "@rollup/rollup-linux-arm-musleabihf": "4.24.0", - "@rollup/rollup-linux-arm64-gnu": "4.24.0", - "@rollup/rollup-linux-arm64-musl": "4.24.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", - "@rollup/rollup-linux-riscv64-gnu": "4.24.0", - "@rollup/rollup-linux-s390x-gnu": "4.24.0", - "@rollup/rollup-linux-x64-gnu": "4.24.0", - "@rollup/rollup-linux-x64-musl": "4.24.0", - "@rollup/rollup-win32-arm64-msvc": "4.24.0", - "@rollup/rollup-win32-ia32-msvc": "4.24.0", - "@rollup/rollup-win32-x64-msvc": "4.24.0", + "@rollup/rollup-android-arm-eabi": "4.24.3", + "@rollup/rollup-android-arm64": "4.24.3", + "@rollup/rollup-darwin-arm64": "4.24.3", + "@rollup/rollup-darwin-x64": "4.24.3", + "@rollup/rollup-freebsd-arm64": "4.24.3", + "@rollup/rollup-freebsd-x64": "4.24.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.3", + "@rollup/rollup-linux-arm-musleabihf": "4.24.3", + "@rollup/rollup-linux-arm64-gnu": "4.24.3", + "@rollup/rollup-linux-arm64-musl": "4.24.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.3", + "@rollup/rollup-linux-riscv64-gnu": "4.24.3", + "@rollup/rollup-linux-s390x-gnu": "4.24.3", + "@rollup/rollup-linux-x64-gnu": "4.24.3", + "@rollup/rollup-linux-x64-musl": "4.24.3", + "@rollup/rollup-win32-arm64-msvc": "4.24.3", + "@rollup/rollup-win32-ia32-msvc": "4.24.3", + "@rollup/rollup-win32-x64-msvc": "4.24.3", "fsevents": "~2.3.2" } }, @@ -12885,16 +12809,16 @@ } }, "node_modules/shiki": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", - "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz", + "integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/core": "1.22.0", - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", + "@shikijs/core": "1.22.2", + "@shikijs/engine-javascript": "1.22.2", + "@shikijs/engine-oniguruma": "1.22.2", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" } @@ -13934,9 +13858,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", "dev": true, "license": "MIT", "engines": { @@ -13991,9 +13915,9 @@ } }, "node_modules/tslib": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", - "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/tunnel-agent": { @@ -14053,9 +13977,9 @@ } }, "node_modules/typedoc": { - "version": "0.26.10", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz", - "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==", + "version": "0.26.11", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.11.tgz", + "integrity": "sha512-sFEgRRtrcDl2FxVP58Ze++ZK2UQAEvtvvH8rRlig1Ja3o7dDaMHmaBfvJmdGnNEFaLTpQsN8dpvZaTqJSu/Ugw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -14133,15 +14057,6 @@ "dev": true, "license": "MIT" }, - "node_modules/undici": { - "version": "6.20.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz", - "integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==", - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -14459,14 +14374,14 @@ } }, "node_modules/vite-node": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", - "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.4.tgz", + "integrity": "sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.6", + "debug": "^4.3.7", "pathe": "^1.1.2", "vite": "^5.0.0" }, @@ -14481,30 +14396,31 @@ } }, "node_modules/vitest": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", - "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.3", - "@vitest/mocker": "2.1.3", - "@vitest/pretty-format": "^2.1.3", - "@vitest/runner": "2.1.3", - "@vitest/snapshot": "2.1.3", - "@vitest/spy": "2.1.3", - "@vitest/utils": "2.1.3", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.4.tgz", + "integrity": "sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.4", + "@vitest/mocker": "2.1.4", + "@vitest/pretty-format": "^2.1.4", + "@vitest/runner": "2.1.4", + "@vitest/snapshot": "2.1.4", + "@vitest/spy": "2.1.4", + "@vitest/utils": "2.1.4", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", "pathe": "^1.1.2", "std-env": "^3.7.0", "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.3", + "vite-node": "2.1.4", "why-is-node-running": "^2.3.0" }, "bin": { @@ -14519,8 +14435,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.3", - "@vitest/ui": "2.1.3", + "@vitest/browser": "2.1.4", + "@vitest/ui": "2.1.4", "happy-dom": "*", "jsdom": "*" }, diff --git a/package.json b/package.json index a6cb2d7c..9d405c80 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,15 @@ "name": "homebridge-resideo", "displayName": "Resideo", "type": "module", - "version": "2.1.6", + "version": "2.1.7", "description": "The Resideo plugin allows you to access your Resideo device(s) from HomeKit.", "author": { "name": "donavanbecker", "url": "https://github.com/donavanbecker" }, + "maintainers": [ + "donavanbecker" + ], "publishConfig": { "access": "public" }, @@ -49,16 +52,14 @@ "leak" ], "main": "dist/index.js", - "icon": "https://github.com/homebridge-plugins/homebridge-resideo/blob/latest/branding/icon.png?raw=true", "engines": { - "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.21 || ^2.0.0-alpha.37", - "node": "^18 || ^20 || ^22" + "homebridge": "^1.8.5 || ^2.0.0 || ^2.0.0-beta.23 || ^2.0.0-alpha.37", + "node": "^20 || ^22" }, "scripts": { "check": "npm install && npm outdated", - "update": "ncu -u && npm update && npm install", "lint": "eslint src/**/*.ts", - "fix": "eslint src/**/*.ts --fix", + "lint:fix": "eslint src/**/*.ts --fix", "watch": "npm run build && npm run plugin-ui && npm link && nodemon", "plugin-ui": "rsync ./src/homebridge-ui/public/index.html ./dist/homebridge-ui/public/", "build": "npm run clean && tsc && npm run plugin-ui", @@ -71,8 +72,8 @@ }, "dependencies": { "@homebridge/plugin-ui-utils": "^1.0.3", - "rxjs": "^7.8.1", - "undici": "^6.20.1" + "axios": "1.7.7", + "rxjs": "^7.8.1" }, "devDependencies": { "@antfu/eslint-config": "^3.8.0", @@ -81,22 +82,21 @@ "@types/fs-extra": "^11.0.4", "@types/jest": "^29.5.14", "@types/mdast": "^4.0.4", - "@types/node": "^22.7.9", + "@types/node": "^22.8.7", "@types/semver": "^7.5.8", "@types/source-map-support": "^0.5.10", - "@vitest/coverage-v8": "^2.1.3", - "eslint": "^9.13.0", + "@vitest/coverage-v8": "^2.1.4", + "eslint": "^9.14.0", "eslint-plugin-format": "^0.1.2", - "homebridge": "^1.8.4", + "homebridge": "^1.8.5", "homebridge-config-ui-x": "4.62.0", "jest": "^29.7.0", "nodemon": "^3.1.7", - "npm-check-updates": "^17.1.4", "shx": "^0.3.4", "ts-node": "^10.9.2", - "typedoc": "^0.26.10", + "typedoc": "^0.26.11", "typescript": "^5.6.3", "typescript-axios-wb": "^1.0.3", - "vitest": "^2.1.3" + "vitest": "^2.1.4" } } diff --git a/src/devices/device.ts b/src/devices/device.ts index fb75e66b..4245aa75 100644 --- a/src/devices/device.ts +++ b/src/devices/device.ts @@ -50,26 +50,26 @@ export abstract class deviceBase { } async getDeviceLogSettings(accessory: PlatformAccessory, device: resideoDevice & devicesConfig): Promise { - this.deviceLogging = this.platform.debugMode ? 'debugMode' : device.logging ?? this.config.logging ?? 'standard' - const logging = this.platform.debugMode ? 'Debug Mode' : device.logging ? 'Device Config' : this.config.logging ? 'Platform Config' : 'Default' + this.deviceLogging = this.platform.debugMode ? 'debugMode' : device.logging ?? this.platform.platformLogging ?? 'standard' + const logging = this.platform.debugMode ? 'Debug Mode' : device.logging ? 'Device Config' : this.platform.platformLogging ? 'Platform Config' : 'Default' accessory.context.deviceLogging = this.deviceLogging await this.debugLog(`Using ${logging} Logging: ${this.deviceLogging}`) } async getDeviceRateSettings(accessory: PlatformAccessory, device: resideoDevice & devicesConfig): Promise { // refreshRate - this.deviceRefreshRate = device.thermostat?.roomsensor?.refreshRate ?? device.thermostat?.roompriority?.refreshRate ?? device.refreshRate ?? this.config.options?.refreshRate ?? 120 + this.deviceRefreshRate = device.thermostat?.roomsensor?.refreshRate ?? device.thermostat?.roompriority?.refreshRate ?? device.refreshRate ?? this.platform.platformRefreshRate ?? 120 const refreshRate = device.thermostat?.roomsensor?.refreshRate ? 'Room Sensor Config' : device.thermostat?.roompriority?.refreshRate ? 'Room Priority Config' : device.refreshRate ? 'Device Config' - : this.config.options?.refreshRate ? 'Platform Config' : 'Default' + : this.platform.platformRefreshRate ? 'Platform Config' : 'Default' accessory.context.deviceRefreshRate = this.deviceRefreshRate // pushRate - this.devicePushRate = device.pushRate ?? this.config.options?.pushRate ?? 0.1 - const pushRate = device.pushRate ? 'Device Config' : this.config.options?.pushRate ? 'Platform Config' : 'Default' + this.devicePushRate = device.pushRate ?? this.platform.platformPushRate ?? 0.1 + const pushRate = device.pushRate ? 'Device Config' : this.platform.platformPushRate ? 'Platform Config' : 'Default' await this.debugLog(`Using ${refreshRate} refreshRate: ${this.deviceRefreshRate}, ${pushRate} pushRate: ${this.devicePushRate}`) accessory.context.devicePushRate = this.devicePushRate } diff --git a/src/devices/leaksensors.ts b/src/devices/leaksensors.ts index f916486a..934f9df6 100644 --- a/src/devices/leaksensors.ts +++ b/src/devices/leaksensors.ts @@ -11,7 +11,6 @@ import { interval, Subject } from 'rxjs' import { skipWhile, take } from 'rxjs/operators' import { DeviceURL } from '../settings.js' -// import { request } from 'undici'; import { deviceBase } from './device.js' /** @@ -48,7 +47,7 @@ export class LeakSensor extends deviceBase { CurrentTemperature: CharacteristicValue } - // Updates + // Sensor Update SensorUpdateInProgress!: boolean doSensorUpdate!: Subject @@ -193,7 +192,7 @@ export class LeakSensor extends deviceBase { this.updateHomeKitCharacteristics() // Start an update interval - interval(this.config.options!.refreshRate! * 1000) + interval(this.deviceRefreshRate * 1000) .pipe(skipWhile(() => this.SensorUpdateInProgress)) .subscribe(async () => { await this.refreshStatus() @@ -203,48 +202,48 @@ export class LeakSensor extends deviceBase { /** * Parse the device status from the Resideo api */ - async parseStatus(device: resideoDevice & devicesConfig): Promise { + async parseStatus(): Promise { // Battery Service - this.Battery.BatteryLevel = Number(device.batteryRemaining) + this.Battery.BatteryLevel = Number(this.device.batteryRemaining) this.Battery.Service.getCharacteristic(this.hap.Characteristic.BatteryLevel).updateValue(this.Battery.BatteryLevel) if (this.device.batteryRemaining < 15) { this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW } else { this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL } - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}, StatusLowBattery: ${this.Battery.StatusLowBattery}`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}, StatusLowBattery: ${this.Battery.StatusLowBattery}`) // LeakSensor Service - if (!device.leaksensor?.hide_leak) { + if (!this.device.leaksensor?.hide_leak) { if (this.LeakSensor) { // Active - this.LeakSensor.StatusActive = device.hasDeviceCheckedIn + this.LeakSensor.StatusActive = this.device.hasDeviceCheckedIn // LeakDetected - if (device.waterPresent === true) { + if (this.device.waterPresent === true) { this.LeakSensor.LeakDetected = this.hap.Characteristic.LeakDetected.LEAK_DETECTED } else { this.LeakSensor.LeakDetected = this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED } - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} StatusActive: ${this.LeakSensor.StatusActive}, LeakDetected: ${this.LeakSensor.LeakDetected}`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} StatusActive: ${this.LeakSensor.StatusActive}, LeakDetected: ${this.LeakSensor.LeakDetected}`) } } - const currentSensorReadings = device.currentSensorReadings as CurrentSensorReadings ?? { temperature: 20, humidity: 50 } + const currentSensorReadings = this.device.currentSensorReadings as CurrentSensorReadings ?? { temperature: 20, humidity: 50 } // Temperature Service - if (!device.leaksensor?.hide_temperature) { + if (!this.device.leaksensor?.hide_temperature) { if (this.TemperatureSensor) { this.TemperatureSensor.CurrentTemperature = currentSensorReadings.temperature - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°`) } } // Humidity Service - if (!device.leaksensor?.hide_humidity) { + if (!this.device.leaksensor?.hide_humidity) { if (this.HumiditySensor) { this.HumiditySensor.CurrentRelativeHumidity = currentSensorReadings.humidity - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`) } } } @@ -254,17 +253,16 @@ export class LeakSensor extends deviceBase { */ async refreshStatus(): Promise { try { - const device: any = await this.platform.makeRequest( - `${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, - { - method: 'GET', + const device: any = ( + await this.platform.axios.get(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { params: { locationId: this.location.locationID, }, - }, - ) + }) + ).data this.debugLog(`(refreshStatus) ${device.deviceClass} device: ${JSON.stringify(device)}`) - await this.parseStatus(device) + this.device = device + await this.parseStatus() await this.updateHomeKitCharacteristics() } catch (e: any) { const action = 'refreshStatus' diff --git a/src/devices/roomsensors.ts b/src/devices/roomsensors.ts index 6aa21955..06a2fd4f 100644 --- a/src/devices/roomsensors.ts +++ b/src/devices/roomsensors.ts @@ -189,7 +189,7 @@ export class RoomSensors extends deviceBase { this.updateHomeKitCharacteristics() // Start an update interval - interval(this.config.options!.refreshRate! * 1000) + interval(this.deviceRefreshRate * 1000) .pipe(skipWhile(() => this.SensorUpdateInProgress)) .subscribe(async () => { await this.refreshStatus() @@ -199,9 +199,9 @@ export class RoomSensors extends deviceBase { /** * Parse the device status from the Resideo api */ - async parseStatus(device: resideoDevice & devicesConfig, sensorAccessory: sensorAccessory): Promise { + async parseStatus(): Promise { // Get the accessory value - const accessoryValue = sensorAccessory.accessoryValue as accessoryValue + const accessoryValue = this.sensorAccessory?.accessoryValue as accessoryValue ?? { batteryStatus: 'Ok', indoorTemperature: 20, indoorHumidity: 50, occupancyDet: false } // Set Room Sensor State @@ -210,33 +210,33 @@ export class RoomSensors extends deviceBase { } else { this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW } - this.debugLog(`${sensorAccessory?.accessoryAttribute.type} ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`) + this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`) // Set Temperature Sensor State - if (!device.thermostat?.roomsensor?.hide_temperature) { + if (!this.device.thermostat?.roomsensor?.hide_temperature) { if (this.TemperatureSensor) { this.TemperatureSensor.CurrentTemperature = toCelsius(accessoryValue.indoorTemperature, this.hap.Characteristic.TemperatureDisplayUnits.CELSIUS) - this.debugLog(`${sensorAccessory?.accessoryAttribute.type} ${this.accessory.displayName} CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`) + this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${this.accessory.displayName} CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`) } } // Set Occupancy Sensor State - if (!device.thermostat?.roomsensor?.hide_occupancy) { + if (!this.device.thermostat?.roomsensor?.hide_occupancy) { if (this.OccupancySensor) { if (accessoryValue.occupancyDet) { this.OccupancySensor.OccupancyDetected = 1 } else { this.OccupancySensor.OccupancyDetected = 0 } - this.debugLog(`${sensorAccessory?.accessoryAttribute.type} ${this.accessory.displayName} OccupancyDetected: ${this.OccupancySensor.OccupancyDetected}`) + this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${this.accessory.displayName} OccupancyDetected: ${this.OccupancySensor.OccupancyDetected}`) } } // Set Humidity Sensor State - if (!device.thermostat?.roomsensor?.hide_humidity) { + if (!this.device.thermostat?.roomsensor?.hide_humidity) { if (this.HumiditySensor) { this.HumiditySensor.CurrentRelativeHumidity = accessoryValue.indoorHumidity - this.debugLog(`${sensorAccessory?.accessoryAttribute.type} ${this.accessory.displayName} CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`) + this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${this.accessory.displayName} CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`) } } } @@ -247,8 +247,8 @@ export class RoomSensors extends deviceBase { async refreshStatus(): Promise { try { const roomsensors = await this.platform.getCurrentSensorData(this.location, this.device, this.group) - const sensorAccessory = roomsensors[this.roomId][this.accessoryId] - this.parseStatus(this.device, sensorAccessory) + this.sensorAccessory = roomsensors[this.roomId][this.accessoryId] + this.parseStatus() this.updateHomeKitCharacteristics() } catch (e: any) { const action = 'refreshStatus' diff --git a/src/devices/roomsensorthermostats.ts b/src/devices/roomsensorthermostats.ts index 0e264e9a..90c220d6 100644 --- a/src/devices/roomsensorthermostats.ts +++ b/src/devices/roomsensorthermostats.ts @@ -227,7 +227,7 @@ export class RoomSensorThermostat extends deviceBase { this.updateHomeKitCharacteristics() // Start an update interval - interval(this.config.options!.refreshRate! * 1000) + interval(this.deviceRefreshRate * 1000) .pipe(skipWhile(() => this.thermostatUpdateInProgress)) .subscribe(async () => { await this.refreshStatus() @@ -325,47 +325,47 @@ export class RoomSensorThermostat extends deviceBase { /** * Parse the device status from the Resideo api */ - async parseStatus(device: resideoDevice & devicesConfig, sensorAccessory?: sensorAccessory): Promise { + async parseStatus(): Promise { // Parse the device status - if (device.units === 'Fahrenheit') { + if (this.device.units === 'Fahrenheit') { this.Thermostat.TemperatureDisplayUnits = this.hap.Characteristic.TemperatureDisplayUnits.FAHRENHEIT } - if (device.units === 'Celsius') { + if (this.device.units === 'Celsius') { this.Thermostat.TemperatureDisplayUnits = this.hap.Characteristic.TemperatureDisplayUnits.CELSIUS } // Parse the Sensor Accessory status - if (sensorAccessory) { - const accessoryValue = sensorAccessory.accessoryValue as accessoryValue + if (this.sensorAccessory) { + const accessoryValue = this.sensorAccessory.accessoryValue as accessoryValue ?? { indoorTemperature: 20, indoorHumidity: 50 } this.Thermostat.CurrentTemperature = toCelsius(accessoryValue.indoorTemperature, Number(this.Thermostat.TemperatureDisplayUnits)) - this.debugLog(`${sensorAccessory.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} CurrentTemperature: ${this.Thermostat.CurrentTemperature}`) + this.debugLog(`${this.sensorAccessory.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} CurrentTemperature: ${this.Thermostat.CurrentTemperature}`) - if (!device.thermostat?.hide_humidity && accessoryValue.indoorHumidity) { + if (!this.device.thermostat?.hide_humidity && accessoryValue.indoorHumidity) { if (this.HumiditySensor) { this.HumiditySensor!.CurrentRelativeHumidity = accessoryValue.indoorHumidity - this.debugLog(`${sensorAccessory.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}`) + this.debugLog(`${this.sensorAccessory.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}`) } } } // Parse the Thermostat status if (this.device.changeableValues!.heatSetpoint > 0) { - this.Thermostat.HeatingThresholdTemperature = toCelsius(device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.Thermostat.HeatingThresholdTemperature = toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) } if (this.device.changeableValues!.coolSetpoint > 0) { - this.Thermostat.CoolingThresholdTemperature = toCelsius(device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.Thermostat.CoolingThresholdTemperature = toCelsius(this.device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) } - this.Thermostat.TargetHeatingCoolingState = HomeKitModes[device.changeableValues!.mode] + this.Thermostat.TargetHeatingCoolingState = HomeKitModes[this.device.changeableValues!.mode] /** * The CurrentHeatingCoolingState is either 'Heat', 'Cool', or 'Off' * CurrentHeatingCoolingState = OFF = 0, HEAT = 1, COOL = 2 */ - switch (device.operationStatus!.mode) { + switch (this.device.operationStatus!.mode) { case 'Heat': this.Thermostat.CurrentHeatingCoolingState = this.hap.Characteristic.CurrentHeatingCoolingState.HEAT // 1 break @@ -375,16 +375,16 @@ export class RoomSensorThermostat extends deviceBase { default: this.Thermostat.CurrentHeatingCoolingState = this.hap.Characteristic.CurrentHeatingCoolingState.OFF // 0 } - this.debugLog(`${sensorAccessory?.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} CurrentHeatingCoolingState: ${this.Thermostat.CurrentHeatingCoolingState}`) + this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} CurrentHeatingCoolingState: ${this.Thermostat.CurrentHeatingCoolingState}`) // Set the TargetTemperature value based on the current mode if (this.Thermostat.TargetHeatingCoolingState === this.hap.Characteristic.TargetHeatingCoolingState.HEAT) { if (this.device.changeableValues!.heatSetpoint > 0) { - this.Thermostat.TargetTemperature = toCelsius(device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.Thermostat.TargetTemperature = toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) } } else { if (this.device.changeableValues!.coolSetpoint > 0) { - this.Thermostat.TargetTemperature = toCelsius(device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.Thermostat.TargetTemperature = toCelsius(this.device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) } } } @@ -394,15 +394,17 @@ export class RoomSensorThermostat extends deviceBase { */ async refreshStatus(): Promise { try { - const device: any = await this.platform.makeRequest(`${DeviceURL}/thermostats/${this.device.deviceID}`, { - method: 'GET', - params: { - locationId: this.location.locationID, - }, - }) + const device: any = ( + await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + params: { + locationId: this.location.locationID, + }, + }) + ).data this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${device.deviceClass} ${this.accessory.displayName} (refreshStatus) device: ${JSON.stringify(device)}`) this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${device.deviceClass} ${this.accessory.displayName} Fetched update for: ${this.device.name} from Resideo API: ${JSON.stringify(this.device.changeableValues)}`) - this.parseStatus(device) + this.device = device + this.parseStatus() this.updateHomeKitCharacteristics() } catch (e: any) { const action = 'refreshStatus' @@ -442,7 +444,8 @@ export class RoomSensorThermostat extends deviceBase { if (sensorAccessory.accessoryAttribute) { if (sensorAccessory.accessoryAttribute.type) { if (sensorAccessory.accessoryAttribute.type.startsWith('IndoorAirSensor')) { - this.parseStatus(this.device, sensorAccessory) + this.sensorAccessory = sensorAccessory + this.parseStatus() this.debugLog(`${sensorAccessory.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} accessoryAttribute: ${JSON.stringify(this.sensorAccessory?.accessoryAttribute)}`) this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} Name: ${this.sensorAccessory?.accessoryAttribute.name}, Software Version: ${this.sensorAccessory?.accessoryAttribute.softwareRevision}`) } @@ -477,12 +480,13 @@ export class RoomSensorThermostat extends deviceBase { async refreshRoomPriority(): Promise { if (this.device.thermostat?.roompriority?.deviceType === 'Thermostat') { try { - const roomPriorityStatus = await this.platform.makeRequest(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { - method: 'GET', - params: { - locationId: this.location.locationID, - }, - }) + const roomPriorityStatus = ( + await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + params: { + locationId: this.location.locationID, + }, + }) + ).data this.debugLog(`${this.sensorAccessory?.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} (refreshRoomPriority) roomPriorityStatus: ${JSON.stringify(roomPriorityStatus)}`) } catch (e: any) { const action = 'refreshRoomPriority' @@ -499,7 +503,7 @@ export class RoomSensorThermostat extends deviceBase { this.apiError(e) } } - this.parseStatus(this.device, this.sensorAccessory) + this.parseStatus() this.updateHomeKitCharacteristics() } @@ -537,9 +541,7 @@ export class RoomSensorThermostat extends deviceBase { // Make the API request try { - await this.platform.makeRequest(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { - method: 'PUT', - body: JSON.stringify(payload), + await this.platform.axios.put(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, payload, { params: { locationId: this.location.locationID, }, @@ -601,9 +603,7 @@ export class RoomSensorThermostat extends deviceBase { this.successLog(`${this.sensorAccessory?.accessoryAttribute.type} ${this.device.deviceClass} ${this.accessory.displayName} set request (${JSON.stringify(payload)}) to Resideo API.`) // Make the API request - await this.platform.makeRequest(`${DeviceURL}/thermostats/${this.device.deviceID}`, { - method: 'POST', - body: JSON.stringify(payload), + await this.platform.axios.post(`${DeviceURL}/thermostats/${this.device.deviceID}`, payload, { params: { locationId: this.location.locationID, }, diff --git a/src/devices/thermostats.ts b/src/devices/thermostats.ts index 51a74761..849533a2 100644 --- a/src/devices/thermostats.ts +++ b/src/devices/thermostats.ts @@ -5,7 +5,7 @@ import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge' import type { ResideoPlatform } from '../platform.js' -import type { devicesConfig, Fan, location, payload, Priority, resideoDevice } from '../settings.js' +import type { devicesConfig, fanStatus, location, payload, resideoDevice, roomPriorityStatus } from '../settings.js' // import { request } from 'undici'; import { interval, Subject } from 'rxjs' @@ -57,18 +57,17 @@ export class Thermostats extends deviceBase { // Config thermostatSetpointStatus!: string - // Others - T9 Only - roomPriorityStatus!: Priority - // Thermostat Updates thermostatUpdateInProgress!: boolean doThermostatUpdate!: Subject // Fan Updates + fanStatus!: fanStatus fanUpdateInProgress!: boolean doFanUpdate!: Subject // Room Updates - T9 Only + roomPriorityStatus!: roomPriorityStatus roomUpdateInProgress!: boolean doRoomUpdate!: Subject @@ -312,11 +311,8 @@ export class Thermostats extends deviceBase { // Intial Refresh this.refreshStatus() - // Retrieve initial values and updateHomekit - this.updateHomeKitCharacteristics() - // Start an update interval - interval(this.config.options!.refreshRate! * 1000) + interval(this.deviceRefreshRate * 1000) .pipe(skipWhile(() => this.thermostatUpdateInProgress)) .subscribe(async () => { await this.refreshStatus() @@ -435,89 +431,85 @@ export class Thermostats extends deviceBase { /** * Parse the device status from the Resideo api */ - async parseStatus(device: resideoDevice & devicesConfig, fanStatus?: Fan, roomPriorityStatus?: Priority): Promise { + async parseStatus(): Promise { this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus`) - if (device.units === 'Fahrenheit') { + if (this.device.units === 'Fahrenheit') { this.Thermostat.TemperatureDisplayUnits = this.hap.Characteristic.TemperatureDisplayUnits.FAHRENHEIT - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus TemperatureDisplayUnits: ${this.hap.Characteristic.TemperatureDisplayUnits.FAHRENHEIT}`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus TemperatureDisplayUnits: ${this.hap.Characteristic.TemperatureDisplayUnits.FAHRENHEIT}`) } - if (device.units === 'Celsius') { + if (this.device.units === 'Celsius') { this.Thermostat.TemperatureDisplayUnits = this.hap.Characteristic.TemperatureDisplayUnits.CELSIUS - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus TemperatureDisplayUnits: ${this.hap.Characteristic.TemperatureDisplayUnits.CELSIUS}`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus TemperatureDisplayUnits: ${this.hap.Characteristic.TemperatureDisplayUnits.CELSIUS}`) } - this.Thermostat.CurrentTemperature = await toCelsius(device.indoorTemperature!, Number(this.Thermostat.TemperatureDisplayUnits)) - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus CurrentTemperature: ${toCelsius(device.indoorTemperature!, Number(this.Thermostat.TemperatureDisplayUnits))}`) + this.Thermostat.CurrentTemperature = toCelsius(this.device.indoorTemperature!, Number(this.Thermostat.TemperatureDisplayUnits)) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus CurrentTemperature: ${toCelsius(this.device.indoorTemperature!, Number(this.Thermostat.TemperatureDisplayUnits))}`) - if (device.indoorHumidity) { + if (this.device.indoorHumidity) { if (this.HumiditySensor) { - this.HumiditySensor.CurrentRelativeHumidity = device.indoorHumidity - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}`) + this.HumiditySensor.CurrentRelativeHumidity = this.device.indoorHumidity + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}`) } } - if (device.changeableValues!.heatSetpoint > 0) { - this.Thermostat.HeatingThresholdTemperature = await toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus HeatingThresholdTemperature: ${toCelsius(device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits))}`) + if (this.device.changeableValues!.heatSetpoint > 0) { + this.Thermostat.HeatingThresholdTemperature = toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus HeatingThresholdTemperature: ${toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits))}`) } - if (device.changeableValues!.coolSetpoint > 0) { - this.Thermostat.CoolingThresholdTemperature = await toCelsius(device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus CoolingThresholdTemperature: ${toCelsius(device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits))}`) + if (this.device.changeableValues!.coolSetpoint > 0) { + this.Thermostat.CoolingThresholdTemperature = toCelsius(this.device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus CoolingThresholdTemperature: ${toCelsius(this.device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits))}`) } - this.Thermostat.TargetHeatingCoolingState = HomeKitModes[device.changeableValues!.mode] - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus TargetHeatingCoolingState: ${HomeKitModes[device.changeableValues!.mode]}`) + this.Thermostat.TargetHeatingCoolingState = HomeKitModes[this.device.changeableValues!.mode] + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus TargetHeatingCoolingState: ${HomeKitModes[this.device.changeableValues!.mode]}`) /** * The CurrentHeatingCoolingState is either 'Heat', 'Cool', or 'Off' * CurrentHeatingCoolingState = OFF = 0, HEAT = 1, COOL = 2 */ - switch (device.operationStatus!.mode) { + switch (this.device.operationStatus!.mode) { case 'Heat': this.Thermostat.CurrentHeatingCoolingState = this.hap.Characteristic.CurrentHeatingCoolingState.HEAT - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus Currently Mode (HEAT): ${device.operationStatus!.mode}(${this.Thermostat.CurrentHeatingCoolingState})`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus Currently Mode (HEAT): ${this.device.operationStatus!.mode}(${this.Thermostat.CurrentHeatingCoolingState})`) break case 'Cool': this.Thermostat.CurrentHeatingCoolingState = this.hap.Characteristic.CurrentHeatingCoolingState.COOL - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus Currently Mode (COOL): ${device.operationStatus!.mode}(${this.Thermostat.CurrentHeatingCoolingState})`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus Currently Mode (COOL): ${this.device.operationStatus!.mode}(${this.Thermostat.CurrentHeatingCoolingState})`) break default: this.Thermostat.CurrentHeatingCoolingState = this.hap.Characteristic.CurrentHeatingCoolingState.OFF - this.debugLog(`${device.deviceClass} ${this.accessory.displayName} parseStatus Currently Mode (OFF): ${device.operationStatus!.mode}(${this.Thermostat.CurrentHeatingCoolingState})`) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus Currently Mode (OFF): ${this.device.operationStatus!.mode}(${this.Thermostat.CurrentHeatingCoolingState})`) } // Set the TargetTemperature value based on the current mode if (this.Thermostat.TargetHeatingCoolingState === this.hap.Characteristic.TargetHeatingCoolingState.HEAT) { - if (device.changeableValues!.heatSetpoint > 0) { - this.Thermostat.TargetTemperature = await toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) - this.debugLog( - `${device.deviceClass} ${this.accessory.displayName} parseStatus TargetTemperature (HEAT): ${toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits))})`, - ) + if (this.device.changeableValues!.heatSetpoint > 0) { + this.Thermostat.TargetTemperature = toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus TargetTemperature (HEAT): ${toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits))})`) } } else { - if (device.changeableValues) { - if (device.changeableValues.coolSetpoint > 0) { - this.Thermostat.TargetTemperature = await toCelsius(device.changeableValues.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) - this.debugLog( - `${this.device.deviceClass} ${this.accessory.displayName} parseStatus TargetTemperature (OFF/COOL): ${toCelsius(device.changeableValues.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits))})`, - ) + if (this.device.changeableValues) { + if (this.device.changeableValues.coolSetpoint > 0) { + this.Thermostat.TargetTemperature = toCelsius(this.device.changeableValues.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} parseStatus TargetTemperature (OFF/COOL): ${toCelsius(this.device.changeableValues.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits))})`) } } } // Set the Target Fan State - if (device.settings?.fan && !this.device.thermostat?.hide_fan) { + if (this.device.settings?.fan && !this.device.thermostat?.hide_fan) { if (this.Fan) { - if (fanStatus) { - this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} fanStatus: ${JSON.stringify(fanStatus)}`) - if (fanStatus.changeableValues.mode === 'Auto') { + if (this.fanStatus) { + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} fanStatus: ${JSON.stringify(this.fanStatus)}`) + if (this.fanStatus.changeableValues.mode === 'Auto') { this.Fan.TargetFanState = this.hap.Characteristic.TargetFanState.AUTO this.Fan.Active = this.hap.Characteristic.Active.INACTIVE - } else if (fanStatus.changeableValues.mode === 'On') { + } else if (this.fanStatus.changeableValues.mode === 'On') { this.Fan.TargetFanState = this.hap.Characteristic.TargetFanState.MANUAL this.Fan.Active = this.hap.Characteristic.Active.ACTIVE - } else if (fanStatus.changeableValues.mode === 'Circulate') { + } else if (this.fanStatus.changeableValues.mode === 'Circulate') { this.Fan.TargetFanState = this.hap.Characteristic.TargetFanState.MANUAL this.Fan.Active = this.hap.Characteristic.Active.INACTIVE } @@ -526,11 +518,8 @@ export class Thermostats extends deviceBase { } // Set the Room Priority Status - T9 Only - if (device.thermostat?.roompriority?.deviceType === 'Thermostat' && device.deviceModel === 'T9-T10') { - this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} roomPriorityStatus: ${JSON.stringify(roomPriorityStatus)}`) - if (roomPriorityStatus) { - this.roomPriorityStatus = roomPriorityStatus - } + if (this.device.thermostat?.roompriority?.deviceType === 'Thermostat' && this.device.deviceModel === 'T9-T10') { + this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} roomPriorityStatus: ${JSON.stringify(this.roomPriorityStatus)}`) } } @@ -539,10 +528,14 @@ export class Thermostats extends deviceBase { */ async refreshStatus(): Promise { try { - const deviceStatus: any = await this.getDeviceStatus() + const device: any = await this.getDeviceStatus() const fanStatus: any = await this.getFanStatus() const roomPriorityStatus: any = await this.getRoomPriorityStatus() - this.parseStatus(deviceStatus, fanStatus, roomPriorityStatus) + this.device = device + this.fanStatus = fanStatus + this.roomPriorityStatus = roomPriorityStatus + this.parseStatus() + this.updateHomeKitCharacteristics() } catch (e: any) { const action = 'refreshStatus' if (this.device.retry) { @@ -560,80 +553,51 @@ export class Thermostats extends deviceBase { } private async getDeviceStatus() { - const url = `${DeviceURL}/thermostats/${this.device.deviceID}` - const options = { - method: 'GET', - query: { - locationId: this.location.locationID, - apikey: this.config.credentials?.consumerKey, - }, - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', - }, - } - - const { data: device, statusCode } = await this.platform.makeRequest(url, options) - const action = 'refreshStatus' - await this.statusCode(statusCode, action) - + const device: any = ( + await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}`, { + params: { + locationId: this.location.locationID, + }, + }) + ).data this.debugLog(`(refreshStatus) ${device.deviceClass} device: ${JSON.stringify(device)}`) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} refreshStatus for ${this.device.name} from Resideo API: ${JSON.stringify(this.device.changeableValues)}`) return device } private async getRoomPriorityStatus() { - let roomPriorityStatus: any if (this.device.thermostat?.roompriority?.deviceType === 'Thermostat' && this.device.deviceModel === 'T9-T10') { - const url = `${DeviceURL}/thermostats/${this.device.deviceID}/priority` - const options = { - method: 'GET', - query: { - locationId: this.location.locationID, - apikey: this.config.credentials?.consumerKey, - }, - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', - }, - } - - const { data: roomPriority, statusCode } = await this.platform.makeRequest(url, options) + const roompriority = ( + await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, { + params: { + locationId: this.location.locationID, + }, + }) + ).data + this.debugLog(`Thermostat: ${this.accessory.displayName} Priority: ${JSON.stringify(roompriority.data)}`) const action = 'refreshRoomPriority' - await this.statusCode(statusCode, action) - - this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} (refreshRoomPriority) roompriority: ${JSON.stringify(roomPriority)}`) - roomPriorityStatus = roomPriority + await this.statusCode(200, action) + return roompriority } - return roomPriorityStatus } private async getFanStatus() { - let fanSettings: any if (this.device.settings?.fan && !this.device.thermostat?.hide_fan) { - const url = `${DeviceURL}/thermostats/${this.device.deviceID}/fan` - const options = { - method: 'GET', - query: { - locationId: this.location.locationID, - apikey: this.config.credentials?.consumerKey, - }, - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', - }, - } - - const { data: fan, statusCode } = await this.platform.makeRequest(url, options) + const fan: any = ( + await this.platform.axios.get(`${DeviceURL}/thermostats/${this.device.deviceID}/fan`, { + params: { + locationId: this.location.locationID, + }, + }) + ).data const action = 'refreshFanStatus' - await this.statusCode(statusCode, action) - + await this.statusCode(200, action) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} (refreshFanStatus) fanMode: ${JSON.stringify(fan)}`) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} fanMode: ${JSON.stringify(fan)}`) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} refreshStatus for ${this.device.name} Fan from Resideo Fan API: ${JSON.stringify(fan)}`) - fanSettings = fan + return fan } - return fanSettings + return null } /** @@ -711,7 +675,7 @@ export class Thermostats extends deviceBase { switch (this.device.deviceModel) { case 'Unknown': this.errorLog(JSON.stringify(this.device)) - payload.thermostatSetpoint = await toFahrenheit(Number(this.Thermostat.TargetTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.thermostatSetpoint = toFahrenheit(Number(this.Thermostat.TargetTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) switch (this.device.units) { case 'Fahrenheit': payload.unit = 'Fahrenheit' @@ -729,47 +693,36 @@ export class Thermostats extends deviceBase { // Set the heat and cool set point value based on the selected mode switch (this.Thermostat.TargetHeatingCoolingState) { case this.hap.Characteristic.TargetHeatingCoolingState.HEAT: - payload.heatSetpoint = await toFahrenheit(Number(this.Thermostat.TargetTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) - payload.coolSetpoint = await toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.heatSetpoint = toFahrenheit(Number(this.Thermostat.TargetTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.coolSetpoint = toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} TargetHeatingCoolingState (HEAT): ${this.Thermostat.TargetHeatingCoolingState}, TargetTemperature: ${toFahrenheit(Number(this.Thermostat.TargetTemperature), Number(this.Thermostat.TemperatureDisplayUnits))} heatSetpoint, CoolingThresholdTemperature: ${toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits))} coolSetpoint`) break case this.hap.Characteristic.TargetHeatingCoolingState.COOL: - payload.coolSetpoint = await toFahrenheit(Number(this.Thermostat.TargetTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) - payload.heatSetpoint = await toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.coolSetpoint = toFahrenheit(Number(this.Thermostat.TargetTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.heatSetpoint = toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} TargetHeatingCoolingState (COOL): ${this.Thermostat.TargetHeatingCoolingState}, TargetTemperature: ${toFahrenheit(Number(this.Thermostat.TargetTemperature), Number(this.Thermostat.TemperatureDisplayUnits))} coolSetpoint, CoolingThresholdTemperature: ${toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits))} heatSetpoint`) break case this.hap.Characteristic.TargetHeatingCoolingState.AUTO: - payload.coolSetpoint = await toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) - payload.heatSetpoint = await toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.coolSetpoint = toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.heatSetpoint = toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} TargetHeatingCoolingState (AUTO): ${this.Thermostat.TargetHeatingCoolingState}, CoolingThresholdTemperature: ${toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits))} coolSetpoint, HeatingThresholdTemperature: ${toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits))} heatSetpoint`) break default: - payload.coolSetpoint = await toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) - payload.heatSetpoint = await toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.coolSetpoint = toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) + payload.heatSetpoint = toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits)) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} TargetHeatingCoolingState (OFF): ${this.Thermostat.TargetHeatingCoolingState}, CoolingThresholdTemperature: ${toFahrenheit(Number(this.Thermostat.CoolingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits))} coolSetpoint, HeatingThresholdTemperature: ${toFahrenheit(Number(this.Thermostat.HeatingThresholdTemperature), Number(this.Thermostat.TemperatureDisplayUnits))} heatSetpoint`) } this.successLog(`${this.device.deviceClass} ${this.accessory.displayName} set request (${JSON.stringify(payload)}) to Resideo API.`) } // Attempt to make the API request - const url = `${DeviceURL}/thermostats/${this.device.deviceID}` - const options = { - method: 'POST', - data: payload, + await this.platform.axios.post(`${DeviceURL}/thermostats/${this.device.deviceID}`, payload, { params: { locationId: this.location.locationID, - apikey: this.config.credentials?.consumerKey, - }, - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', }, - } - - const { statusCode } = await this.platform.makeRequest(url, options) + }) const action = 'pushChanges' - await this.statusCode(statusCode, action) - + await this.statusCode(200, action) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} pushChanges: ${JSON.stringify(payload)}`) await this.updateHomeKitCharacteristics() } catch (e: any) { @@ -857,24 +810,13 @@ export class Thermostats extends deviceBase { ) } // Make the API request - const url = `${DeviceURL}/thermostats/${this.device.deviceID}/priority` - const options = { - method: 'PUT', - data: payload, + await this.platform.axios.put(`${DeviceURL}/thermostats/${this.device.deviceID}/priority`, payload, { params: { locationId: this.location.locationID, - apikey: this.config.credentials?.consumerKey, }, - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', - }, - } - - const { statusCode } = await this.platform.makeRequest(url, options) + }) const action = 'pushRoomChanges' - await this.statusCode(statusCode, action) - + await this.statusCode(200, action) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} pushRoomChanges: ${JSON.stringify(payload)}`) } } @@ -990,9 +932,9 @@ export class Thermostats extends deviceBase { // Set the TargetTemperature value based on the selected mode if (this.Thermostat.TargetHeatingCoolingState === this.hap.Characteristic.TargetHeatingCoolingState.HEAT) { - this.Thermostat.TargetTemperature = await toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.Thermostat.TargetTemperature = toCelsius(this.device.changeableValues!.heatSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) } else { - this.Thermostat.TargetTemperature = await toCelsius(this.device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) + this.Thermostat.TargetTemperature = toCelsius(this.device.changeableValues!.coolSetpoint, Number(this.Thermostat.TemperatureDisplayUnits)) } this.Thermostat.Service.updateCharacteristic(this.hap.Characteristic.TargetTemperature, this.Thermostat.TargetTemperature) if (this.device.thermostat?.roompriority?.deviceType === 'Thermostat' && this.device.deviceModel === 'T9-T10') { @@ -1074,23 +1016,13 @@ export class Thermostats extends deviceBase { this.successLog(`Sending request for ${this.accessory.displayName} to Resideo API Fan Mode: ${payload.mode}`) // Make the API request - const url = `${DeviceURL}/thermostats/${this.device.deviceID}/fan` - const options = { - method: 'POST', - data: payload, + await this.platform.axios.post(`${DeviceURL}/thermostats/${this.device.deviceID}/fan`, payload, { params: { locationId: this.location.locationID, - apikey: this.config.credentials?.consumerKey, - }, - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', }, - } - - const { statusCode } = await this.platform.makeRequest(url, options) + }) const action = 'pushFanChanges' - await this.statusCode(statusCode, action) + await this.statusCode(200, action) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} pushChanges: ${JSON.stringify(payload)}`) } diff --git a/src/devices/valve.ts b/src/devices/valve.ts index 5c2a7dfd..2139c9a3 100644 --- a/src/devices/valve.ts +++ b/src/devices/valve.ts @@ -57,7 +57,6 @@ export class Valve extends deviceBase { .onGet(() => this.Valve.InUse) this.refreshStatus() - this.updateHomeKitCharacteristics() interval(this.deviceRefreshRate * 1000) .pipe(skipWhile(() => this.valveUpdateInProgress)) @@ -102,20 +101,13 @@ export class Valve extends deviceBase { async refreshStatus(): Promise { try { - const response = await this.platform.makeRequest( - `${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, - { - method: 'GET', - query: { + const device: any = ( + await this.platform.axios.get(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, { + params: { locationId: this.location.locationID, }, - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', - }, - }, - ) - const device = await response.json() + }) + ).data this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} (refreshStatus) device: ${JSON.stringify(device)}`) this.parseStatus(device as resideoDevice & devicesConfig) this.updateHomeKitCharacteristics() @@ -140,27 +132,15 @@ export class Valve extends deviceBase { const payload: payload = { state: this.Valve.Active === this.hap.Characteristic.Active.ACTIVE ? 'open' : 'closed', } - const response = await this.platform.makeRequest( - `${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, - { - method: 'POST', - body: JSON.stringify(payload), - query: { - locationId: this.location.locationID, - }, - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', - }, + + await this.platform.axios.post(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, payload, { + params: { + locationId: this.location.locationID, }, - ) + }) this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} pushChanges: ${JSON.stringify(payload)}`) - if (response.statusCode === 200) { - this.successLog(`${this.device.deviceClass}: ${this.accessory.displayName} request to Resideo API, state: ${JSON.stringify(payload.state)} sent successfully`) - } else { - const action = 'pushChanges' - await this.statusCode(response.statusCode, action) - } + const action = 'pushChanges' + await this.statusCode(200, action) } catch (e: any) { const action = 'pushChanges' await this.resideoAPIError(e, action) diff --git a/src/index.ts b/src/index.ts index af29a1b6..6a603021 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,12 +2,12 @@ * * index.ts: homebridge-resideo. */ -import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'; -import { API } from 'homebridge'; -import { ResideoPlatform } from './platform.js'; +import type { API } from 'homebridge' + +import { ResideoPlatform } from './platform.js' +import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js' // Register our platform with homebridge. export default (api: API): void => { - - api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, ResideoPlatform); -}; + api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, ResideoPlatform) +} diff --git a/src/platform.ts b/src/platform.ts index aa8b8e7b..7bf71594 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -1,27 +1,28 @@ +import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios' /* Copyright(C) 2022-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved. * * platform.ts: homebridge-resideo. */ -import type { API, DynamicPlatformPlugin, HAP, Logging, PlatformAccessory, UnknownContext } from 'homebridge' +import type { API, DynamicPlatformPlugin, HAP, Logging, PlatformAccessory } from 'homebridge' import type { accessoryAttribute, devicesConfig, location, locations, + options, resideoDevice, ResideoPlatformConfig, sensorAccessory, + T9groups, } from './settings.js' -import { Buffer } from 'node:buffer' import { readFileSync, writeFileSync } from 'node:fs' -import { readFile } from 'node:fs/promises' -import process from 'node:process' +import { argv } from 'node:process' import { stringify } from 'node:querystring' -import { request } from 'undici' +import axios from 'axios' import { LeakSensor } from './devices/leaksensors.js' import { RoomSensors } from './devices/roomsensors.js' @@ -47,12 +48,19 @@ export class ResideoPlatform implements DynamicPlatformPlugin { locations?: locations sensorAccessory!: sensorAccessory firmware!: accessoryAttribute['softwareRevision'] - platformConfig!: ResideoPlatformConfig['options'] - platformLogging!: ResideoPlatformConfig['logging'] + platformConfig!: ResideoPlatformConfig + platformLogging!: options['logging'] + platformRefreshRate!: options['refreshRate'] + platformPushRate!: options['pushRate'] + platformUpdateRate!: options['updateRate'] debugMode!: boolean version!: string action!: string + public axios: AxiosInstance = axios.create({ + responseType: 'json', + }) + constructor(log: Logging, config: ResideoPlatformConfig, api: API) { this.api = api this.hap = this.api.hap @@ -61,10 +69,20 @@ export class ResideoPlatform implements DynamicPlatformPlugin { return } - this.config = { platform: 'Resideo', credentials: config.credentials, options: config.options } + this.config = { + platform: 'Resideo', + name: config.name, + credentials: config.credentials, + options: config.options, + } + + // Plugin Configuration this.getPlatformLogSettings() + this.getPlatformRateSettings() this.getPlatformConfigSettings() this.getVersion() + + // Finish initializing the platform this.debugLog(`Finished initializing platform: ${config.name}`) try { @@ -76,6 +94,15 @@ export class ResideoPlatform implements DynamicPlatformPlugin { return } + // setup axios interceptor to add headers / api key to each request + this.axios.interceptors.request.use((request: InternalAxiosRequestConfig) => { + request.headers!.Authorization = `Bearer ${this.config.credentials?.accessToken}` + request.params = request.params || {} + request.params.apikey = this.config.credentials?.consumerKey + request.headers!['Content-Type'] = 'application/json' + return request + }) + this.api.on('didFinishLaunching', async () => { this.debugLog('Executed didFinishLaunching callback') await this.refreshAccessToken() @@ -149,25 +176,33 @@ export class ResideoPlatform implements DynamicPlatformPlugin { async getAccessToken() { try { let result: any - if (this.config.credentials?.consumerSecret) { - const { body } = await request(TokenURL, { - method: 'POST', - body: stringify({ - grant_type: 'refresh_token', - refresh_token: this.config.credentials!.refreshToken, - }), - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'Authorization': `Basic ${Buffer.from(`${this.config.credentials?.consumerKey}:${this.config.credentials?.consumerSecret}`).toString('base64')}`, - }, - }) - result = await body.json() + + if (this.config.credentials!.consumerSecret && this.config.credentials?.consumerKey && this.config.credentials?.refreshToken) { + result = ( + await axios({ + url: TokenURL, + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + auth: { + username: this.config.credentials.consumerKey, + password: this.config.credentials.consumerSecret, + }, + data: stringify({ + grant_type: 'refresh_token', + refresh_token: this.config.credentials.refreshToken, + }), + responseType: 'json', + }) + ).data } else { this.warnLog('Please re-link your account in the Homebridge UI.') } this.config.credentials!.accessToken = result.access_token this.debugLog(`Got access token: ${this.config.credentials!.accessToken}`) + // check if the refresh token has changed if (result.refresh_token !== this.config.credentials!.refreshToken) { this.debugLog(`New refresh token: ${result.refresh_token}`) await this.updateRefreshToken(result.refresh_token) @@ -209,34 +244,21 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } - public async discoverlocations(): Promise { - this.debugLog(`accessToken: ${this.config.credentials?.accessToken}, consumerKey: ${this.config.credentials?.consumerKey}`) - const { body } = await request(LocationURL, { - method: 'GET', - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', - }, - }) - const locations = await body.json() as location[] - this.debugLog(`(discoverlocations) Location: ${JSON.stringify(locations)}`) - return locations // Ensure this returns an array + async discoverlocations(): Promise { + const locations = (await this.axios.get(LocationURL)).data + return locations } public async getCurrentSensorData(location: location, device: resideoDevice & devicesConfig, group: T9groups) { if (!this.sensorData[device.deviceID] || this.sensorData[device.deviceID].timestamp < Date.now()) { - const { body } = await request(`${DeviceURL}/thermostats/${device.deviceID}/group/${group.id}/rooms`, { - method: 'GET', - headers: { - 'Authorization': `Bearer ${this.config.credentials?.accessToken}`, - 'Content-Type': 'application/json', + const response: any = await this.axios.get(`${DeviceURL}/thermostats/${device.deviceID}/group/${group.id}/rooms`, { + params: { + locationId: location.locationID, }, - query: { locationId: location.locationID }, }) - const response = await body.json() this.sensorData[device.deviceID] = { timestamp: Date.now() + 45000, - data: this.normalizeSensorDate((response as { data: any }).data), + data: this.normalizeSensorDate(response.data), } this.debugLog(`getCurrentSensorData ${device.deviceType} ${device.deviceModel}: ${this.sensorData[device.deviceID]}`) } else { @@ -377,7 +399,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { if (existingAccessory) { if (await this.registerDevice(device)) { this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceID}`) - existingAccessory.displayName = device.userDefinedDeviceName + existingAccessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(device.userDefinedDeviceName, 'userDefinedDeviceName', device.userDefinedDeviceName) await this.thermostatFirmwareExistingAccessory(device, existingAccessory, location) existingAccessory.context.device = device existingAccessory.context.deviceID = device.deviceID @@ -394,6 +418,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } const accessory = new this.api.platformAccessory(device.userDefinedDeviceName, uuid) await this.thermostatFirmwareNewAccessory(device, accessory, location) + accessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(device.userDefinedDeviceName, 'userDefinedDeviceName', device.userDefinedDeviceName) accessory.context.device = device accessory.context.deviceID = device.deviceID accessory.context.model = device.deviceModel @@ -413,7 +440,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { if (existingAccessory) { if (await this.registerDevice(device)) { this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceID}`) - existingAccessory.displayName = device.userDefinedDeviceName + existingAccessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(device.userDefinedDeviceName, 'userDefinedDeviceName', device.userDefinedDeviceName) existingAccessory.context.deviceID = device.deviceID existingAccessory.context.model = device.deviceClass this.leaksensorFirmwareExistingAccessory(device, existingAccessory) @@ -428,6 +457,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { this.infoLog(`Adding new accessory: ${device.userDefinedDeviceName} ${device.deviceClass} Device ID: ${device.deviceID}`) } const accessory = new this.api.platformAccessory(device.userDefinedDeviceName, uuid) + accessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(device.userDefinedDeviceName, 'userDefinedDeviceName', device.userDefinedDeviceName) accessory.context.device = device accessory.context.deviceID = device.deviceID accessory.context.model = device.deviceClass @@ -449,7 +481,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { if (existingAccessory) { if (await this.registerDevice(device)) { this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} DeviceID: ${device.deviceID}`) - existingAccessory.displayName = device.userDefinedDeviceName + existingAccessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(device.userDefinedDeviceName, 'userDefinedDeviceName', device.userDefinedDeviceName) existingAccessory.context.deviceID = device.deviceID existingAccessory.context.model = device.deviceClass this.valveFirmwareExistingAccessory(device, existingAccessory) @@ -464,6 +498,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { this.infoLog(`Adding new accessory: ${device.userDefinedDeviceName} ${device.deviceClass} Device ID: ${device.deviceID}`) } const accessory = new this.api.platformAccessory(device.userDefinedDeviceName, uuid) + accessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(device.userDefinedDeviceName, 'userDefinedDeviceName', device.userDefinedDeviceName) accessory.context.device = device accessory.context.deviceID = device.deviceID accessory.context.model = device.deviceClass @@ -484,7 +521,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { if (existingAccessory) { if (await this.registerDevice(device)) { this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} Serial Number: ${sensorAccessory.accessoryAttribute.serialNumber}`) - existingAccessory.displayName = sensorAccessory.accessoryAttribute.name + existingAccessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(sensorAccessory.accessoryAttribute.name, 'accessoryAttributeName', sensorAccessory.accessoryAttribute.name) existingAccessory.context.deviceID = sensorAccessory.accessoryAttribute.serialNumber existingAccessory.context.model = sensorAccessory.accessoryAttribute.model this.roomsensorFirmwareExistingAccessory(existingAccessory, sensorAccessory) @@ -499,6 +538,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { this.infoLog(`Adding new accessory: ${sensorAccessory.accessoryAttribute.name} ${sensorAccessory.accessoryAttribute.type} Device ID: ${sensorAccessory.accessoryAttribute.serialNumber}`) } const accessory = new this.api.platformAccessory(sensorAccessory.accessoryAttribute.name, uuid) + accessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(sensorAccessory.accessoryAttribute.name, 'accessoryAttributeName', sensorAccessory.accessoryAttribute.name) accessory.context.deviceID = sensorAccessory.accessoryAttribute.serialNumber accessory.context.model = sensorAccessory.accessoryAttribute.model this.roomsensorFirmwareNewAccessory(accessory, sensorAccessory) @@ -518,7 +560,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { if (existingAccessory) { if (await this.registerDevice(device)) { this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} Serial Number: ${sensorAccessory.accessoryAttribute.serialNumber}`) - existingAccessory.displayName = sensorAccessory.accessoryAttribute.name + existingAccessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(sensorAccessory.accessoryAttribute.name, 'accessoryAttributeName', sensorAccessory.accessoryAttribute.name) existingAccessory.context.deviceID = sensorAccessory.accessoryAttribute.serialNumber existingAccessory.context.model = sensorAccessory.accessoryAttribute.model this.roomsensorFirmwareExistingAccessory(existingAccessory, sensorAccessory) @@ -533,6 +577,9 @@ export class ResideoPlatform implements DynamicPlatformPlugin { this.infoLog(`Adding new accessory: ${sensorAccessory.accessoryAttribute.name} ${sensorAccessory.accessoryAttribute.type} Serial Number: ${sensorAccessory.accessoryAttribute.serialNumber}`) } const accessory = new this.api.platformAccessory(sensorAccessory.accessoryAttribute.name, uuid) + accessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.userDefinedDeviceName) + : await this.validateAndCleanDisplayName(sensorAccessory.accessoryAttribute.name, 'accessoryAttributeName', sensorAccessory.accessoryAttribute.name) accessory.context.deviceID = sensorAccessory.accessoryAttribute.serialNumber accessory.context.model = sensorAccessory.accessoryAttribute.model this.roomsensorFirmwareNewAccessory(accessory, sensorAccessory) @@ -734,48 +781,95 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } async getPlatformConfigSettings() { - const platformConfig: ResideoPlatformConfig['options'] = {} if (this.config.options) { - if (this.config.options.logging) { - platformConfig.logging = this.config.options.logging - } - if (this.config.options.refreshRate) { - platformConfig.refreshRate = this.config.options.refreshRate - } - if (this.config.options.pushRate) { - platformConfig.pushRate = this.config.options.pushRate + const platformConfig: ResideoPlatformConfig = { + platform: 'Resideo', } + platformConfig.logging = this.config.options.logging ? this.config.options.logging : undefined + platformConfig.refreshRate = this.config.options.refreshRate ? this.config.options.refreshRate : undefined + platformConfig.updateRate = this.config.options.updateRate ? this.config.options.updateRate : undefined + platformConfig.pushRate = this.config.options.pushRate ? this.config.options.pushRate : undefined if (Object.entries(platformConfig).length !== 0) { - this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`) + await this.debugLog(`Platform Config: ${JSON.stringify(platformConfig)}`) } this.platformConfig = platformConfig } } + async getPlatformRateSettings() { + this.platformRefreshRate = this.config.options?.refreshRate ? this.config.options.refreshRate : 0 + const refreshRate = this.config.options?.refreshRate ? 'Using Platform Config refreshRate' : 'refreshRate Disabled by Default' + await this.debugLog(`${refreshRate}: ${this.platformRefreshRate}`) + this.platformUpdateRate = this.config.options?.updateRate ? this.config.options.updateRate : 1 + const updateRate = this.config.options?.updateRate ? 'Using Platform Config updateRate' : 'Using Default updateRate' + await this.debugLog(`${updateRate}: ${this.platformUpdateRate}`) + this.platformPushRate = this.config.options?.pushRate ? this.config.options.pushRate : 1 + const pushRate = this.config.options?.pushRate ? 'Using Platform Config pushRate' : 'Using Default pushRate' + await this.debugLog(`${pushRate}: ${this.platformPushRate}`) + } + async getPlatformLogSettings() { - this.debugMode = process.argv.includes('-D') ?? process.argv.includes('--debug') - if (this.config.options?.logging === 'debug' || this.config.options?.logging === 'standard' || this.config.options?.logging === 'none') { - this.platformLogging = this.config.options.logging - await this.debugWarnLog(`Using Config Logging: ${this.platformLogging}`) - } else if (this.debugMode) { - this.platformLogging = 'debugMode' - await this.debugWarnLog(`Using ${this.platformLogging} Logging`) - } else { - this.platformLogging = 'standard' - await this.debugWarnLog(`Using ${this.platformLogging} Logging`) - } + this.debugMode = argv.includes('-D') ?? argv.includes('--debug') + this.platformLogging = (this.config.options?.logging === 'debug' || this.config.options?.logging === 'standard' + || this.config.options?.logging === 'none') + ? this.config.options.logging + : this.debugMode ? 'debugMode' : 'standard' + const logging = this.config.options?.logging ? 'Platform Config' : this.debugMode ? 'debugMode' : 'Default' + await this.debugLog(`Using ${logging} Logging: ${this.platformLogging}`) } - public async makeRequest(url: string, options: any): Promise { - const { body, statusCode } = await request(url, options) - const data = await body.json() - return { data, statusCode } + /** + * Asynchronously retrieves the version of the plugin from the package.json file. + * + * This method reads the package.json file located in the parent directory, + * parses its content to extract the version, and logs the version using the debug logger. + * The extracted version is then assigned to the `version` property of the class. + * + * @returns {Promise} A promise that resolves when the version has been retrieved and logged. + */ + async getVersion(): Promise { + const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8')) + this.debugLog(`Plugin Version: ${version}`) + this.version = version } - async getVersion() { - const json = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf-8')) - this.debugLog(`Plugin Version: ${json.version}`) - this.version = json.version + /** + * Validate and clean a string value for a Name Characteristic. + * @param displayName - The display name of the accessory. + * @param name - The name of the characteristic. + * @param value - The value to be validated and cleaned. + * @returns The cleaned string value. + */ + async validateAndCleanDisplayName(displayName: string, name: string, value: string): Promise { + if (this.config.options?.allowInvalidCharacters) { + return value + } else { + const validPattern = /^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u + const invalidCharsPattern = /[^\p{L}\p{N} ']/gu + const invalidStartEndPattern = /^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu + + if (typeof value === 'string' && !validPattern.test(value)) { + this.warnLog(`WARNING: The accessory '${displayName}' has an invalid '${name}' characteristic ('${value}'). Please use only alphanumeric, space, and apostrophe characters. Ensure it starts and ends with an alphabetic or numeric character, and avoid emojis. This may prevent the accessory from being added in the Home App or cause unresponsiveness.`) + + // Remove invalid characters + if (invalidCharsPattern.test(value)) { + const before = value + this.warnLog(`Removing invalid characters from '${name}' characteristic, if you feel this is incorrect, please enable \'allowInvalidCharacter\' in the config to allow all characters`) + value = value.replace(invalidCharsPattern, '') + this.warnLog(`${name} Before: '${before}' After: '${value}'`) + } + + // Ensure it starts and ends with an alphanumeric character + if (invalidStartEndPattern.test(value)) { + const before = value + this.warnLog(`Removing invalid starting or ending characters from '${name}' characteristic, if you feel this is incorrect, please enable \'allowInvalidCharacter\' in the config to allow all characters`) + value = value.replace(invalidStartEndPattern, '') + this.warnLog(`${name} Before: '${before}' After: '${value}'`) + } + } + + return value + } } /** @@ -796,7 +890,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { async debugSuccessLog(...log: any[]): Promise { if (await this.enablingPlatformLogging()) { - if (this.platformLogging?.includes('debug')) { + if (await this.loggingIsDebug()) { this.log.success('[DEBUG]', String(...log)) } } @@ -810,7 +904,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { async debugWarnLog(...log: any[]): Promise { if (await this.enablingPlatformLogging()) { - if (this.platformLogging?.includes('debug')) { + if (await this.loggingIsDebug()) { this.log.warn('[DEBUG]', String(...log)) } } @@ -824,7 +918,7 @@ export class ResideoPlatform implements DynamicPlatformPlugin { async debugErrorLog(...log: any[]): Promise { if (await this.enablingPlatformLogging()) { - if (this.platformLogging?.includes('debug')) { + if (await this.loggingIsDebug()) { this.log.error('[DEBUG]', String(...log)) } } @@ -840,7 +934,11 @@ export class ResideoPlatform implements DynamicPlatformPlugin { } } + async loggingIsDebug(): Promise { + return this.platformLogging === 'debugMode' || this.platformLogging === 'debug' + } + async enablingPlatformLogging(): Promise { - return this.platformLogging.includes('debug') ?? this.platformLogging === 'standard' + return this.platformLogging === 'debugMode' || this.platformLogging === 'debug' || this.platformLogging === 'standard' } } diff --git a/src/settings.ts b/src/settings.ts index 86e1b3da..e52617a0 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -34,6 +34,8 @@ export const LocationURL = 'https://api.honeywell.com/v2/locations' */ export const DeviceURL = 'https://api.honeywell.com/v2/devices' +export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD' + // Config export interface ResideoPlatformConfig extends PlatformConfig { credentials?: credentials @@ -50,8 +52,10 @@ export interface credentials { } export interface options { + allowInvalidCharacters?: boolean logging?: string refreshRate?: number + updateRate?: number pushRate?: number devices?: devicesConfig[] } @@ -59,7 +63,7 @@ export interface options { export interface devicesConfig extends resideoDevice { deviceID: string | number // Updated to handle both string and number deviceClass: string - userDefinedDeviceName: string + configDeviceName: string hide_device?: boolean thermostat?: thermostat valve?: valve @@ -401,7 +405,7 @@ export interface accessoryValue { } // T9 Room Priority -export interface Priority { +export interface roomPriorityStatus { deviceId: string status: string currentPriority: CurrentPriority @@ -465,3 +469,9 @@ export interface maintenance { antiScaleDOMSettings: number // If monthly anti - scale is used, day of the month. antiScaleTimeSettings: string // Time for anti - scale in 24 hrs format } + +export interface fanStatus { + changeableValues: { + mode: string + } +}