diff --git a/CHANGELOG.md b/CHANGELOG.md index d86f8990..c6e0b378 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/) +## [4.1.0](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v4.1.0) (2024-10-21) + +### What's Changed +- Add `Meter Pro` deviceType Support +- Fix `node-switchbot` noble issue. +- Housekeeping and updated dependencies. + +**Full Changelog**: https://github.com/OpenWonderLabs/homebridge-switchbot/compare/v4.0.0...v4.1.0 + ## [4.0.0](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v4.0.0) (2024-10-11) ### What's Changed diff --git a/config.schema.json b/config.schema.json index 5d783864..a9579817 100644 --- a/config.schema.json +++ b/config.schema.json @@ -20,6 +20,7 @@ "token": { "title": "Token", "type": "string", + "pattern": "^[0-9A-Fa-f]+$", "x-schema-form": { "type": "token" } @@ -27,6 +28,7 @@ "secret": { "title": "Secret", "type": "string", + "pattern": "^[0-9A-Fa-f]+$", "x-schema-form": { "type": "secret" } @@ -55,6 +57,7 @@ "configDeviceName": { "title": "Device Name", "type": "string", + "pattern": "^[\\p{L}\\p{N}][\\p{L}\\p{N} ']*[\\p{L}\\p{N}]$", "placeholder": "SwitchBot", "condition": { "functionBody": "return (model.options && model.options.devices && model.options.devices[arrayIndices].deviceId);" @@ -63,7 +66,8 @@ "deviceId": { "title": "Device ID", "type": "string", - "placeholder": "81F3UT59513F" + "placeholder": "81F3UT59513F", + "pattern": "^[0-9A-F]{12}$" }, "hide_device": { "title": "Hide Device", @@ -7695,6 +7699,7 @@ "title": "Device Name", "type": "string", "placeholder": "SwitchBot", + "pattern": "^[\\p{L}\\p{N}][\\p{L}\\p{N} ']*[\\p{L}\\p{N}]$", "condition": { "functionBody": "return (model.options && model.options.irdevices && model.options.irdevices[arrayIndices].deviceId);" } @@ -7702,7 +7707,8 @@ "deviceId": { "title": "Device ID", "type": "string", - "placeholder": "81F3UT59513F" + "placeholder": "81F3UT59513F", + "pattern": "^[0-9A-Za-z]{2}-[0-9A-Za-z]{12}-[0-9A-Za-z]{8}$" }, "hide_device": { "title": "Hide Device", 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 21a5d74d..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.href.includes("#")&&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 27c0ce43..49ba9d13 100644 --- a/docs/functions/default.html +++ b/docs/functions/default.html @@ -1 +1 @@ -default | @switchbot/homebridge-switchbot
  • Parameters

    • api: API

    Returns void

+default | @switchbot/homebridge-switchbot
  • Parameters

    • api: API

    Returns void

diff --git a/docs/index.html b/docs/index.html index 392b2f21..d097fbf7 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,4 +1,4 @@ -@switchbot/homebridge-switchbot

@switchbot/homebridge-switchbot

+@switchbot/homebridge-switchbot

@switchbot/homebridge-switchbot

homebridge-verified

@switchbot/homebridge-switchbot

npm version npm downloads diff --git a/docs/modules.html b/docs/modules.html index a3e0704a..2675a027 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -1,2 +1,2 @@ -@switchbot/homebridge-switchbot

@switchbot/homebridge-switchbot

Index

Functions

default +@switchbot/homebridge-switchbot

@switchbot/homebridge-switchbot

Index

Functions

