Add Home Assistant integration discovery

This commit is contained in:
jens committed 2026-08-10 09:28:42 +02:00
1 parent f2887a0ab4
commit 224e190fa1
11 files changed
+144 -22

No files matched your search

+5
View File
@@ -19,6 +19,11 @@ Voraussetzung ist Home Assistant OS.
5. Hinterlege im Tab **Konfiguration** Benutzername, Passwort und Site-ID.
6. Speichere die Konfiguration und starte die App.
Ab App-Version 0.2.0 meldet sich die App automatisch bei Home Assistant. Mit
der Custom Integration aus
`https://git.jensneuber.de/jens/ha-solaredge-optimizers` werden daraus Geräte
und Sensoren für Tagesenergie und aktuelle Leistung jedes Optimierers.
## SolarEdge Optimizer Data
Die App aktualisiert standardmäßig alle zehn Minuten und liefert für jedes
+2 -1
View File
@@ -4,6 +4,7 @@
"workspaces": {
"": {
"name": "solaredge-optimizers",
"version": "0.2.0",
},
"packages/solaredgeapi": {
"name": "@solar-dash/solaredgeapi",
@@ -19,7 +20,7 @@
},
"solaredge-optimizer-data": {
"name": "@solar-dash/solaredge-optimizer-app",
"version": "0.1.0",
"version": "0.2.0",
"dependencies": {
"@solar-dash/solaredgeapi": "workspace:*",
},
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "solaredge-optimizers",
"version": "0.1.0",
"version": "0.2.0",
"private": true,
"packageManager": "bun@1.3.14",
"workspaces": [
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## 0.2.0
- Register the internal optimizer API through Home Assistant Supervisor
discovery.
- Enable automatic setup of the SolarEdge Optimizers custom integration.
## 0.1.0
- Initial Home Assistant App package.
+13 -4
View File
@@ -83,9 +83,18 @@ im App-Panel erreichbar.
## Zugriff aus Home Assistant
Die App veröffentlicht standardmäßig keinen ungeschützten Port im lokalen
Netz. Home Assistant und andere Apps können sie über das interne App-Netzwerk
erreichen. Bei einer lokalen Installation lautet der Hostname typischerweise
`local-solaredge-optimizer-data`:
Netz. Ab Version 0.2.0 meldet sie ihren internen Host und Port automatisch über
die Supervisor-Diensterkennung. Dadurch kann die
[SolarEdge Optimizers Integration](https://git.jensneuber.de/jens/ha-solaredge-optimizers)
ohne manuelle interne URL eingerichtet werden.
Nach Installation und Start der App erscheint unter **Einstellungen → Geräte &
Dienste** die gefundene Integration **SolarEdge Optimizers**. Installiere die
Custom Integration vorher über HACS und bestätige anschließend den Fund.
Home Assistant und andere Apps können die API außerdem direkt über das interne
App-Netzwerk erreichen. Bei einer lokalen Installation lautet der Hostname
typischerweise `local-solaredge-optimizer-data`:
```text
http://local-solaredge-optimizer-data:8099/api/optimizers
@@ -119,7 +128,7 @@ für eine lokale Installation nach:
Lade anschließend den App Store neu, installiere **SolarEdge Optimizer Data**,
pflege Benutzername, Passwort und Site-ID im Tab **Konfiguration** und starte
die App. Der Supervisor lädt dabei das zur App-Version passende Multi-Arch-Image
`git.jensneuber.de/jens/solaredgeoptimizers:0.1.0`.
`git.jensneuber.de/jens/solaredgeoptimizers:0.2.0`.
## Sicherheit und Betrieb
+4 -1
View File
@@ -1,5 +1,5 @@
name: "SolarEdge Optimizer Data"
version: "0.1.0"
version: "0.2.0"
slug: "solaredge_optimizer_data"
description: >-
Cached daily energy and current power data for every SolarEdge optimizer.
@@ -7,6 +7,9 @@ arch:
- aarch64
- amd64
image: git.jensneuber.de/jens/solaredgeoptimizers
discovery:
- solaredge_optimizers
hassio_api: true
startup: application
boot: auto
init: false
+14 -14
View File
@@ -1,5 +1,5 @@
// @bun
var x=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Bo=import.meta.require;var $a=x((re,_a)=>{var Ko=/^xn--/,Ho=/[^\0-\x7F]/,Qo=/[\x2E\u3002\uFF0E\uFF61]/g,Wo={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},q=Math.floor,ia=String.fromCharCode;function F(a){throw RangeError(Wo[a])}function Yo(a,o){let i=[],s=a.length;while(s--)i[s]=o(a[s]);return i}function Oa(a,o){let i=a.split("@"),s="";if(i.length>1)s=i[0]+"@",a=i[1];a=a.replace(Qo,".");let e=a.split("."),n=Yo(e,o).join(".");return s+n}function Aa(a){let o=[],i=0,s=a.length;while(i<s){let e=a.charCodeAt(i++);if(e>=55296&&e<=56319&&i<s){let n=a.charCodeAt(i++);if((n&64512)==56320)o.push(((e&1023)<<10)+(n&1023)+65536);else o.push(e),i--}else o.push(e)}return o}var Mo=(a)=>String.fromCodePoint(...a),Xo=function(a){if(a>=48&&a<58)return 26+(a-48);if(a>=65&&a<91)return a-65;if(a>=97&&a<123)return a-97;return 36},Sa=function(a,o){return a+22+75*(a<26)-((o!=0)<<5)},Ia=function(a,o,i){let s=0;a=i?q(a/700):a>>1,a+=q(a/o);for(;a>455;s+=36)a=q(a/35);return q(s+36*a/(a+38))},Ra=function(a){let o=[],i=a.length,s=0,e=128,n=72,t=a.lastIndexOf("-");if(t<0)t=0;for(let m=0;m<t;++m){if(a.charCodeAt(m)>=128)F("not-basic");o.push(a.charCodeAt(m))}for(let m=t>0?t+1:0;m<i;){let u=s;for(let p=1,r=36;;r+=36){if(m>=i)F("invalid-input");let h=Xo(a.charCodeAt(m++));if(h>=36)F("invalid-input");if(h>q((2147483647-s)/p))F("overflow");s+=h*p;let b=r<=n?1:r>=n+26?26:r-n;if(h<b)break;let l=36-b;if(p>q(2147483647/l))F("overflow");p*=l}let c=o.length+1;if(n=Ia(s-u,c,u==0),q(s/c)>2147483647-e)F("overflow");e+=q(s/c),s%=c,o.splice(s++,0,e)}return String.fromCodePoint(...o)},qa=function(a){let o=[];a=Aa(a);let i=a.length,s=128,e=0,n=72;for(let u of a)if(u<128)o.push(ia(u));let t=o.length,m=t;if(t)o.push("-");while(m<i){let u=2147483647;for(let p of a)if(p>=s&&p<u)u=p;let c=m+1;if(u-s>q((2147483647-e)/c))F("overflow");e+=(u-s)*c,s=u;for(let p of a){if(p<s&&++e>2147483647)F("overflow");if(p===s){let r=e;for(let h=36;;h+=36){let b=h<=n?1:h>=n+26?26:h-n;if(r<b)break;let l=r-b,w=36-b;o.push(ia(Sa(b+l%w,0))),r=q(l/w)}o.push(ia(Sa(r,0))),n=Ia(e,c,m===t),e=0,++m}}++e,++s}return o.join("")},Vo=function(a){return Oa(a,function(o){return Ko.test(o)?Ra(o.slice(4).toLowerCase()):o})},Jo=function(a){return Oa(a,function(o){return Ho.test(o)?"xn--"+qa(o):o})},Po={version:"2.3.1",ucs2:{decode:Aa,encode:Mo},decode:Ra,encode:qa,toASCII:Jo,toUnicode:Vo};_a.exports=Po});var La=x((pe,Ta)=>{Ta.exports=function(o,i){if(i=i.split(":")[0],o=+o,!o)return!1;switch(i){case"http":case"ws":return o!==80;case"https":case"wss":return o!==443;case"ftp":return o!==21;case"gopher":return o!==70;case"file":return!1}return o!==0}});var Fa=x((ss)=>{var Uo=Object.prototype.hasOwnProperty,Co;function Da(a){try{return decodeURIComponent(a.replace(/\+/g," "))}catch(o){return null}}function Ga(a){try{return encodeURIComponent(a)}catch(o){return null}}function as(a){var o=/([^=?#&]+)=?([^&]*)/g,i={},s;while(s=o.exec(a)){var e=Da(s[1]),n=Da(s[2]);if(e===null||n===null||e in i)continue;i[e]=n}return i}function os(a,o){o=o||"";var i=[],s,e;if(typeof o!=="string")o="?";for(e in a)if(Uo.call(a,e)){if(s=a[e],!s&&(s===null||s===Co||isNaN(s)))s="";if(e=Ga(e),s=Ga(s),e===null||s===null)continue;i.push(e+"="+s)}return i.length?o+i.join("&"):""}ss.stringify=os;ss.parse=as});var Ya=x((ce,Wa)=>{var Za=La(),J=Fa(),ns=/^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/,Ba=/[\n\r\t]/g,ts=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,Ka=/:\d+$/,ms=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i,rs=/^[a-zA-Z]:/;function na(a){return(a?a:"").toString().replace(ns,"")}var ea=[["#","hash"],["?","query"],function(o,i){return _(i.protocol)?o.replace(/\\/g,"/"):o},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d*)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],Na={hash:1,query:1};function Ha(a){var o;if(typeof window<"u")o=window;else if(typeof global<"u")o=global;else if(typeof self<"u")o=self;else o={};var i=o.location||{};a=a||i;var s={},e=typeof a,n;if(a.protocol==="blob:")s=new $(unescape(a.pathname),{});else if(e==="string"){s=new $(a,{});for(n in Na)delete s[n]}else if(e==="object"){for(n in a){if(n in Na)continue;s[n]=a[n]}if(s.slashes===void 0)s.slashes=ts.test(a.href)}return s}function _(a){return a==="file:"||a==="ftp:"||a==="http:"||a==="https:"||a==="ws:"||a==="wss:"}function Qa(a,o){a=na(a),a=a.replace(Ba,""),o=o||{};var i=ms.exec(a),s=i[1]?i[1].toLowerCase():"",e=!!i[2],n=!!i[3],t=0,m;if(e)if(n)m=i[2]+i[3]+i[4],t=i[2].length+i[3].length;else m=i[2]+i[4],t=i[2].length;else if(n)m=i[3]+i[4],t=i[3].length;else m=i[4];if(s==="file:"){if(t>=2)m=m.slice(2)}else if(_(s))m=i[4];else if(s){if(e)m=m.slice(2)}else if(t>=2&&_(o.protocol))m=i[4];return{protocol:s,slashes:e||_(s),slashesCount:t,rest:m}}function ps(a,o){if(a==="")return o;var i=(o||"/").split("/").slice(0,-1).concat(a.split("/")),s=i.length,e=i[sLine truncated
var S=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Zo=import.meta.require;var Ta=S((ge,qa)=>{var Qo=/^xn--/,Wo=/[^\0-\x7F]/,Yo=/[\x2E\u3002\uFF0E\uFF61]/g,Mo={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},_=Math.floor,ia=String.fromCharCode;function F(a){throw RangeError(Mo[a])}function Xo(a,o){let i=[],s=a.length;while(s--)i[s]=o(a[s]);return i}function Oa(a,o){let i=a.split("@"),s="";if(i.length>1)s=i[0]+"@",a=i[1];a=a.replace(Yo,".");let e=a.split("."),n=Xo(e,o).join(".");return s+n}function Aa(a){let o=[],i=0,s=a.length;while(i<s){let e=a.charCodeAt(i++);if(e>=55296&&e<=56319&&i<s){let n=a.charCodeAt(i++);if((n&64512)==56320)o.push(((e&1023)<<10)+(n&1023)+65536);else o.push(e),i--}else o.push(e)}return o}var Vo=(a)=>String.fromCodePoint(...a),Po=function(a){if(a>=48&&a<58)return 26+(a-48);if(a>=65&&a<91)return a-65;if(a>=97&&a<123)return a-97;return 36},xa=function(a,o){return a+22+75*(a<26)-((o!=0)<<5)},Ia=function(a,o,i){let s=0;a=i?_(a/700):a>>1,a+=_(a/o);for(;a>455;s+=36)a=_(a/35);return _(s+36*a/(a+38))},Ra=function(a){let o=[],i=a.length,s=0,e=128,n=72,t=a.lastIndexOf("-");if(t<0)t=0;for(let m=0;m<t;++m){if(a.charCodeAt(m)>=128)F("not-basic");o.push(a.charCodeAt(m))}for(let m=t>0?t+1:0;m<i;){let u=s;for(let p=1,r=36;;r+=36){if(m>=i)F("invalid-input");let h=Po(a.charCodeAt(m++));if(h>=36)F("invalid-input");if(h>_((2147483647-s)/p))F("overflow");s+=h*p;let b=r<=n?1:r>=n+26?26:r-n;if(h<b)break;let l=36-b;if(p>_(2147483647/l))F("overflow");p*=l}let c=o.length+1;if(n=Ia(s-u,c,u==0),_(s/c)>2147483647-e)F("overflow");e+=_(s/c),s%=c,o.splice(s++,0,e)}return String.fromCodePoint(...o)},_a=function(a){let o=[];a=Aa(a);let i=a.length,s=128,e=0,n=72;for(let u of a)if(u<128)o.push(ia(u));let t=o.length,m=t;if(t)o.push("-");while(m<i){let u=2147483647;for(let p of a)if(p>=s&&p<u)u=p;let c=m+1;if(u-s>_((2147483647-e)/c))F("overflow");e+=(u-s)*c,s=u;for(let p of a){if(p<s&&++e>2147483647)F("overflow");if(p===s){let r=e;for(let h=36;;h+=36){let b=h<=n?1:h>=n+26?26:h-n;if(r<b)break;let l=r-b,w=36-b;o.push(ia(xa(b+l%w,0))),r=_(l/w)}o.push(ia(xa(r,0))),n=Ia(e,c,m===t),e=0,++m}}++e,++s}return o.join("")},Jo=function(a){return Oa(a,function(o){return Qo.test(o)?Ra(o.slice(4).toLowerCase()):o})},Uo=function(a){return Oa(a,function(o){return Wo.test(o)?"xn--"+_a(o):o})},Co={version:"2.3.1",ucs2:{decode:Aa,encode:Vo},decode:Ra,encode:_a,toASCII:Uo,toUnicode:Jo};qa.exports=Co});var La=S((ke,$a)=>{$a.exports=function(o,i){if(i=i.split(":")[0],o=+o,!o)return!1;switch(i){case"http":case"ws":return o!==80;case"https":case"wss":return o!==443;case"ftp":return o!==21;case"gopher":return o!==70;case"file":return!1}return o!==0}});var Fa=S((es)=>{var as=Object.prototype.hasOwnProperty,os;function Da(a){try{return decodeURIComponent(a.replace(/\+/g," "))}catch(o){return null}}function Ga(a){try{return encodeURIComponent(a)}catch(o){return null}}function ss(a){var o=/([^=?#&]+)=?([^&]*)/g,i={},s;while(s=o.exec(a)){var e=Da(s[1]),n=Da(s[2]);if(e===null||n===null||e in i)continue;i[e]=n}return i}function is(a,o){o=o||"";var i=[],s,e;if(typeof o!=="string")o="?";for(e in a)if(as.call(a,e)){if(s=a[e],!s&&(s===null||s===os||isNaN(s)))s="";if(e=Ga(e),s=Ga(s),e===null||s===null)continue;i.push(e+"="+s)}return i.length?o+i.join("&"):""}es.stringify=is;es.parse=ss});var Ya=S((he,Wa)=>{var Ha=La(),P=Fa(),ms=/^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/,Ba=/[\n\r\t]/g,rs=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,Ka=/:\d+$/,ps=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i,us=/^[a-zA-Z]:/;function na(a){return(a?a:"").toString().replace(ms,"")}var ea=[["#","hash"],["?","query"],function(o,i){return q(i.protocol)?o.replace(/\\/g,"/"):o},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d*)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],Na={hash:1,query:1};function Za(a){var o;if(typeof window<"u")o=window;else if(typeof global<"u")o=global;else if(typeof self<"u")o=self;else o={};var i=o.location||{};a=a||i;var s={},e=typeof a,n;if(a.protocol==="blob:")s=new T(unescape(a.pathname),{});else if(e==="string"){s=new T(a,{});for(n in Na)delete s[n]}else if(e==="object"){for(n in a){if(n in Na)continue;s[n]=a[n]}if(s.slashes===void 0)s.slashes=rs.test(a.href)}return s}function q(a){return a==="file:"||a==="ftp:"||a==="http:"||a==="https:"||a==="ws:"||a==="wss:"}function Qa(a,o){a=na(a),a=a.replace(Ba,""),o=o||{};var i=ps.exec(a),s=i[1]?i[1].toLowerCase():"",e=!!i[2],n=!!i[3],t=0,m;if(e)if(n)m=i[2]+i[3]+i[4],t=i[2].length+i[3].length;else m=i[2]+i[4],t=i[2].length;else if(n)m=i[3]+i[4],t=i[3].length;else m=i[4];if(s==="file:"){if(t>=2)m=m.slice(2)}else if(q(s))m=i[4];else if(s){if(e)m=m.slice(2)}else if(t>=2&&q(o.protocol))m=i[4];return{protocol:s,slashes:e||q(s),slashesCount:t,rest:m}}function cs(a,o){if(a==="")return o;var i=(o||"/").split("/").slice(0,-1).concat(a.split("/")),s=i.length,e=i[sLine truncated
* Copyright (c) 2018, Salesforce.com, Inc.
* All rights reserved.
*
@@ -28,7 +28,7 @@ var x=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Bo=import.meta
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/var xs=Ua(),Ca=["local","example","invalid","localhost","test"],Ss=["localhost","invalid"];function Os(a,o={}){let i=a.split("."),s=i[i.length-1],e=!!o.allowSpecialUseDomain,n=!!o.ignoreError;if(e&&Ca.includes(s)){if(i.length>1)return`${i[i.length-2]}.${s}`;else if(Ss.includes(s))return`${s}`}if(!n&&Ca.includes(s))throw Error(`Cookie has domain set to the public suffix "${s}" which is a special use domain. To allow this, configure your CookieJar with {allowSpecialUseDomain:true, rejectPublicSuffixes: false}.`);return xs.get(a)}As.getPublicSuffix=Os});var ra=x((Rs)=>{/*!
*/var Os=Ua(),Ca=["local","example","invalid","localhost","test"],As=["localhost","invalid"];function Is(a,o={}){let i=a.split("."),s=i[i.length-1],e=!!o.allowSpecialUseDomain,n=!!o.ignoreError;if(e&&Ca.includes(s)){if(i.length>1)return`${i[i.length-2]}.${s}`;else if(As.includes(s))return`${s}`}if(!n&&Ca.includes(s))throw Error(`Cookie has domain set to the public suffix "${s}" which is a special use domain. To allow this, configure your CookieJar with {allowSpecialUseDomain:true, rejectPublicSuffixes: false}.`);return Os.get(a)}Rs.getPublicSuffix=Is});var ra=S((qs)=>{/*!
* Copyright (c) 2015, Salesforce.com, Inc.
* All rights reserved.
*
@@ -57,7 +57,7 @@ var x=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Bo=import.meta
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/class ao{constructor(){this.synchronous=!1}findCookie(a,o,i,s){throw Error("findCookie is not implemented")}findCookies(a,o,i,s){throw Error("findCookies is not implemented")}putCookie(a,o){throw Error("putCookie is not implemented")}updateCookie(a,o,i){throw Error("updateCookie is not implemented")}removeCookie(a,o,i,s){throw Error("removeCookie is not implemented")}removeCookies(a,o,i){throw Error("removeCookies is not implemented")}removeAllCookies(a){throw Error("removeAllCookies is not implemented")}getAllCookies(a){throw Error("getAllCookies is not implemented (therefore jar cannot be serialized)")}}Rs.Store=ao});var pa=x((_s)=>{_s.fromCallback=function(a){return Object.defineProperty(function(){if(typeof arguments[arguments.length-1]==="function")a.apply(this,arguments);else return new Promise((o,i)=>{arguments[arguments.length]=(s,e)=>{if(s)return i(s);o(e)},arguments.length++,a.apply(this,arguments)})},"name",{value:a.name})};_s.fromPromise=function(a){return Object.defineProperty(function(){let o=arguments[arguments.length-1];if(typeof o!=="function")return a.apply(this,arguments);else delete arguments[arguments.length-1],arguments.length--,a.apply(this,arguments).then((i)=>o(null,i),o)},"name",{value:a.name})}});var ua=x((Gs)=>{/*!
*/class ao{constructor(){this.synchronous=!1}findCookie(a,o,i,s){throw Error("findCookie is not implemented")}findCookies(a,o,i,s){throw Error("findCookies is not implemented")}putCookie(a,o){throw Error("putCookie is not implemented")}updateCookie(a,o,i){throw Error("updateCookie is not implemented")}removeCookie(a,o,i,s){throw Error("removeCookie is not implemented")}removeCookies(a,o,i){throw Error("removeCookies is not implemented")}removeAllCookies(a){throw Error("removeAllCookies is not implemented")}getAllCookies(a){throw Error("getAllCookies is not implemented (therefore jar cannot be serialized)")}}qs.Store=ao});var pa=S(($s)=>{$s.fromCallback=function(a){return Object.defineProperty(function(){if(typeof arguments[arguments.length-1]==="function")a.apply(this,arguments);else return new Promise((o,i)=>{arguments[arguments.length]=(s,e)=>{if(s)return i(s);o(e)},arguments.length++,a.apply(this,arguments)})},"name",{value:a.name})};$s.fromPromise=function(a){return Object.defineProperty(function(){let o=arguments[arguments.length-1];if(typeof o!=="function")return a.apply(this,arguments);else delete arguments[arguments.length-1],arguments.length--,a.apply(this,arguments).then((i)=>o(null,i),o)},"name",{value:a.name})}});var ua=S((Ns)=>{/*!
* Copyright (c) 2015, Salesforce.com, Inc.
* All rights reserved.
*
@@ -86,7 +86,7 @@ var x=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Bo=import.meta
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/var Ls=ma();function Ds(a,o){let i=Ls.getPublicSuffix(a,{allowSpecialUseDomain:o});if(!i)return null;if(i==a)return[a];if(a.slice(-1)==".")a=a.slice(0,-1);let e=a.slice(0,-(i.length+1)).split(".").reverse(),n=i,t=[n];while(e.length)n=`${e.shift()}.${n}`,t.push(n);return t}Gs.permuteDomain=Ds});var ca=x((Zs)=>{/*!
*/var Gs=ma();function Fs(a,o){let i=Gs.getPublicSuffix(a,{allowSpecialUseDomain:o});if(!i)return null;if(i==a)return[a];if(a.slice(-1)==".")a=a.slice(0,-1);let e=a.slice(0,-(i.length+1)).split(".").reverse(),n=i,t=[n];while(e.length)n=`${e.shift()}.${n}`,t.push(n);return t}Ns.permuteDomain=Fs});var ca=S((Ks)=>{/*!
* Copyright (c) 2015, Salesforce.com, Inc.
* All rights reserved.
*
@@ -115,7 +115,7 @@ var x=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Bo=import.meta
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/function Ns(a,o){if(o===a)return!0;if(a.indexOf(o)===0){if(o.substr(-1)==="/")return!0;if(a.substr(o.length,1)==="/")return!0}return!1}Zs.pathMatch=Ns});var ga=x((Qs)=>{function oo(){try{return Bo("util")}catch(a){return null}}function Ks(){return Symbol.for("nodejs.util.inspect.custom")}function Hs(a){let i=(a.requireUtil||oo)();return i?i.inspect.custom:null}Qs.getUtilInspect=function(o,i={}){let e=(i.requireUtil||oo)();return function(t,m,u){return e?e.inspect(t,m,u):o(t)}};Qs.getCustomInspectSymbol=function(o={}){return(o.lookupCustomInspectSymbol||Ks)()||Hs(o)}});var io=x((oi)=>{/*!
*/function Bs(a,o){if(o===a)return!0;if(a.indexOf(o)===0){if(o.substr(-1)==="/")return!0;if(a.substr(o.length,1)==="/")return!0}return!1}Ks.pathMatch=Bs});var ga=S((Ys)=>{function oo(){try{return Zo("util")}catch(a){return null}}function Qs(){return Symbol.for("nodejs.util.inspect.custom")}function Ws(a){let i=(a.requireUtil||oo)();return i?i.inspect.custom:null}Ys.getUtilInspect=function(o,i={}){let e=(i.requireUtil||oo)();return function(t,m,u){return e?e.inspect(t,m,u):o(t)}};Ys.getCustomInspectSymbol=function(o={}){return(o.lookupCustomInspectSymbol||Qs)()||Ws(o)}});var io=S((ii)=>{/*!
* Copyright (c) 2015, Salesforce.com, Inc.
* All rights reserved.
*
@@ -144,13 +144,13 @@ var x=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Bo=import.meta
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/var{fromCallback:Ms}=pa(),Xs=ra().Store,Vs=ua().permuteDomain,Js=ca().pathMatch,{getCustomInspectSymbol:Ps,getUtilInspect:Us}=ga();class U extends Xs{constructor(){super();this.synchronous=!0,this.idx=Object.create(null);let a=Ps();if(a)this[a]=this.inspect}inspect(){return`{ idx: ${{inspect:Us(so)}.inspect(this.idx,!1,2)} }`}findCookie(a,o,i,s){if(!this.idx[a])return s(null,void 0);if(!this.idx[a][o])return s(null,void 0);return s(null,this.idx[a][o][i]||null)}findCookies(a,o,i,s){let e=[];if(typeof i==="function")s=i,i=!0;if(!a)return s(null,[]);let n;if(!o)n=function(c){for(let p in c){let r=c[p];for(let h in r)e.push(r[h])}};else n=function(c){Object.keys(c).forEach((p)=>{if(Js(o,p)){let r=c[p];for(let h in r)e.push(r[h])}})};let t=Vs(a,i)||[a],m=this.idx;t.forEach((u)=>{let c=m[u];if(!c)return;n(c)}),s(null,e)}putCookie(a,o){if(!this.idx[a.domain])this.idx[a.domain]=Object.create(null);if(!this.idx[a.domain][a.path])this.idx[a.domain][a.path]=Object.create(null);this.idx[a.domain][a.path][a.key]=a,o(null)}updateCookie(a,o,i){this.putCookie(o,i)}removeCookie(a,o,i,s){if(this.idx[a]&&this.idx[a][o]&&this.idx[a][o][i])delete this.idx[a][o][i];s(null)}removeCookies(a,o,i){if(this.idx[a])if(o)delete this.idx[a][o];else delete this.idx[a];return i(null)}removeAllCookies(a){return this.idx=Object.create(null),a(null)}getAllCookies(a){let o=[],i=this.idx;Object.keys(i).forEach((e)=>{Object.keys(i[e]).forEach((t)=>{Object.keys(i[e][t]).forEach((u)=>{if(u!==null)o.push(i[e][t][u])})})}),o.sort((e,n)=>{return(e.creationIndex||0)-(n.creationIndex||0)}),a(null,o)}}["findCookie","findCookies","putCookie","updateCookie","removeCookie","removeCookies","removeAllCookies","getAllCookies"].forEach((a)=>{U.prototype[a]=Ms(U.prototype[a])});oi.MemoryCookieStore=U;function so(a){let o=Object.keys(a);if(o.length===0)return"[Object: null prototype] {}";let i=`[Object: null prototype] {
`;return Object.keys(a).forEach((s,e)=>{if(i+=Cs(s,a[s]),e<o.length-1)i+=",";i+=`
`}),i+="}",i}function Cs(a,o){let s=` '${a}': [Object: null prototype] {
`;return Object.keys(o).forEach((e,n,t)=>{if(s+=ai(e,o[e]),n<t.length-1)s+=",";s+=`
`}),s+=" }",s}function ai(a,o){let s=` '${a}': [Object: null prototype] {
*/var{fromCallback:Vs}=pa(),Ps=ra().Store,Js=ua().permuteDomain,Us=ca().pathMatch,{getCustomInspectSymbol:Cs,getUtilInspect:ai}=ga();class U extends Ps{constructor(){super();this.synchronous=!0,this.idx=Object.create(null);let a=Cs();if(a)this[a]=this.inspect}inspect(){return`{ idx: ${{inspect:ai(so)}.inspect(this.idx,!1,2)} }`}findCookie(a,o,i,s){if(!this.idx[a])return s(null,void 0);if(!this.idx[a][o])return s(null,void 0);return s(null,this.idx[a][o][i]||null)}findCookies(a,o,i,s){let e=[];if(typeof i==="function")s=i,i=!0;if(!a)return s(null,[]);let n;if(!o)n=function(c){for(let p in c){let r=c[p];for(let h in r)e.push(r[h])}};else n=function(c){Object.keys(c).forEach((p)=>{if(Us(o,p)){let r=c[p];for(let h in r)e.push(r[h])}})};let t=Js(a,i)||[a],m=this.idx;t.forEach((u)=>{let c=m[u];if(!c)return;n(c)}),s(null,e)}putCookie(a,o){if(!this.idx[a.domain])this.idx[a.domain]=Object.create(null);if(!this.idx[a.domain][a.path])this.idx[a.domain][a.path]=Object.create(null);this.idx[a.domain][a.path][a.key]=a,o(null)}updateCookie(a,o,i){this.putCookie(o,i)}removeCookie(a,o,i,s){if(this.idx[a]&&this.idx[a][o]&&this.idx[a][o][i])delete this.idx[a][o][i];s(null)}removeCookies(a,o,i){if(this.idx[a])if(o)delete this.idx[a][o];else delete this.idx[a];return i(null)}removeAllCookies(a){return this.idx=Object.create(null),a(null)}getAllCookies(a){let o=[],i=this.idx;Object.keys(i).forEach((e)=>{Object.keys(i[e]).forEach((t)=>{Object.keys(i[e][t]).forEach((u)=>{if(u!==null)o.push(i[e][t][u])})})}),o.sort((e,n)=>{return(e.creationIndex||0)-(n.creationIndex||0)}),a(null,o)}}["findCookie","findCookies","putCookie","updateCookie","removeCookie","removeCookies","removeAllCookies","getAllCookies"].forEach((a)=>{U.prototype[a]=Vs(U.prototype[a])});ii.MemoryCookieStore=U;function so(a){let o=Object.keys(a);if(o.length===0)return"[Object: null prototype] {}";let i=`[Object: null prototype] {
`;return Object.keys(a).forEach((s,e)=>{if(i+=oi(s,a[s]),e<o.length-1)i+=",";i+=`
`}),i+="}",i}function oi(a,o){let s=` '${a}': [Object: null prototype] {
`;return Object.keys(o).forEach((e,n,t)=>{if(s+=si(e,o[e]),n<t.length-1)s+=",";s+=`
`}),s+=" }",s}function si(a,o){let s=` '${a}': [Object: null prototype] {
`;return Object.keys(o).forEach((e,n,t)=>{let m=o[e];if(s+=` ${e}: ${m.inspect()}`,n<t.length-1)s+=",";s+=`
`}),s+=" }",s}oi.inspectFallback=so});var ro=x((ui)=>{var ei=Object.prototype.toString;function eo(a){return typeof a==="function"}function no(a){return to(a)&&a!==""}function ni(a){return mo(a,Date)&&ri(a.getTime())}function ti(a){return a===""||a instanceof String&&a.toString()===""}function to(a){return typeof a==="string"||a instanceof String}function ka(a){return ei.call(a)==="[object Object]"}function mo(a,o){try{return a instanceof o}catch(i){return!1}}function mi(a){return no(a)||ka(a)&&"hostname"in a&&"pathname"in a&&"protocol"in a||mo(a,URL)}function ri(a){return typeof a==="number"&&a%1===0}function pi(a,o,i){if(!eo(o))i=o,o=null;if(!ka(i))i={Error:"Failed Check"};if(!a)if(o)o(new C(i));else throw new C(i)}class C extends Error{constructor(...a){super(...a)}}ui.ParameterError=C;ui.isFunction=eo;ui.isNonEmptyString=no;ui.isDate=ni;ui.isEmptyString=ti;ui.isString=to;ui.isObject=ka;ui.isUrlStringOrObject=mi;ui.validate=pi});var uo=x((fe,po)=>{po.exports="4.1.4"});/*!
`}),s+=" }",s}ii.inspectFallback=so});var ro=S((gi)=>{var ti=Object.prototype.toString;function eo(a){return typeof a==="function"}function no(a){return to(a)&&a!==""}function mi(a){return mo(a,Date)&&ui(a.getTime())}function ri(a){return a===""||a instanceof String&&a.toString()===""}function to(a){return typeof a==="string"||a instanceof String}function ka(a){return ti.call(a)==="[object Object]"}function mo(a,o){try{return a instanceof o}catch(i){return!1}}function pi(a){return no(a)||ka(a)&&"hostname"in a&&"pathname"in a&&"protocol"in a||mo(a,URL)}function ui(a){return typeof a==="number"&&a%1===0}function ci(a,o,i){if(!eo(o))i=o,o=null;if(!ka(i))i={Error:"Failed Check"};if(!a)if(o)o(new C(i));else throw new C(i)}class C extends Error{constructor(...a){super(...a)}}gi.ParameterError=C;gi.isFunction=eo;gi.isNonEmptyString=no;gi.isDate=mi;gi.isEmptyString=ri;gi.isString=to;gi.isObject=ka;gi.isUrlStringOrObject=pi;gi.validate=ci});var uo=S((Se,po)=>{po.exports="4.1.4"});/*!
* Copyright (c) 2015-2020, Salesforce.com, Inc.
* All rights reserved.
*
@@ -179,8 +179,8 @@ var x=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Bo=import.meta
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/var co=$a(),yi=Ya(),ha=ma(),fi=ra().Store,zi=io().MemoryCookieStore,vi=ca().pathMatch,k=ro(),Ei=uo(),{fromCallback:yo}=pa(),{getCustomInspectSymbol:xi}=ga(),Si=/^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/,go=/[\x00-\x1F]/,ko=[`
`,"\r","\x00"],Oi=/[\x20-\x3A\x3C-\x7E]+/,Ai=/[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/,Ii={jan:0,feb:1,mar:2,apr:3,may:4,jun:5,jul:6,aug:7,sep:8,oct:9,nov:10,dec:11};function lo(a){k.validate(k.isNonEmptyString(a),a);let o=String(a).toLowerCase();if(o==="none"||o==="lax"||o==="strict")return o;else return null}var H=Object.freeze({SILENT:"silent",STRICT:"strict",DISABLED:"unsafe-disabled"}),Ri=/(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-f\d]{1,4}:){7}(?:[a-f\d]{1,4}|:)|(?:[a-f\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-f\d]{1,4}|:)|(?:[a-f\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,2}|:)|(?:[a-f\d]{1,4}:){4}(?:(?::[a-f\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,3}|:)|(?:[a-f\d]{1,4}:){3}(?:(?::[a-f\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,4}|:)|(?:[a-f\d]{1,4}:){2}(?:(?::[a-f\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,5}|:)|(?:[a-f\d]{1,4}:){1}(?:(?::[a-f\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,6}|:)|(?::(?:(?::[a-f\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,7}|:)))$)/,qi=`
*/var co=Ta(),zi=Ya(),ha=ma(),vi=ra().Store,Ei=io().MemoryCookieStore,Si=ca().pathMatch,k=ro(),xi=uo(),{fromCallback:yo}=pa(),{getCustomInspectSymbol:Oi}=ga(),Ai=/^[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]+$/,go=/[\x00-\x1F]/,ko=[`
`,"\r","\x00"],Ii=/[\x20-\x3A\x3C-\x7E]+/,Ri=/[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/,_i={jan:0,feb:1,mar:2,apr:3,may:4,jun:5,jul:6,aug:7,sep:8,oct:9,nov:10,dec:11};function lo(a){k.validate(k.isNonEmptyString(a),a);let o=String(a).toLowerCase();if(o==="none"||o==="lax"||o==="strict")return o;else return null}var Q=Object.freeze({SILENT:"silent",STRICT:"strict",DISABLED:"unsafe-disabled"}),qi=/(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-f\d]{1,4}:){7}(?:[a-f\d]{1,4}|:)|(?:[a-f\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-f\d]{1,4}|:)|(?:[a-f\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,2}|:)|(?:[a-f\d]{1,4}:){4}(?:(?::[a-f\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,3}|:)|(?:[a-f\d]{1,4}:){3}(?:(?::[a-f\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,4}|:)|(?:[a-f\d]{1,4}:){2}(?:(?::[a-f\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,5}|:)|(?:[a-f\d]{1,4}:){1}(?:(?::[a-f\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,6}|:)|(?::(?:(?::[a-f\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,7}|:)))$)/,Ti=`
\\[?(?:
(?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|
(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|
@@ -191,4 +191,4 @@ var x=(a,o)=>()=>(o||a((o={exports:{}}).exports,o),o.exports);var Bo=import.meta
(?:[a-fA-F\\d]{1,4}:){1}(?:(?::[a-fA-F\\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,6}|:)|
(?::(?:(?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,7}|:))
)(?:%[0-9a-zA-Z]{1,})?\\]?
`.replace(/\s*\/\/.*$/gm,"").replace(/\n/g,"").trim(),fo=new RegExp(`^${qi}$`);function la(a,o,i,s){let e=0;while(e<a.length){let n=a.charCodeAt(e);if(n<=47||n>=58)break;e++}if(e<o||e>i)return null;if(!s&&e!=a.length)return null;return parseInt(a.substr(0,e),10)}function _i(a){let o=a.split(":"),i=[0,0,0];if(o.length!==3)return null;for(let s=0;s<3;s++){let e=s==2,n=la(o[s],1,2,e);if(n===null)return null;i[s]=n}return i}function $i(a){a=String(a).substr(0,3).toLowerCase();let o=Ii[a];return o>=0?o:null}function aa(a){if(!a)return;let o=a.split(Ai);if(!o)return;let i=null,s=null,e=null,n=null,t=null,m=null;for(let u=0;u<o.length;u++){let c=o[u].trim();if(!c.length)continue;let p;if(e===null){if(p=_i(c),p){i=p[0],s=p[1],e=p[2];continue}}if(n===null){if(p=la(c,1,2,!0),p!==null){n=p;continue}}if(t===null){if(p=$i(c),p!==null){t=p;continue}}if(m===null){if(p=la(c,2,4,!0),p!==null){if(m=p,m>=70&&m<=99)m+=1900;else if(m>=0&&m<=69)m+=2000}}}if(n===null||t===null||m===null||e===null||n<1||n>31||m<1601||i>23||s>59||e>59)return;return new Date(Date.UTC(m,t,n,i,s,e))}function Ti(a){return k.validate(k.isDate(a),a),a.toUTCString()}function M(a){if(a==null)return null;if(a=a.trim().replace(/^\./,""),fo.test(a))a=a.replace("[","").replace("]","");if(co&&/[^\u0001-\u007f]/.test(a))a=co.toASCII(a);return a.toLowerCase()}function ho(a,o,i){if(a==null||o==null)return null;if(i!==!1)a=M(a),o=M(o);if(a==o)return!0;let s=a.lastIndexOf(o);if(s<=0)return!1;if(a.length!==o.length+s)return!1;if(a.substr(s-1,1)!==".")return!1;if(Ri.test(a))return!1;return!0}function Li(a){if(!a||a.substr(0,1)!=="/")return"/";if(a==="/")return a;let o=a.lastIndexOf("/");if(o===0)return"/";return a.slice(0,o)}function Di(a){if(k.isEmptyString(a))return a;for(let o=0;o<ko.length;o++){let i=a.indexOf(ko[o]);if(i!==-1)a=a.substr(0,i)}return a}function Gi(a,o){a=Di(a),k.validate(k.isString(a),a);let i=a.indexOf("=");if(o){if(i===0)a=a.substr(1),i=a.indexOf("=")}else if(i<=0)return;let s,e;if(i<=0)s="",e=a.trim();else s=a.substr(0,i).trim(),e=a.substr(i+1).trim();if(go.test(s)||go.test(e))return;let n=new z;return n.key=s,n.value=e,n}function Fi(a,o){if(!o||typeof o!=="object")o={};if(k.isEmptyString(a)||!k.isString(a))return null;a=a.trim();let i=a.indexOf(";"),s=i===-1?a:a.substr(0,i),e=Gi(s,!!o.loose);if(!e)return;if(i===-1)return e;let n=a.slice(i+1).trim();if(n.length===0)return e;let t=n.split(";");while(t.length){let m=t.shift().trim();if(m.length===0)continue;let u=m.indexOf("="),c,p;if(u===-1)c=m,p=null;else c=m.substr(0,u),p=m.substr(u+1);if(c=c.trim().toLowerCase(),p)p=p.trim();switch(c){case"expires":if(p){let h=aa(p);if(h)e.expires=h}break;case"max-age":if(p){if(/^-?[0-9]+$/.test(p)){let h=parseInt(p,10);e.setMaxAge(h)}}break;case"domain":if(p){let h=p.trim().replace(/^\./,"");if(h)e.domain=h.toLowerCase()}break;case"path":e.path=p&&p[0]==="/"?p:null;break;case"secure":e.secure=!0;break;case"httponly":e.httpOnly=!0;break;case"samesite":switch(p?p.toLowerCase():""){case"strict":e.sameSite="strict";break;case"lax":e.sameSite="lax";break;case"none":e.sameSite="none";break;default:e.sameSite=void 0;break}break;default:e.extensions=e.extensions||[],e.extensions.push(m);break}}return e}function Ni(a){return k.validate(k.isObject(a),a),!a.key.startsWith("__Secure-")||a.secure}function Zi(a){return k.validate(k.isObject(a)),!a.key.startsWith("__Host-")||a.secure&&a.hostOnly&&a.path!=null&&a.path==="/"}function zo(a){let o;try{o=JSON.parse(a)}catch(i){return i}return o}function da(a){if(!a||k.isEmptyString(a))return null;let o;if(typeof a==="string"){if(o=zo(a),o instanceof Error)return null}else o=a;let i=new z;for(let s=0;s<z.serializableProperties.length;s++){let e=z.serializableProperties[s];if(o[e]===void 0||o[e]===Y[e])continue;if(e==="expires"||e==="creation"||e==="lastAccessed")if(o[e]===null)i[e]=null;else i[e]=o[e]=="Infinity"?"Infinity":new Date(o[e]);else i[e]=o[e]}return i}function jo(a,o){k.validate(k.isObject(a),a),k.validate(k.isObject(o),o);let i=0,s=a.path?a.path.length:0;if(i=(o.path?o.path.length:0)-s,i!==0)return i;let n=a.creation?a.creation.getTime():2147483647000,t=o.creation?o.creation.getTime():2147483647000;if(i=n-t,i!==0)return i;return i=a.creationIndex-o.creationIndex,i}function wo(a){if(a instanceof Object)return a;try{a=decodeURI(a)}catch(o){}return yi(a)}var Y={key:"",value:"",expires:"Infinity",maxAge:null,domain:null,path:null,secure:!1,httpOnly:!1,extensions:null,hostOnly:null,pathIsDefault:null,creation:null,lastAccessed:null,sameSite:void 0};class z{constructor(a={}){let o=xi();if(o)this[o]=this.inspect;Object.assign(this,Y,a),this.creation=this.creation||new Date,Object.defineProperty(this,"creationIndex",{configurable:!1,enumerable:!1,writable:!0,value:++z.cookiesCreated})}inspect(){let a=Date.now(),o=this.hostOnly!=null?this.hostOnly:"?",i=this.creation?`${a-this.creation.getTime()}ms`:"?",s=this.lastAccessed?`${a-this.lastAccessed.getTime()}ms`:"?";return`Cookie="${this.toString()}; hostOnly=${o}; aAge=${s}; cALine truncated
`.replace(/\s*\/\/.*$/gm,"").replace(/\n/g,"").trim(),fo=new RegExp(`^${Ti}$`);function la(a,o,i,s){let e=0;while(e<a.length){let n=a.charCodeAt(e);if(n<=47||n>=58)break;e++}if(e<o||e>i)return null;if(!s&&e!=a.length)return null;return parseInt(a.substr(0,e),10)}function $i(a){let o=a.split(":"),i=[0,0,0];if(o.length!==3)return null;for(let s=0;s<3;s++){let e=s==2,n=la(o[s],1,2,e);if(n===null)return null;i[s]=n}return i}function Li(a){a=String(a).substr(0,3).toLowerCase();let o=_i[a];return o>=0?o:null}function aa(a){if(!a)return;let o=a.split(Ri);if(!o)return;let i=null,s=null,e=null,n=null,t=null,m=null;for(let u=0;u<o.length;u++){let c=o[u].trim();if(!c.length)continue;let p;if(e===null){if(p=$i(c),p){i=p[0],s=p[1],e=p[2];continue}}if(n===null){if(p=la(c,1,2,!0),p!==null){n=p;continue}}if(t===null){if(p=Li(c),p!==null){t=p;continue}}if(m===null){if(p=la(c,2,4,!0),p!==null){if(m=p,m>=70&&m<=99)m+=1900;else if(m>=0&&m<=69)m+=2000}}}if(n===null||t===null||m===null||e===null||n<1||n>31||m<1601||i>23||s>59||e>59)return;return new Date(Date.UTC(m,t,n,i,s,e))}function Di(a){return k.validate(k.isDate(a),a),a.toUTCString()}function X(a){if(a==null)return null;if(a=a.trim().replace(/^\./,""),fo.test(a))a=a.replace("[","").replace("]","");if(co&&/[^\u0001-\u007f]/.test(a))a=co.toASCII(a);return a.toLowerCase()}function ho(a,o,i){if(a==null||o==null)return null;if(i!==!1)a=X(a),o=X(o);if(a==o)return!0;let s=a.lastIndexOf(o);if(s<=0)return!1;if(a.length!==o.length+s)return!1;if(a.substr(s-1,1)!==".")return!1;if(qi.test(a))return!1;return!0}function Gi(a){if(!a||a.substr(0,1)!=="/")return"/";if(a==="/")return a;let o=a.lastIndexOf("/");if(o===0)return"/";return a.slice(0,o)}function Fi(a){if(k.isEmptyString(a))return a;for(let o=0;o<ko.length;o++){let i=a.indexOf(ko[o]);if(i!==-1)a=a.substr(0,i)}return a}function Ni(a,o){a=Fi(a),k.validate(k.isString(a),a);let i=a.indexOf("=");if(o){if(i===0)a=a.substr(1),i=a.indexOf("=")}else if(i<=0)return;let s,e;if(i<=0)s="",e=a.trim();else s=a.substr(0,i).trim(),e=a.substr(i+1).trim();if(go.test(s)||go.test(e))return;let n=new z;return n.key=s,n.value=e,n}function Hi(a,o){if(!o||typeof o!=="object")o={};if(k.isEmptyString(a)||!k.isString(a))return null;a=a.trim();let i=a.indexOf(";"),s=i===-1?a:a.substr(0,i),e=Ni(s,!!o.loose);if(!e)return;if(i===-1)return e;let n=a.slice(i+1).trim();if(n.length===0)return e;let t=n.split(";");while(t.length){let m=t.shift().trim();if(m.length===0)continue;let u=m.indexOf("="),c,p;if(u===-1)c=m,p=null;else c=m.substr(0,u),p=m.substr(u+1);if(c=c.trim().toLowerCase(),p)p=p.trim();switch(c){case"expires":if(p){let h=aa(p);if(h)e.expires=h}break;case"max-age":if(p){if(/^-?[0-9]+$/.test(p)){let h=parseInt(p,10);e.setMaxAge(h)}}break;case"domain":if(p){let h=p.trim().replace(/^\./,"");if(h)e.domain=h.toLowerCase()}break;case"path":e.path=p&&p[0]==="/"?p:null;break;case"secure":e.secure=!0;break;case"httponly":e.httpOnly=!0;break;case"samesite":switch(p?p.toLowerCase():""){case"strict":e.sameSite="strict";break;case"lax":e.sameSite="lax";break;case"none":e.sameSite="none";break;default:e.sameSite=void 0;break}break;default:e.extensions=e.extensions||[],e.extensions.push(m);break}}return e}function Bi(a){return k.validate(k.isObject(a),a),!a.key.startsWith("__Secure-")||a.secure}function Ki(a){return k.validate(k.isObject(a)),!a.key.startsWith("__Host-")||a.secure&&a.hostOnly&&a.path!=null&&a.path==="/"}function zo(a){let o;try{o=JSON.parse(a)}catch(i){return i}return o}function da(a){if(!a||k.isEmptyString(a))return null;let o;if(typeof a==="string"){if(o=zo(a),o instanceof Error)return null}else o=a;let i=new z;for(let s=0;s<z.serializableProperties.length;s++){let e=z.serializableProperties[s];if(o[e]===void 0||o[e]===M[e])continue;if(e==="expires"||e==="creation"||e==="lastAccessed")if(o[e]===null)i[e]=null;else i[e]=o[e]=="Infinity"?"Infinity":new Date(o[e]);else i[e]=o[e]}return i}function jo(a,o){k.validate(k.isObject(a),a),k.validate(k.isObject(o),o);let i=0,s=a.path?a.path.length:0;if(i=(o.path?o.path.length:0)-s,i!==0)return i;let n=a.creation?a.creation.getTime():2147483647000,t=o.creation?o.creation.getTime():2147483647000;if(i=n-t,i!==0)return i;return i=a.creationIndex-o.creationIndex,i}function wo(a){if(a instanceof Object)return a;try{a=decodeURI(a)}catch(o){}return zi(a)}var M={key:"",value:"",expires:"Infinity",maxAge:null,domain:null,path:null,secure:!1,httpOnly:!1,extensions:null,hostOnly:null,pathIsDefault:null,creation:null,lastAccessed:null,sameSite:void 0};class z{constructor(a={}){let o=Oi();if(o)this[o]=this.inspect;Object.assign(this,M,a),this.creation=this.creation||new Date,Object.defineProperty(this,"creationIndex",{configurable:!1,enumerable:!1,writable:!0,value:++z.cookiesCreated})}inspect(){let a=Date.now(),o=this.hostOnly!=null?this.hostOnly:"?",i=this.creation?`${a-this.creation.getTime()}ms`:"?",s=this.lastAccessed?`${a-this.lastAccessed.getTime()}ms`:"?";return`Cookie="${this.toString()}; hostOnly=${o}; aAge=${s}; cALine truncated
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@solar-dash/solaredge-optimizer-app",
"version": "0.1.0",
"version": "0.2.0",
"private": true,
"type": "module",
"scripts": {
@@ -0,0 +1,48 @@
import { describe, expect, test } from "bun:test";
import { registerHomeAssistantDiscovery } from "./discovery";
describe("registerHomeAssistantDiscovery", () => {
test("registers the internal App endpoint with Supervisor", async () => {
let requestUrl: string | undefined;
let requestInit: RequestInit | undefined;
const fetchImpl = (async (
input: string | URL | Request,
init?: RequestInit,
) => {
requestUrl = String(input);
requestInit = init;
return Response.json({ result: "ok", data: { uuid: "test-uuid" } });
}) as typeof fetch;
await registerHomeAssistantDiscovery({
port: 8099,
host: "abc-solaredge-optimizer-data",
supervisorToken: "secret-token",
fetchImpl,
});
expect(requestUrl).toBe("http://supervisor/discovery");
expect(requestInit?.method).toBe("POST");
expect(requestInit?.headers).toEqual({
Accept: "application/json",
Authorization: "Bearer secret-token",
"Content-Type": "application/json",
});
expect(JSON.parse(String(requestInit?.body))).toEqual({
service: "solaredge_optimizers",
config: { host: "abc-solaredge-optimizer-data", port: 8099 },
});
});
test("does not start without a Supervisor token", async () => {
await expect(
registerHomeAssistantDiscovery({
port: 8099,
host: "abc-solaredge-optimizer-data",
supervisorToken: "",
}),
).rejects.toThrow("Supervisor token is unavailable");
});
});
+40
View File
@@ -0,0 +1,40 @@
import { hostname as systemHostname } from "node:os";
const DISCOVERY_SERVICE = "solaredge_optimizers";
const SUPERVISOR_DISCOVERY_URL = "http://supervisor/discovery";
export async function registerHomeAssistantDiscovery({
port,
host = process.env.HOSTNAME || systemHostname(),
supervisorToken = process.env.SUPERVISOR_TOKEN,
fetchImpl = fetch,
}: {
port: number;
host?: string;
supervisorToken?: string;
fetchImpl?: typeof fetch;
}): Promise<void> {
if (!host) {
throw new Error("App hostname is unavailable");
}
if (!supervisorToken) {
throw new Error("Supervisor token is unavailable");
}
const response = await fetchImpl(SUPERVISOR_DISCOVERY_URL, {
method: "POST",
headers: {
Accept: "application/json",
Authorization: `Bearer ${supervisorToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
service: DISCOVERY_SERVICE,
config: { host, port },
}),
});
if (!response.ok) {
throw new Error(`Supervisor discovery failed with HTTP ${response.status}`);
}
}
+10
View File
@@ -7,6 +7,7 @@ import {
readAppOptions,
resolveHomeAssistantTimeZone,
} from "./config";
import { registerHomeAssistantDiscovery } from "./discovery";
import { createRequestHandler } from "./http";
export async function main(): Promise<void> {
@@ -52,6 +53,15 @@ export async function main(): Promise<void> {
"info",
`Listening on port ${port}; refresh interval ${options.pollIntervalMinutes} minutes; time zone ${timeZone}`,
);
try {
await registerHomeAssistantDiscovery({ port });
log("info", "Registered optimizer API discovery with Home Assistant");
} catch (error) {
log(
"warning",
`Home Assistant discovery registration failed: ${formatStartupError(error)}`,
);
}
cache.start();
}