diff --git a/package-lock.json b/package-lock.json index 86e7fe60..b0aec4b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@switchbot/homebridge-switchbot", - "version": "4.0.0", + "version": "4.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@switchbot/homebridge-switchbot", - "version": "4.0.0", + "version": "4.1.0", "funding": [ { "type": "Paypal", @@ -23,33 +23,33 @@ "async-mqtt": "^2.6.3", "fakegato-history": "^0.6.5", "homebridge-lib": "^7.0.9", - "node-switchbot": "^3.1.1", + "node-switchbot": "^3.2.1", "rxjs": "^7.8.1" }, "devDependencies": { - "@antfu/eslint-config": "^3.7.3", + "@antfu/eslint-config": "^3.8.0", "@types/aes-js": "^3.1.4", "@types/debug": "^4.1.12", "@types/fs-extra": "^11.0.4", "@types/mdast": "^4.0.4", - "@types/node": "^22.7.5", + "@types/node": "^22.7.8", "@types/semver": "^7.5.8", "@types/source-map-support": "^0.5.10", - "@vitest/coverage-v8": "^2.1.2", - "eslint": "^9.12.0", + "@vitest/coverage-v8": "^2.1.3", + "eslint": "^9.13.0", "eslint-plugin-format": "^0.1.2", "homebridge": "^1.8.4", - "homebridge-config-ui-x": "4.61.0", + "homebridge-config-ui-x": "4.62.0", "nodemon": "^3.1.7", - "npm-check-updates": "^17.1.3", + "npm-check-updates": "^17.1.4", "shx": "^0.3.4", "ts-node": "^10.9.2", - "typedoc": "^0.26.9", + "typedoc": "^0.26.10", "typescript": "^5.6.3", - "vitest": "^2.1.2" + "vitest": "^2.1.3" }, "engines": { - "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.11 || ^2.0.0-alpha.10", + "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.22 || ^2.0.0-alpha.37", "node": "^20 || ^22" } }, @@ -68,43 +68,43 @@ } }, "node_modules/@antfu/eslint-config": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-3.7.3.tgz", - "integrity": "sha512-vzhKtzQT+f/xBV8T5U8SFy3D7uAqL2CEcjsJVqtA7F8tdKvGuC/96uWeEKMHk5lRfijgj+xRvb+c4qQn60YlIA==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-3.8.0.tgz", + "integrity": "sha512-O5QSufPHpKTm0wk1OQ5c2mOZVzCqYV3hIDrt5zt+cOWqiG8YXLPkSOD4fFwjomATtOuUbcLUwkcgY5dErM7aIw==", "dev": true, "license": "MIT", "dependencies": { "@antfu/install-pkg": "^0.4.1", "@clack/prompts": "^0.7.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.4.0", - "@eslint/markdown": "^6.1.0", - "@stylistic/eslint-plugin": "^2.8.0", - "@typescript-eslint/eslint-plugin": "^8.7.0", - "@typescript-eslint/parser": "^8.7.0", - "@vitest/eslint-plugin": "^1.1.4", + "@eslint/markdown": "^6.2.0", + "@stylistic/eslint-plugin": "^2.9.0", + "@typescript-eslint/eslint-plugin": "^8.9.0", + "@typescript-eslint/parser": "^8.9.0", + "@vitest/eslint-plugin": "^1.1.7", "eslint-config-flat-gitignore": "^0.3.0", "eslint-flat-config-utils": "^0.4.0", "eslint-merge-processors": "^0.1.0", "eslint-plugin-antfu": "^2.7.0", "eslint-plugin-command": "^0.2.6", - "eslint-plugin-import-x": "^4.3.0", - "eslint-plugin-jsdoc": "^50.3.0", + "eslint-plugin-import-x": "^4.3.1", + "eslint-plugin-jsdoc": "^50.4.1", "eslint-plugin-jsonc": "^2.16.0", - "eslint-plugin-n": "^17.10.3", + "eslint-plugin-n": "^17.11.1", "eslint-plugin-no-only-tests": "^3.3.0", - "eslint-plugin-perfectionist": "^3.7.0", + "eslint-plugin-perfectionist": "^3.9.0", "eslint-plugin-regexp": "^2.6.0", "eslint-plugin-toml": "^0.11.1", - "eslint-plugin-unicorn": "^55.0.0", + "eslint-plugin-unicorn": "^56.0.0", "eslint-plugin-unused-imports": "^4.1.4", - "eslint-plugin-vue": "^9.28.0", + "eslint-plugin-vue": "^9.29.0", "eslint-plugin-yml": "^1.14.0", "eslint-processor-vue-blocks": "^0.1.2", - "globals": "^15.9.0", + "globals": "^15.11.0", "jsonc-eslint-parser": "^2.4.0", "local-pkg": "^0.5.0", "parse-gitignore": "^2.0.0", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "toml-eslint-parser": "^0.10.0", "vue-eslint-parser": "^9.4.3", "yaml-eslint-parser": "^1.2.3", @@ -124,7 +124,7 @@ "eslint": "^9.10.0", "eslint-plugin-astro": "^1.2.0", "eslint-plugin-format": ">=0.1.0", - "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.4", "eslint-plugin-solid": "^0.14.3", "eslint-plugin-svelte": ">=2.35.1", @@ -913,9 +913,9 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.0.tgz", - "integrity": "sha512-CkPWddN7J9JPrQedEr2X7AjK9y1jaMJtxZ4A/+jTMFA2+n5BWhcKHW/EbJyARqg2zzQfgtWUtVmG3hrG6+nGpg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.1.tgz", + "integrity": "sha512-JbHG2TWuCeNzh87fXo+/46Z1LEo9DBA9T188d0fZgGxAD+cNyS6sx9fdiyxjGPBMyQVRlCutTByZ6a5+YMkF7g==", "dev": true, "license": "Apache-2.0", "engines": { @@ -970,9 +970,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", - "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1041,9 +1041,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", - "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", + "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", "dev": true, "license": "MIT", "engines": { @@ -1051,9 +1051,9 @@ } }, "node_modules/@eslint/markdown": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.2.0.tgz", - "integrity": "sha512-ZLWZ6RNy5flf1Nk2DBt0V77MQpQEo8snkjVT75P5J0SJkE/QNoqgy7+dBvNjlyZuj664pU43uDXWg3J8AfF0IQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.2.1.tgz", + "integrity": "sha512-cKVd110hG4ICHmWhIwZJfKmmJBvbiDWyrHODJknAtudKgZtlROGoLX9UEOA0o746zC0hCY4UV4vR+aOGW9S6JQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1077,9 +1077,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "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==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1129,11 +1129,11 @@ } }, "node_modules/@fastify/ajv-compiler/node_modules/ajv/node_modules/fast-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", - "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause" }, "node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": { "version": "1.0.0", @@ -1561,9 +1561,9 @@ } }, "node_modules/@nestjs/common": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.4.tgz", - "integrity": "sha512-0j2/zqRw9nvHV1GKTktER8B/hIC/Z8CYFjN/ZqUuvwayCH+jZZBhCR2oRyuvLTXdnlSmtCAg2xvQ0ULqQvzqhA==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.5.tgz", + "integrity": "sha512-N/yUyuYCBMb0+H6jHhntR7PURzji0usID/DByhOfooyk/aPGscI0aQKwOA6edlJlT92hHUvXYLJ5p3npj7KcjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1590,10 +1590,17 @@ } } }, + "node_modules/@nestjs/common/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, "node_modules/@nestjs/core": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.4.tgz", - "integrity": "sha512-y9tjmAzU6LTh1cC/lWrRsCcOd80khSR0qAHAqwY2svbW+AhsR/XCzgpZrAAKJrm/dDfjLCZKyxJSayeirGcW5Q==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.5.tgz", + "integrity": "sha512-wk0KJ+6tuidqAdeemsQ40BCp1BgMsSuSLG577aqXLxXYoa8FQYPrdxoSzd05znYLwJYM55fisZWb3FLF9HT2qw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1629,6 +1636,13 @@ } } }, + "node_modules/@nestjs/core/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, "node_modules/@nestjs/jwt": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.2.0.tgz", @@ -1676,9 +1690,9 @@ } }, "node_modules/@nestjs/platform-fastify": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-10.4.4.tgz", - "integrity": "sha512-3fRt9mhhqe7aS1kF9myAFSUazhW88yrq9w3LrdHbjOTkGh8ZiZckjzKL705xORVJw2d/BHkgP8AqoNthakLJeQ==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-10.4.5.tgz", + "integrity": "sha512-5kcLsloaKkG6i46qbHmz6m/XoEtwroBni3uwsNENw4OJ8fptllihOqG3PWKRfljfpH4twyKdtZfKvyjMHXNj4w==", "dev": true, "license": "MIT", "dependencies": { @@ -1686,7 +1700,7 @@ "@fastify/formbody": "7.4.0", "@fastify/middie": "8.3.3", "fastify": "4.28.1", - "light-my-request": "6.0.0", + "light-my-request": "6.1.0", "path-to-regexp": "3.3.0", "tslib": "2.7.0" }, @@ -1709,10 +1723,17 @@ } } }, + "node_modules/@nestjs/platform-fastify/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, "node_modules/@nestjs/platform-socket.io": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.4.tgz", - "integrity": "sha512-5GEYUA3sNbX2jOBP6FmrIK/zv9VCdvpdr4Sef1OKvt1U0qsV1YgmWPWDPumZM77n5DI0VHSJPyo7yjZaEKWOiQ==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.5.tgz", + "integrity": "sha512-dHkHJQArhrpkX6qBdTW2ghuja3i3cCslwy4QHY6d46u+9UyANQlsNK9wt/lZnmXfCMaci8xAJvUpyODa6YtV7g==", "dev": true, "license": "MIT", "dependencies": { @@ -1729,6 +1750,13 @@ "rxjs": "^7.1.0" } }, + "node_modules/@nestjs/platform-socket.io/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, "node_modules/@nestjs/swagger": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.2.tgz", @@ -1764,9 +1792,9 @@ } }, "node_modules/@nestjs/websockets": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.4.tgz", - "integrity": "sha512-ZHnak04i/iKBS0csjJa7K6D6xdsB0Yz6duJuCR7xGLItchFK+Ne21m9rEF8ffvW74U7UAYkQHBgD5242LBBYiQ==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.5.tgz", + "integrity": "sha512-LbL/HRLWQUBTUPY7swojOHdvokyVGINIiuP/VmRdhob4T751r+9i09z2RqRpP71psuom9mnRHYI1+vT2FABrAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1787,6 +1815,13 @@ } } }, + "node_modules/@nestjs/websockets/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true, + "license": "0BSD" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2697,9 +2732,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "version": "22.7.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.8.tgz", + "integrity": "sha512-a922jJy31vqR5sk+kAdIENJjHblqcZ4RmERviFsER4WJcEONqxKcjNOlk0q7OUfrF5sddT+vng070cdfMlrPLg==", "dev": true, "license": "MIT", "dependencies": { @@ -2752,17 +2787,17 @@ "optional": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz", - "integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.11.0.tgz", + "integrity": "sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.8.1", - "@typescript-eslint/type-utils": "8.8.1", - "@typescript-eslint/utils": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1", + "@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", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2786,16 +2821,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz", - "integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", + "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.8.1", - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/typescript-estree": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1", + "@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", "debug": "^4.3.4" }, "engines": { @@ -2815,14 +2850,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz", - "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", + "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1" + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2833,14 +2868,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz", - "integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.8.1", - "@typescript-eslint/utils": "8.8.1", + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/utils": "8.11.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2858,9 +2893,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz", - "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", + "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", "dev": true, "license": "MIT", "engines": { @@ -2872,14 +2907,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz", - "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", + "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/visitor-keys": "8.8.1", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2901,16 +2936,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz", - "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.11.0.tgz", + "integrity": "sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.8.1", - "@typescript-eslint/types": "8.8.1", - "@typescript-eslint/typescript-estree": "8.8.1" + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2924,13 +2959,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz", - "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/types": "8.11.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2962,9 +2997,9 @@ "license": "ISC" }, "node_modules/@vitest/coverage-v8": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.2.tgz", - "integrity": "sha512-b7kHrFrs2urS0cOk5N10lttI8UdJ/yP3nB4JYTREvR5o18cR99yPpK4gK8oQgI42BVv0ILWYUSYB7AXkAUDc0g==", + "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==", "dev": true, "license": "MIT", "dependencies": { @@ -2985,8 +3020,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "2.1.2", - "vitest": "2.1.2" + "@vitest/browser": "2.1.3", + "vitest": "2.1.3" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -3016,14 +3051,14 @@ } }, "node_modules/@vitest/expect": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.2.tgz", - "integrity": "sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", + "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.2", - "@vitest/utils": "2.1.2", + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" }, @@ -3032,13 +3067,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.2.tgz", - "integrity": "sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", + "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "^2.1.0-beta.1", + "@vitest/spy": "2.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.11" }, @@ -3046,7 +3081,7 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/spy": "2.1.2", + "@vitest/spy": "2.1.3", "msw": "^2.3.5", "vite": "^5.0.0" }, @@ -3070,9 +3105,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.2.tgz", - "integrity": "sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", + "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3083,13 +3118,13 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.2.tgz", - "integrity": "sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", + "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "2.1.2", + "@vitest/utils": "2.1.3", "pathe": "^1.1.2" }, "funding": { @@ -3097,13 +3132,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.2.tgz", - "integrity": "sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", + "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.2", + "@vitest/pretty-format": "2.1.3", "magic-string": "^0.30.11", "pathe": "^1.1.2" }, @@ -3112,9 +3147,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.2.tgz", - "integrity": "sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", + "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3125,13 +3160,13 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.2.tgz", - "integrity": "sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", + "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.2", + "@vitest/pretty-format": "2.1.3", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" }, @@ -3212,19 +3247,6 @@ "license": "BSD-2-Clause", "optional": true }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/abstract-logging": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", @@ -3247,9 +3269,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", "dev": true, "license": "MIT", "bin": { @@ -3347,11 +3369,11 @@ } }, "node_modules/ajv-formats/node_modules/fast-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", - "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause" }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", @@ -3699,9 +3721,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -3719,10 +3741,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -3827,9 +3849,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001668", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz", - "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==", + "version": "1.0.30001669", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", + "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", "dev": true, "funding": [ { @@ -4278,9 +4300,9 @@ } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "license": "MIT", "engines": { @@ -4728,9 +4750,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.36", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.36.tgz", - "integrity": "sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==", + "version": "1.5.41", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.41.tgz", + "integrity": "sha512-dfdv/2xNjX0P8Vzme4cfzHqnPm5xsZXwsolTYr0eyW18IUmNyG08vL+fttvinTfhKfIKdRoqkDIC9e9iWQCNYQ==", "dev": true, "license": "ISC" }, @@ -4969,18 +4991,18 @@ } }, "node_modules/eslint": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", - "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", + "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.6.0", + "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.12.0", + "@eslint/js": "9.13.0", "@eslint/plugin-kit": "^0.2.0", "@humanfs/node": "^0.16.5", "@humanwhocodes/module-importer": "^1.0.1", @@ -5235,13 +5257,13 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.3.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.2.tgz", - "integrity": "sha512-TjgZocG53N3a84PdCFGqVMWLWwDitOUuKjlJftwTu/iTiD7N/Q2Q3eEy/Q4GfJqpM4rTJCkzUYWQfol6RZNDcA==", + "version": "50.4.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.4.3.tgz", + "integrity": "sha512-uWtwFxGRv6B8sU63HZM5dAGDhgsatb+LONwmILZJhdRALLOkCX2HFZhdL/Kw2ls8SQMAVEfK+LmnEfxInRN8HA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.48.0", + "@es-joy/jsdoccomment": "~0.49.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.3.6", @@ -5260,6 +5282,21 @@ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-jsdoc/node_modules/@es-joy/jsdoccomment": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz", + "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/eslint-plugin-jsonc": { "version": "2.16.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.16.0.tgz", @@ -5366,14 +5403,14 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.8.0.tgz", - "integrity": "sha512-BYJWbQVOjvIGK9V1xUfn790HuvkePjxti8epOi1H6sdzo0N4RehBmQ8coHPbgA/f12BUG1NIoDtQhI9mUm+o2A==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.9.1.tgz", + "integrity": "sha512-9WRzf6XaAxF4Oi5t/3TqKP5zUjERhasHmLFHin2Yw6ZAp/EP/EVA2dr3BhQrrHWCm5SzTMZf0FcjDnBkO2xFkA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.8.0", - "@typescript-eslint/utils": "^8.8.0", + "@typescript-eslint/types": "^8.9.0", + "@typescript-eslint/utils": "^8.9.0", "minimatch": "^9.0.5", "natural-compare-lite": "^1.4.0" }, @@ -5447,19 +5484,19 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "55.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-55.0.0.tgz", - "integrity": "sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==", + "version": "56.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-56.0.0.tgz", + "integrity": "sha512-aXpddVz/PQMmd69uxO98PA4iidiVNvA0xOtbpUoz1WhBd4RxOQQYqN618v68drY0hmy5uU2jy1bheKEVWBjlPw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.7", "@eslint-community/eslint-utils": "^4.4.0", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", - "core-js-compat": "^3.37.0", - "esquery": "^1.5.0", - "globals": "^15.7.0", + "core-js-compat": "^3.38.1", + "esquery": "^1.6.0", + "globals": "^15.9.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", @@ -5467,7 +5504,7 @@ "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", - "semver": "^7.6.1", + "semver": "^7.6.3", "strip-indent": "^3.0.0" }, "engines": { @@ -5497,9 +5534,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.29.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.29.0.tgz", - "integrity": "sha512-hamyjrBhNH6Li6R1h1VF9KHfshJlKgKEg3ARbGTn72CMNDSMhWbgC7NdkRDEh25AFW+4SDATzyNM+3gWuZii8g==", + "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==", "dev": true, "license": "MIT", "dependencies": { @@ -5727,26 +5764,6 @@ "through": "^2.3.8" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -5909,11 +5926,11 @@ } }, "node_modules/fast-json-stringify/node_modules/ajv/node_modules/fast-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", - "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause" }, "node_modules/fast-json-stringify/node_modules/json-schema-traverse": { "version": "1.0.0", @@ -6015,16 +6032,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fastify/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/fastify/node_modules/light-my-request": { "version": "5.14.0", "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.14.0.tgz", @@ -6809,9 +6816,9 @@ } }, "node_modules/homebridge-config-ui-x": { - "version": "4.61.0", - "resolved": "https://registry.npmjs.org/homebridge-config-ui-x/-/homebridge-config-ui-x-4.61.0.tgz", - "integrity": "sha512-jmilxafuUxwA7Wm1jJ02zAjNQb1anz2668p63ZpBHahbHYg8kT1sIKLIb53FmlTzVrf+CCoJzXo4EJ2UUqNn0Q==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/homebridge-config-ui-x/-/homebridge-config-ui-x-4.62.0.tgz", + "integrity": "sha512-f1k7m90EqGUnHPN8Jo3UhXlVEMN2brJJO8KkysxTU8Wk9qwO2VmE957JJ0LWflQRlgJCMn/iaDW5zt5bR3dkWg==", "dev": true, "funding": [ { @@ -6831,14 +6838,14 @@ "@homebridge/hap-client": "1.10.2", "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", "@nestjs/axios": "3.0.3", - "@nestjs/common": "10.4.4", - "@nestjs/core": "10.4.4", + "@nestjs/common": "10.4.5", + "@nestjs/core": "10.4.5", "@nestjs/jwt": "10.2.0", "@nestjs/passport": "10.0.3", - "@nestjs/platform-fastify": "10.4.4", - "@nestjs/platform-socket.io": "10.4.4", + "@nestjs/platform-fastify": "10.4.5", + "@nestjs/platform-socket.io": "10.4.5", "@nestjs/swagger": "7.4.2", - "@nestjs/websockets": "10.4.4", + "@nestjs/websockets": "10.4.5", "axios": "1.7.7", "bash-color": "0.0.4", "buffer-shims": "1.0.0", @@ -7894,20 +7901,20 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.11.11", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.11.tgz", - "integrity": "sha512-mF3KaORjJQR6JBNcOkluDcJKhtoQT4VTLRMrX1v/wlBayL4M8ybwEDeryyPcrSEJmD0rVwHUbBarpZwN5NfPFQ==", + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.12.tgz", + "integrity": "sha512-QkJn9/D7zZ1ucvT++TQSvZuSA2xAWeUytU+DiEQwbPKLyrDpvbul2AFs1CGbRAPpSCCk47aRAb5DX5mmcayp4g==", "dev": true, "license": "MIT" }, "node_modules/light-my-request": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.0.0.tgz", - "integrity": "sha512-kFkFXrmKCL0EEeOmJybMH5amWFd+AFvlvMlvFTRxCUwbhfapZqDmeLMPoWihntnYY6JpoQDE9k+vOzObF1fDqg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.1.0.tgz", + "integrity": "sha512-+NFuhlOGoEwxeQfJ/pobkVFxcnKyDtiX847hLjuB/IzBxIl3q4VJeFI8uRCgb3AlTWL1lgOr+u5+8QdUcr33ng==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "cookie": "^0.6.0", + "cookie": "^0.7.0", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } @@ -9360,9 +9367,9 @@ } }, "node_modules/node-abi": { - "version": "3.68.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.68.0.tgz", - "integrity": "sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==", + "version": "3.71.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", + "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==", "dev": true, "license": "MIT", "dependencies": { @@ -9466,14 +9473,14 @@ } }, "node_modules/node-switchbot": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-switchbot/-/node-switchbot-3.1.1.tgz", - "integrity": "sha512-JqEBHb0BHp5RZCtXPXw3atJiTNracOmmAO1t59vDjd1v12AFpSPiwVRoaZ6zWH6MQ3/IYb5GKtjmIi8YApZ1VQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-switchbot/-/node-switchbot-3.2.1.tgz", + "integrity": "sha512-L3zf2BjNmYc+W77yGPaBrYDcuOhFutS7j/Bsp+DZN2dXQu2++6LarsDuj5RK6/B9o4xM4he/P30IdIN5iWTX5w==", "license": "MIT", "dependencies": { "@stoprocent/noble": "^1.15.1", "async-mutex": "^0.5.0", - "undici": "^6.20.0" + "undici": "^6.20.1" }, "engines": { "node": "^20 || ^22" @@ -9592,9 +9599,9 @@ } }, "node_modules/npm-check-updates": { - "version": "17.1.3", - "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.3.tgz", - "integrity": "sha512-4uDLBWPuDHT5KLieIJ20FoAB8yqJejmupI42wPyfObgQOBbPAikQSwT73afDwREvhuxYrRDqlRvxTMSfvO+L8A==", + "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": { @@ -10181,9 +10188,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -10201,16 +10208,16 @@ } }, "node_modules/pino": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.4.0.tgz", - "integrity": "sha512-nbkQb5+9YPhQRz/BeQmrWpEknAaqjpAqRK8NwJpmrX/JHu7JuZC5G1CeAwJDJfGes4h+YihC6in3Q2nGb+Y09w==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.5.0.tgz", + "integrity": "sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==", "dev": true, "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.2.0", + "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^4.0.0", "quick-format-unescaped": "^4.0.3", @@ -10224,58 +10231,15 @@ } }, "node_modules/pino-abstract-transport": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", - "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", "dev": true, "license": "MIT", "dependencies": { - "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, - "node_modules/pino-abstract-transport/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/pino-abstract-transport/node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -10440,16 +10404,6 @@ "node": ">=6.0.0" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -11252,9 +11206,9 @@ "optional": true }, "node_modules/set-cookie-parser": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.0.tgz", - "integrity": "sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", "dev": true, "license": "MIT" }, @@ -11605,9 +11559,9 @@ } }, "node_modules/sonic-boom": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.1.0.tgz", - "integrity": "sha512-NGipjjRicyJJ03rPiZCJYjwlsuP2d1/5QUviozRXC7S3WdVWNK5e3Ojieb9CCyfhq2UC+3+SRd9nG3I2lPRvUw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", "dev": true, "license": "MIT", "dependencies": { @@ -12229,9 +12183,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", "dev": true, "license": "MIT" }, @@ -12435,9 +12389,9 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "license": "0BSD" }, "node_modules/tunnel-agent": { @@ -12490,9 +12444,9 @@ "license": "MIT" }, "node_modules/typedoc": { - "version": "0.26.9", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.9.tgz", - "integrity": "sha512-Rc7QpWL7EtmrT8yxV0GmhOR6xHgFnnhphbD9Suti3fz3um7ZOrou6q/g9d6+zC5PssTLZmjaW4Upmzv8T1rCcQ==", + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.10.tgz", + "integrity": "sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -12561,9 +12515,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.0.tgz", - "integrity": "sha512-AITZfPuxubm31Sx0vr8bteSalEbs9wQb/BOBi9FPlD9Qpd6HxZ4Q0+hI742jBhkPb4RT2v5MQzaW5VhRVyj+9A==", + "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" @@ -12845,9 +12799,9 @@ } }, "node_modules/vite": { - "version": "5.4.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", - "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "version": "5.4.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz", + "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", "dev": true, "license": "MIT", "dependencies": { @@ -12905,9 +12859,9 @@ } }, "node_modules/vite-node": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.2.tgz", - "integrity": "sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", + "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", "dev": true, "license": "MIT", "dependencies": { @@ -12927,19 +12881,19 @@ } }, "node_modules/vitest": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.2.tgz", - "integrity": "sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A==", + "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.2", - "@vitest/mocker": "2.1.2", - "@vitest/pretty-format": "^2.1.2", - "@vitest/runner": "2.1.2", - "@vitest/snapshot": "2.1.2", - "@vitest/spy": "2.1.2", - "@vitest/utils": "2.1.2", + "@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", @@ -12950,7 +12904,7 @@ "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.2", + "vite-node": "2.1.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -12965,8 +12919,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.2", - "@vitest/ui": "2.1.2", + "@vitest/browser": "2.1.3", + "@vitest/ui": "2.1.3", "happy-dom": "*", "jsdom": "*" }, @@ -13368,9 +13322,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", "devOptional": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 4b67dcac..f6e2ac4c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@switchbot/homebridge-switchbot", "displayName": "SwitchBot", "type": "module", - "version": "4.0.0", + "version": "4.1.0", "description": "The SwitchBot plugin allows you to access your SwitchBot device(s) from HomeKit.", "author": "SwitchBot (https://github.com/SwitchBot)", "contributors": [ @@ -55,7 +55,7 @@ "icon": "https://raw.githubusercontent.com/OpenWonderLabs/homebridge-switchbot/latest/branding/icon.png", "engineStrict": true, "engines": { - "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.11 || ^2.0.0-alpha.10", + "homebridge": "^1.8.4 || ^2.0.0 || ^2.0.0-beta.22 || ^2.0.0-alpha.37", "node": "^20 || ^22" }, "scripts": { @@ -81,30 +81,30 @@ "async-mqtt": "^2.6.3", "fakegato-history": "^0.6.5", "homebridge-lib": "^7.0.9", - "node-switchbot": "^3.1.1", + "node-switchbot": "^3.2.1", "rxjs": "^7.8.1" }, "devDependencies": { - "@antfu/eslint-config": "^3.7.3", + "@antfu/eslint-config": "^3.8.0", "@types/aes-js": "^3.1.4", "@types/debug": "^4.1.12", "@types/fs-extra": "^11.0.4", "@types/mdast": "^4.0.4", - "@types/node": "^22.7.5", + "@types/node": "^22.7.8", "@types/semver": "^7.5.8", "@types/source-map-support": "^0.5.10", - "@vitest/coverage-v8": "^2.1.2", - "eslint": "^9.12.0", + "@vitest/coverage-v8": "^2.1.3", + "eslint": "^9.13.0", "eslint-plugin-format": "^0.1.2", "homebridge": "^1.8.4", - "homebridge-config-ui-x": "4.61.0", + "homebridge-config-ui-x": "4.62.0", "nodemon": "^3.1.7", - "npm-check-updates": "^17.1.3", + "npm-check-updates": "^17.1.4", "shx": "^0.3.4", "ts-node": "^10.9.2", - "typedoc": "^0.26.9", + "typedoc": "^0.26.10", "typescript": "^5.6.3", - "vitest": "^2.1.2" + "vitest": "^2.1.3" }, "directories": { "doc": "docs" diff --git a/src/device/bot.ts b/src/device/bot.ts index f5a47d35..03ff4f99 100644 --- a/src/device/bot.ts +++ b/src/device/bot.ts @@ -582,10 +582,10 @@ export class Bot extends deviceBase { parameter: 'default', commandType: 'command', } - this.debugLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)},`) + await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) - const deviceStatus: any = body + const deviceStatus: any = await body await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`) if (await this.successfulStatusCodes(deviceStatus)) { await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`) diff --git a/src/device/curtain.ts b/src/device/curtain.ts index 00b80f78..7c065978 100644 --- a/src/device/curtain.ts +++ b/src/device/curtain.ts @@ -504,7 +504,7 @@ export class Curtain extends deviceBase { await this.debugLog('openAPIRefreshStatus') try { const { body } = await this.deviceRefreshStatus() - const deviceStatus: any = await body + const deviceStatus: any = body await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`) if (await this.successfulStatusCodes(deviceStatus)) { await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`) diff --git a/src/device/meterpro.ts b/src/device/meterpro.ts new file mode 100644 index 00000000..0596a2fc --- /dev/null +++ b/src/device/meterpro.ts @@ -0,0 +1,417 @@ +/* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved. + * + * MeterPro.ts: @switchbot/homebridge-switchbot. + */ +import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge' +import type { device, meterProServiceData, meterProStatus, meterProWebhookContext } from 'node-switchbot' + +import type { SwitchBotPlatform } from '../platform.js' +import type { devicesConfig, meterConfig } from '../settings.js' + +import { Units } from 'homebridge' +/* +* For Testing Locally: +* import { SwitchBotBLEModel, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js'; +*/ +import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot' +import { interval, skipWhile, Subject } from 'rxjs' + +import { convertUnits, formatDeviceIdAsMac, validHumidity } from '../utils.js' +import { deviceBase } from './device.js' + +/** + * Platform Accessory + * An instance of this class is created for each accessory your platform registers + * Each accessory may expose multiple services of different service types. + */ +export class MeterPro extends deviceBase { + // Services + private Battery: { + Name: CharacteristicValue + Service: Service + BatteryLevel: CharacteristicValue + StatusLowBattery: CharacteristicValue + } + + private HumiditySensor?: { + Name: CharacteristicValue + Service: Service + CurrentRelativeHumidity: CharacteristicValue + } + + private TemperatureSensor?: { + Name: CharacteristicValue + Service: Service + CurrentTemperature: CharacteristicValue + } + + // OpenAPI + deviceStatus!: meterProStatus + + // Webhook + webhookContext!: meterProWebhookContext + + // BLE + serviceData!: meterProServiceData + + // Updates + meterUpdateInProgress!: boolean + doMeterUpdate: Subject + + constructor( + readonly platform: SwitchBotPlatform, + accessory: PlatformAccessory, + device: device & devicesConfig, + ) { + super(platform, accessory, device) + // Set category + accessory.category = this.hap.Categories.SENSOR + + // this is subject we use to track when we need to POST changes to the SwitchBot API + this.doMeterUpdate = new Subject() + this.meterUpdateInProgress = false + + // Initialize Battery Service + accessory.context.Battery = accessory.context.Battery ?? {} + this.Battery = { + Name: `${accessory.displayName} Battery`, + Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service, + BatteryLevel: accessory.context.BatteryLevel ?? 100, + StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL, + } + accessory.context.Battery = this.Battery as object + + // Initialize Battery Characteristics + this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name).setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE).getCharacteristic(this.hap.Characteristic.BatteryLevel).onGet(() => { + return this.Battery.BatteryLevel + }) + + this.Battery.Service.getCharacteristic(this.hap.Characteristic.StatusLowBattery).onGet(() => { + return this.Battery.StatusLowBattery + }) + + // Initialize Temperature Sensor Service + if ((device as meterConfig).hide_temperature) { + if (this.TemperatureSensor) { + this.debugLog('Removing Temperature Sensor Service') + this.TemperatureSensor.Service = this.accessory.getService(this.hap.Service.TemperatureSensor) as Service + accessory.removeService(this.TemperatureSensor.Service) + } + } else { + accessory.context.TemperatureSensor = accessory.context.TemperatureSensor ?? {} + this.TemperatureSensor = { + Name: `${accessory.displayName} Temperature Sensor`, + Service: accessory.getService(this.hap.Service.TemperatureSensor) ?? this.accessory.addService(this.hap.Service.TemperatureSensor) as Service, + CurrentTemperature: accessory.context.CurrentTemperature ?? 30, + } + accessory.context.TemperatureSensor = this.TemperatureSensor as object + + // Initialize Temperature Sensor Characteristics + this.TemperatureSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.TemperatureSensor.Name).getCharacteristic(this.hap.Characteristic.CurrentTemperature).setProps({ + unit: Units.CELSIUS, + validValueRanges: [-273.15, 100], + minValue: -273.15, + maxValue: 100, + minStep: 0.1, + }).onGet(() => { + return this.TemperatureSensor!.CurrentTemperature! + }) + } + // Initialize Humidity Sensor Service + if ((device as meterConfig).hide_humidity) { + if (this.HumiditySensor) { + this.debugLog('Removing Humidity Sensor Service') + this.HumiditySensor.Service = this.accessory.getService(this.hap.Service.HumiditySensor) as Service + accessory.removeService(this.HumiditySensor.Service) + } + } else { + accessory.context.HumiditySensor = accessory.context.HumiditySensor ?? {} + this.HumiditySensor = { + Name: `${accessory.displayName} Humidity Sensor`, + Service: accessory.getService(this.hap.Service.HumiditySensor) ?? this.accessory.addService(this.hap.Service.HumiditySensor) as Service, + CurrentRelativeHumidity: accessory.context.CurrentRelativeHumidity ?? 50, + } + accessory.context.HumiditySensor = this.HumiditySensor as object + + // Initialize Humidity Sensor Characteristics + this.HumiditySensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.HumiditySensor.Name).getCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity).setProps({ + minStep: 0.1, + }).onGet(() => { + return this.HumiditySensor!.CurrentRelativeHumidity! + }) + } + + // Retrieve initial values and updateHomekit + try { + this.debugLog('Retrieve initial values and update Homekit') + this.refreshStatus() + } catch (e: any) { + this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e.message ?? e}`) + } + + // regisiter webhook event handler if enabled + try { + this.debugLog('Registering Webhook Event Handler') + this.registerWebhook() + } catch (e: any) { + this.errorLog(`failed to registerWebhook, Error: ${e.message ?? e}`) + } + + // regisiter platform BLE event handler if enabled + try { + this.debugLog('Registering Platform BLE Event Handler') + this.registerPlatformBLE() + } catch (e: any) { + this.errorLog(`failed to registerPlatformBLE, Error: ${e.message ?? e}`) + } + + // Start an update interval + interval(this.deviceRefreshRate * 1000) + .pipe(skipWhile(() => this.meterUpdateInProgress)) + .subscribe(async () => { + await this.refreshStatus() + }) + } + + async BLEparseStatus(): Promise { + await this.debugLog('BLEparseStatus') + await this.debugLog(`(temperature, humidity) = BLE:(${this.serviceData.celsius}, ${this.serviceData.humidity}), current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity})`) + + // CurrentRelativeHumidity + if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) { + this.HumiditySensor.CurrentRelativeHumidity = validHumidity(this.serviceData.humidity, 0, 100) + await this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`) + } + // Current Temperature + if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) { + const CELSIUS = this.serviceData.celsius < 0 ? 0 : this.serviceData.celsius > 100 ? 100 : this.serviceData.celsius + this.TemperatureSensor.CurrentTemperature = CELSIUS + await this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`) + } + // BatteryLevel + this.Battery.BatteryLevel = this.serviceData.battery + await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`) + // StatusLowBattery + this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10 + ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW + : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL + await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`) + } + + async openAPIparseStatus(): Promise { + await this.debugLog('openAPIparseStatus') + await this.debugLog(`(temperature, humidity) = OpenAPI:(${this.deviceStatus.temperature}, ${this.deviceStatus.humidity}), current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity})`) + + // CurrentRelativeHumidity + if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) { + this.HumiditySensor.CurrentRelativeHumidity = this.deviceStatus.humidity + await this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`) + } + + // CurrentTemperature + if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) { + this.TemperatureSensor.CurrentTemperature = this.deviceStatus.temperature + await this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°c`) + } + + // BatteryLevel + this.Battery.BatteryLevel = this.deviceStatus.battery + await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`) + + // StatusLowBattery + this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10 + ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW + : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL + await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`) + + // FirmwareVersion + if (this.deviceStatus.version) { + const version = this.deviceStatus.version.toString() + this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`) + const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0' + this.accessory + .getService(this.hap.Service.AccessoryInformation)! + .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion) + .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion) + .getCharacteristic(this.hap.Characteristic.FirmwareRevision) + .updateValue(deviceVersion) + this.accessory.context.version = deviceVersion + this.debugSuccessLog(`v: ${this.accessory.context.version}`) + } + } + + async parseStatusWebhook(): Promise { + await this.debugLog('parseStatusWebhook') + await this.debugLog(`(scale, temperature, humidity) = Webhook:(${this.webhookContext.scale}, ${convertUnits(this.webhookContext.temperature, this.webhookContext.scale, (this.device as meterConfig).convertUnitTo)}, ${this.webhookContext.humidity}) current:(${this.TemperatureSensor?.CurrentTemperature}, ${this.HumiditySensor?.CurrentRelativeHumidity})`) + // Check if the scale is not CELSIUS + if (this.webhookContext.scale !== 'CELSIUS' && (this.device as meterConfig).convertUnitTo === undefined) { + await this.warnLog(`received a non-CELSIUS Webhook scale: ${this.webhookContext.scale}, Use the *convertUnitsTo* config under Hub settings, if displaying incorrectly in HomeKit.`) + } + + // CurrentRelativeHumidity + if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) { + this.HumiditySensor.CurrentRelativeHumidity = this.webhookContext.humidity + await this.debugLog(`CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}`) + } + + // CurrentTemperature + if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) { + this.TemperatureSensor.CurrentTemperature = convertUnits(this.webhookContext.temperature, this.webhookContext.scale, (this.device as meterConfig).convertUnitTo) + await this.debugLog(`CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}`) + } + } + + /** + * Asks the SwitchBot API for the latest device information + */ + async refreshStatus(): Promise { + if (!this.device.enableCloudService && this.OpenAPI) { + await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`) + } else if (this.BLE) { + await this.BLERefreshStatus() + } else if (this.OpenAPI && this.platform.config.credentials?.token) { + await this.openAPIRefreshStatus() + } else { + await this.offlineOff() + await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`) + } + } + + async BLERefreshStatus(): Promise { + await this.debugLog('BLERefreshStatus') + const switchBotBLE = await this.switchbotBLE() + if (switchBotBLE === undefined) { + await this.BLERefreshConnection(switchBotBLE) + } else { + // Start to monitor advertisement packets + (async () => { + // Start to monitor advertisement packets + const serviceData = await this.monitorAdvertisementPackets(switchBotBLE) as meterProServiceData + // Update HomeKit + if (serviceData.model === SwitchBotBLEModel.MeterPro && serviceData.modelName === SwitchBotBLEModelName.MeterPro) { + this.serviceData = serviceData + await this.BLEparseStatus() + await this.updateHomeKitCharacteristics() + } else { + await this.errorLog(`failed to get serviceData, serviceData: ${JSON.stringify(serviceData)}`) + await this.BLERefreshConnection(switchBotBLE) + } + })() + } + } + + async registerPlatformBLE(): Promise { + await this.debugLog('registerPlatformBLE') + if (this.config.options?.BLE) { + await this.debugLog('is listening to Platform BLE.') + try { + const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId) + this.device.bleMac = formattedDeviceId + await this.debugLog(`bleMac: ${this.device.bleMac}`) + this.platform.bleEventHandler[this.device.bleMac] = async (context: meterProServiceData) => { + try { + await this.debugLog(`received BLE: ${JSON.stringify(context)}`) + this.serviceData = context + await this.BLEparseStatus() + await this.updateHomeKitCharacteristics() + } catch (e: any) { + await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`) + } + } + } catch (error) { + await this.errorLog(`failed to format device ID as MAC, Error: ${error}`) + } + } else { + await this.debugLog('is not listening to Platform BLE') + } + } + + async openAPIRefreshStatus(): Promise { + await this.debugLog('openAPIRefreshStatus') + try { + const { body } = await this.deviceRefreshStatus() + const deviceStatus: any = await body + await this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`) + if (await this.successfulStatusCodes(deviceStatus)) { + await this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`) + this.deviceStatus = deviceStatus.body + await this.openAPIparseStatus() + await this.updateHomeKitCharacteristics() + } else { + await this.debugWarnLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`) + await this.debugWarnLog(deviceStatus) + } + } catch (e: any) { + await this.apiError(e) + await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`) + } + } + + async registerWebhook() { + if (this.device.webhook) { + await this.debugLog('is listening webhook.') + this.platform.webhookEventHandler[this.device.deviceId] = async (context: meterProWebhookContext) => { + try { + await this.debugLog(`received Webhook: ${JSON.stringify(context)}`) + this.webhookContext = context + await this.parseStatusWebhook() + await this.updateHomeKitCharacteristics() + } catch (e: any) { + await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`) + } + } + } else { + await this.debugLog('is not listening webhook.') + } + } + + /** + * Updates the status for each of the HomeKit Characteristics + */ + async updateHomeKitCharacteristics(): Promise { + // CurrentRelativeHumidity + if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) { + await this.updateCharacteristic(this.HumiditySensor.Service, this.hap.Characteristic.CurrentRelativeHumidity, this.HumiditySensor.CurrentRelativeHumidity, 'CurrentRelativeHumidity') + } + // CurrentTemperature + if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) { + await this.updateCharacteristic(this.TemperatureSensor.Service, this.hap.Characteristic.CurrentTemperature, this.TemperatureSensor.CurrentTemperature, 'CurrentTemperature') + } + // BatteryLevel + await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel, 'BatteryLevel') + // StatusLowBattery + await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery, 'StatusLowBattery') + } + + async BLERefreshConnection(switchbot: any): Promise { + await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') { + await this.warnLog('Using OpenAPI Connection to Refresh Status') + await this.openAPIRefreshStatus() + } + } + + async offlineOff(): Promise { + if (this.device.offline) { + if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) { + this.HumiditySensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, 50) + } + if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) { + this.TemperatureSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, 30) + } + this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, 100) + this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL) + } + } + + async apiError(e: any): Promise { + if (!(this.device as meterConfig).hide_humidity && this.HumiditySensor?.Service) { + this.HumiditySensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, e) + } + if (!(this.device as meterConfig).hide_temperature && this.TemperatureSensor?.Service) { + this.TemperatureSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, e) + } + this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e) + this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e) + } +} diff --git a/src/device/motion.ts b/src/device/motion.ts index ae8900da..06fcd560 100644 --- a/src/device/motion.ts +++ b/src/device/motion.ts @@ -120,9 +120,7 @@ export class Motion extends deviceBase { accessory.context.LightSensor = this.LightSensor as object // Initialize LightSensor Characteristics - this.LightSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name).setCharacteristic(this.hap.Characteristic.StatusActive, true).getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel).onGet(() => { - return this.LightSensor!.CurrentAmbientLightLevel - }) + this.LightSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name).setCharacteristic(this.hap.Characteristic.StatusActive, true) }; // Retrieve initial values and updateHomekit diff --git a/src/irdevice/airconditioner.ts b/src/irdevice/airconditioner.ts index 4eab629a..f4c0f440 100644 --- a/src/irdevice/airconditioner.ts +++ b/src/irdevice/airconditioner.ts @@ -314,7 +314,7 @@ export class AirConditioner extends irdeviceBase { async pushChanges(bodyChange: any): Promise { await this.debugLog('pushChanges') if (this.device.connectionType === 'OpenAPI' && !this.disablePushDetail) { - await this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/irdevice/airpurifier.ts b/src/irdevice/airpurifier.ts index a3f98d73..effda98e 100644 --- a/src/irdevice/airpurifier.ts +++ b/src/irdevice/airpurifier.ts @@ -211,7 +211,7 @@ export class AirPurifier extends irdeviceBase { async pushChanges(bodyChange: any): Promise { await this.debugLog('pushChanges') if (this.device.connectionType === 'OpenAPI') { - this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/irdevice/camera.ts b/src/irdevice/camera.ts index e42eee90..96882d06 100644 --- a/src/irdevice/camera.ts +++ b/src/irdevice/camera.ts @@ -98,7 +98,7 @@ export class Camera extends irdeviceBase { async pushChanges(bodyChange: any): Promise { await this.debugLog('pushChanges') if (this.device.connectionType === 'OpenAPI') { - this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/irdevice/fan.ts b/src/irdevice/fan.ts index 929fda97..ac761e15 100644 --- a/src/irdevice/fan.ts +++ b/src/irdevice/fan.ts @@ -189,7 +189,7 @@ export class IRFan extends irdeviceBase { async pushChanges(bodyChange: any): Promise { await this.debugLog('pushChanges') if (this.device.connectionType === 'OpenAPI') { - this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/irdevice/irdevice.ts b/src/irdevice/irdevice.ts index 4c4f2768..2a055fcc 100644 --- a/src/irdevice/irdevice.ts +++ b/src/irdevice/irdevice.ts @@ -175,7 +175,7 @@ export abstract class irdeviceBase { async successfulPushChange(deviceStatus: any, bodyChange: any) { this.debugSuccessLog(`deviceStatus StatusCode: ${deviceStatus.statusCode}`) - this.successLog(`request to SwitchBot API, body: ${JSON.stringify(JSON.parse(bodyChange))} sent successfully`) + this.successLog(`request to SwitchBot API, body: ${JSON.stringify(bodyChange)} sent successfully`) } async pushChangeError(e: Error) { diff --git a/src/irdevice/light.ts b/src/irdevice/light.ts index 29b7dc01..e0ba6614 100644 --- a/src/irdevice/light.ts +++ b/src/irdevice/light.ts @@ -196,7 +196,7 @@ export class Light extends irdeviceBase { async pushChanges(bodyChange: any, On: boolean): Promise { this.debugLog('pushChanges') if (this.device.connectionType === 'OpenAPI') { - this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/irdevice/other.ts b/src/irdevice/other.ts index 20898eb1..6ad69fbc 100644 --- a/src/irdevice/other.ts +++ b/src/irdevice/other.ts @@ -445,7 +445,7 @@ export class Others extends irdeviceBase { async pushChanges(bodyChange: any): Promise { await this.debugLog('pushChanges') if (this.device.connectionType === 'OpenAPI') { - this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/irdevice/tv.ts b/src/irdevice/tv.ts index ce4229da..d8737728 100644 --- a/src/irdevice/tv.ts +++ b/src/irdevice/tv.ts @@ -344,7 +344,7 @@ export class TV extends irdeviceBase { async pushTVChanges(bodyChange: any): Promise { await this.debugLog('pushTVChanges') if (this.device.connectionType === 'OpenAPI') { - await this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/irdevice/vacuumcleaner.ts b/src/irdevice/vacuumcleaner.ts index 4d5554c9..08ebbed8 100644 --- a/src/irdevice/vacuumcleaner.ts +++ b/src/irdevice/vacuumcleaner.ts @@ -95,7 +95,7 @@ export class VacuumCleaner extends irdeviceBase { async pushChanges(bodyChange: any): Promise { await this.debugLog('pushChanges') if (this.device.connectionType === 'OpenAPI') { - await this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/irdevice/waterheater.ts b/src/irdevice/waterheater.ts index fc1031b8..41469ac3 100644 --- a/src/irdevice/waterheater.ts +++ b/src/irdevice/waterheater.ts @@ -96,7 +96,7 @@ export class WaterHeater extends irdeviceBase { async pushChanges(bodyChange: any): Promise { await this.debugLog('pushChanges') if (this.device.connectionType === 'OpenAPI') { - this.infoLog(`Sending request to SwitchBot API, body: ${bodyChange},`) + await this.infoLog(`Sending request to SwitchBot API, body: ${JSON.stringify(bodyChange)}`) try { const { body } = await this.pushChangeRequest(bodyChange) const deviceStatus: any = await body diff --git a/src/platform.ts b/src/platform.ts index af75e68d..ee9fac31 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -39,6 +39,7 @@ import { StripLight } from './device/lightstrip.js' import { Lock } from './device/lock.js' import { Meter } from './device/meter.js' import { MeterPlus } from './device/meterplus.js' +import { MeterPro } from './device/meterpro.js' import { Motion } from './device/motion.js' import { Plug } from './device/plug.js' import { RobotVacuumCleaner } from './device/robotvacuumcleaner.js' @@ -630,6 +631,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin { 'Meter': this.createMeter.bind(this), 'MeterPlus': this.createMeterPlus.bind(this), 'Meter Plus (JP)': this.createMeterPlus.bind(this), + 'Meter Pro': this.createMeterPro.bind(this), 'WoIOSensor': this.createIOSensor.bind(this), 'Water Detector': this.createWaterDetector.bind(this), 'Motion Sensor': this.createMotion.bind(this), @@ -960,6 +962,69 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin { } } + private async createMeterPro(device: device & devicesConfig) { + const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`) + + // see if an accessory with the same uuid has already been registered and restored from + // the cached devices we stored in the `configureAccessory` method above + const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid) + + if (existingAccessory) { + // the accessory already exists + if (await this.registerDevice(device)) { + // console.log("existingAccessory", existingAccessory); + // if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.: + existingAccessory.context.device = device + existingAccessory.context.model = SwitchBotModel.MeterPro ?? SwitchBotModel.MeterProCO2 + existingAccessory.context.deviceId = device.deviceId + existingAccessory.context.deviceType = device.deviceType + existingAccessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName) + : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName) + existingAccessory.context.connectionType = await this.connectionType(device) + existingAccessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0' + this.infoLog(`Restoring existing accessory from cache: ${existingAccessory.displayName} deviceId: ${device.deviceId}`) + this.api.updatePlatformAccessories([existingAccessory]) + // create the accessory handler for the restored accessory + // this is imported from `platformAccessory.ts` + new MeterPro(this, existingAccessory, device) + await this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${existingAccessory.UUID})`) + } else { + this.unregisterPlatformAccessories(existingAccessory) + } + } else if (await this.registerDevice(device)) { + // create a new accessory + const accessory = new this.api.platformAccessory(device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName) + : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName), uuid) + + // store a copy of the device object in the `accessory.context` + // the `context` property can be used to store any data about the accessory you may need + accessory.context.device = device + accessory.context.model = SwitchBotModel.MeterPro ?? SwitchBotModel.MeterProCO2 + accessory.context.deviceId = device.deviceId + accessory.context.deviceType = device.deviceType + accessory.displayName = device.configDeviceName + ? await this.validateAndCleanDisplayName(device.configDeviceName, 'configDeviceName', device.configDeviceName) + : await this.validateAndCleanDisplayName(device.deviceName, 'deviceName', device.deviceName) + accessory.context.connectionType = await this.connectionType(device) + accessory.context.connectionType = await this.connectionType(device) + accessory.context.version = device.firmware ?? device.version ?? this.version ?? '0.0.0' + const newOrExternal = !device.external ? 'Adding new' : 'Loading external' + await this.infoLog(`${newOrExternal} accessory: ${accessory.displayName} deviceId: ${device.deviceId}`) + // create the accessory handler for the newly create accessory + // this is imported from `platformAccessory.ts` + new MeterPro(this, accessory, device) + await this.debugLog(`${device.deviceType} uuid: ${device.deviceId}-${device.deviceType}, (${accessory.UUID})`) + + // publish device externally or link the accessory to your platform + this.externalOrPlatform(device, accessory) + this.accessories.push(accessory) + } else { + await this.debugLog(`Device not registered: ${device.deviceName} ${device.deviceType} deviceId: ${device.deviceId}`) + } + } + private async createHub2(device: device & devicesConfig) { const uuid = this.api.hap.uuid.generate(`${device.deviceId}-${device.deviceType}`)