signalk-edge-link 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/delta-sanitizer.js +86 -0
- package/lib/instance.js +284 -8
- package/lib/metadata.js +467 -0
- package/lib/metrics.js +22 -1
- package/lib/packet.js +51 -14
- package/lib/pathDictionary.js +20 -1
- package/lib/pipeline-v2-client.js +177 -12
- package/lib/pipeline-v2-server.js +236 -2
- package/lib/pipeline.js +221 -1
- package/lib/prometheus.js +11 -0
- package/lib/routes/config-validation.js +49 -0
- package/lib/routes/metrics.js +1 -0
- package/lib/routes.js +25 -4
- package/package.json +1 -1
- package/public/{982.b207a377ed6542e2fb4a.js → 982.63949a2b2f6c5854e034.js} +2 -2
- package/public/982.63949a2b2f6c5854e034.js.map +1 -0
- package/public/index.html +1 -1
- package/public/main.0b6f5e3267731da945f0.js +2 -0
- package/public/main.0b6f5e3267731da945f0.js.map +1 -0
- package/public/main.js +467 -0
- package/public/remoteEntry.js +1 -1
- package/public/remoteEntry.js.map +1 -1
- package/public/982.b207a377ed6542e2fb4a.js.map +0 -1
- package/public/main.f1780db6593b0c07a48c.js +0 -2
- package/public/main.f1780db6593b0c07a48c.js.map +0 -1
package/public/remoteEntry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var signalk_edge_link;(()=>{"use strict";var e,r,t,n,a,o,i,l,u,s,f,d,c,p,h,v,g,m,b,y,k,w={805(e,r,t){var n={"./PluginConfigurationPanel":()=>Promise.all([t.e(277),t.e(982)]).then(()=>()=>t(4353))},a=(e,r)=>(t.R=r,r=t.o(n,e)?n[e]():Promise.resolve().then(()=>{throw new Error('Module "'+e+'" does not exist in container.')}),t.R=void 0,r),o=(e,r)=>{if(t.S){var n="default",a=t.S[n];if(a&&a!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[n]=e,t.I(n,r)}};t.d(r,{get:()=>a,init:()=>o})}},S={};function j(e){var r=S[e];if(void 0!==r)return r.exports;var t=S[e]={id:e,loaded:!1,exports:{}};return w[e](t,t.exports,j),t.loaded=!0,t.exports}j.m=w,j.c=S,j.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return j.d(r,{a:r}),r},j.d=(e,r)=>{for(var t in r)j.o(r,t)&&!j.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},j.f={},j.e=e=>Promise.all(Object.keys(j.f).reduce((r,t)=>(j.f[t](e,r),r),[])),j.u=e=>e+"."+{277:"99e19dcb5b778c964ace",540:"70a0bc6aadb412703390",982:"
|
|
1
|
+
var signalk_edge_link;(()=>{"use strict";var e,r,t,n,a,o,i,l,u,s,f,d,c,p,h,v,g,m,b,y,k,w={805(e,r,t){var n={"./PluginConfigurationPanel":()=>Promise.all([t.e(277),t.e(982)]).then(()=>()=>t(4353))},a=(e,r)=>(t.R=r,r=t.o(n,e)?n[e]():Promise.resolve().then(()=>{throw new Error('Module "'+e+'" does not exist in container.')}),t.R=void 0,r),o=(e,r)=>{if(t.S){var n="default",a=t.S[n];if(a&&a!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[n]=e,t.I(n,r)}};t.d(r,{get:()=>a,init:()=>o})}},S={};function j(e){var r=S[e];if(void 0!==r)return r.exports;var t=S[e]={id:e,loaded:!1,exports:{}};return w[e](t,t.exports,j),t.loaded=!0,t.exports}j.m=w,j.c=S,j.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return j.d(r,{a:r}),r},j.d=(e,r)=>{for(var t in r)j.o(r,t)&&!j.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},j.f={},j.e=e=>Promise.all(Object.keys(j.f).reduce((r,t)=>(j.f[t](e,r),r),[])),j.u=e=>e+"."+{277:"99e19dcb5b778c964ace",540:"70a0bc6aadb412703390",982:"63949a2b2f6c5854e034"}[e]+".js",j.miniCssF=e=>{},j.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),j.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},r="signalk-edge-link:",j.l=(t,n,a,o)=>{if(e[t])e[t].push(n);else{var i,l;if(void 0!==a)for(var u=document.getElementsByTagName("script"),s=0;s<u.length;s++){var f=u[s];if(f.getAttribute("src")==t||f.getAttribute("data-webpack")==r+a){i=f;break}}i||(l=!0,(i=document.createElement("script")).charset="utf-8",j.nc&&i.setAttribute("nonce",j.nc),i.setAttribute("data-webpack",r+a),i.src=t),e[t]=[n];var d=(r,n)=>{i.onerror=i.onload=null,clearTimeout(c);var a=e[t];if(delete e[t],i.parentNode&&i.parentNode.removeChild(i),a&&a.forEach(e=>e(n)),r)return r(n)},c=setTimeout(d.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=d.bind(null,i.onerror),i.onload=d.bind(null,i.onload),l&&document.head.appendChild(i)}},j.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},j.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{j.S={};var e={},r={};j.I=(t,n)=>{n||(n=[]);var a=r[t];if(a||(a=r[t]={}),!(n.indexOf(a)>=0)){if(n.push(a),e[t])return e[t];j.o(j.S,t)||(j.S[t]={});var o=j.S[t],i="signalk-edge-link",l=[];return"default"===t&&((e,r,t,n)=>{var a=o[e]=o[e]||{},l=a[r];(!l||!l.loaded&&(1!=!l.eager?n:i>l.from))&&(a[r]={get:()=>j.e(540).then(()=>()=>j(6540)),from:i,eager:!1})})("react","16.14.0"),e[t]=l.length?Promise.all(l).then(()=>e[t]=1):1}}})(),(()=>{var e;j.g.importScripts&&(e=j.g.location+"");var r=j.g.document;if(!e&&r&&(r.currentScript&&"SCRIPT"===r.currentScript.tagName.toUpperCase()&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),j.p=e})(),t=e=>{var r=e=>e.split(".").map(e=>+e==e?+e:e),t=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(e),n=t[1]?r(t[1]):[];return t[2]&&(n.length++,n.push.apply(n,r(t[2]))),t[3]&&(n.push([]),n.push.apply(n,r(t[3]))),n},n=(e,r)=>{e=t(e),r=t(r);for(var n=0;;){if(n>=e.length)return n<r.length&&"u"!=(typeof r[n])[0];var a=e[n],o=(typeof a)[0];if(n>=r.length)return"u"==o;var i=r[n],l=(typeof i)[0];if(o!=l)return"o"==o&&"n"==l||"s"==l||"u"==o;if("o"!=o&&"u"!=o&&a!=i)return a<i;n++}},a=e=>{var r=e[0],t="";if(1===e.length)return"*";if(r+.5){t+=0==r?">=":-1==r?"<":1==r?"^":2==r?"~":r>0?"=":"!=";for(var n=1,o=1;o<e.length;o++)n--,t+="u"==(typeof(l=e[o]))[0]?"-":(n>0?".":"")+(n=2,l);return t}var i=[];for(o=1;o<e.length;o++){var l=e[o];i.push(0===l?"not("+u()+")":1===l?"("+u()+" || "+u()+")":2===l?i.pop()+" "+i.pop():a(l))}return u();function u(){return i.pop().replace(/^\((.+)\)$/,"$1")}},o=(e,r)=>{if(0 in e){r=t(r);var n=e[0],a=n<0;a&&(n=-n-1);for(var i=0,l=1,u=!0;;l++,i++){var s,f,d=l<e.length?(typeof e[l])[0]:"";if(i>=r.length||"o"==(f=(typeof(s=r[i]))[0]))return!u||("u"==d?l>n&&!a:""==d!=a);if("u"==f){if(!u||"u"!=d)return!1}else if(u)if(d==f)if(l<=n){if(s!=e[l])return!1}else{if(a?s>e[l]:s<e[l])return!1;s!=e[l]&&(u=!1)}else if("s"!=d&&"n"!=d){if(a||l<=n)return!1;u=!1,l--}else{if(l<=n||f<d!=a)return!1;u=!1}else"s"!=d&&"n"!=d&&(u=!1,l--)}}var c=[],p=c.pop.bind(c);for(i=1;i<e.length;i++){var h=e[i];c.push(1==h?p()|p():2==h?p()&p():h?o(h,r):!p())}return!!p()},i=(e,r)=>e&&j.o(e,r),l=e=>(e.loaded=1,e.get()),u=e=>Object.keys(e).reduce((r,t)=>(e[t].eager&&(r[t]=e[t]),r),{}),s=(e,r,t)=>{var a=t?u(e[r]):e[r];return(r=Object.keys(a).reduce((e,r)=>!e||n(e,r)?r:e,0))&&a[r]},f=(e,r,t,a)=>{var i=a?u(e[r]):e[r];return(r=Object.keys(i).reduce((e,r)=>!o(t,r)||e&&!n(e,r)?e:r,0))&&i[r]},d=(e,r,t,n,o)=>{var i=e[t];return"No satisfying version ("+a(n)+")"+(o?" for eager consumption":"")+" of shared module "+t+" found in shared scope "+r+".\nAvailable versions: "+Object.keys(i).map(e=>e+" from "+i[e].from).join(", ")},c=e=>{throw new Error(e)},h=(e,r,t)=>t?t():((e,r)=>c("Shared module "+r+" doesn't exist in shared scope "+e))(e,r),v=(p=e=>function(r,t,n,a,o){var i=j.I(r);return i&&i.then&&!n?i.then(e.bind(e,r,j.S[r],t,!1,a,o)):e(r,j.S[r],t,n,a,o)})((e,r,t,n,a)=>i(r,t)?l(s(r,t,n)):h(e,t,a)),g=p((e,r,t,n,a,o)=>{if(!i(r,t))return h(e,t,o);var u=f(r,t,a,n);return u?l(u):o?o():void c(d(r,e,t,a,n))}),m={},b={4147:()=>g("default","react",!1,[1,16,13,1],()=>j.e(540).then(()=>()=>j(6540))),4167:()=>v("default","react",!1,()=>j.e(540).then(()=>()=>j(6540))),7920:()=>g("default","react",!1,[,[0,17],[1,16,14,0],1],()=>j.e(540).then(()=>()=>j(6540))),8271:()=>g("default","react",!1,[0,0,14,0],()=>j.e(540).then(()=>()=>j(6540)))},y={982:[4147,4167,7920,8271]},k={},j.f.consumes=(e,r)=>{j.o(y,e)&&y[e].forEach(e=>{if(j.o(m,e))return r.push(m[e]);if(!k[e]){var t=r=>{m[e]=0,j.m[e]=t=>{delete j.c[e],t.exports=r()}};k[e]=!0;var n=r=>{delete m[e],j.m[e]=t=>{throw delete j.c[e],r}};try{var a=b[e]();a.then?r.push(m[e]=a.then(t).catch(n)):t(a)}catch(e){n(e)}}})},(()=>{var e={981:0};j.f.j=(r,t)=>{var n=j.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else{var a=new Promise((t,a)=>n=e[r]=[t,a]);t.push(n[2]=a);var o=j.p+j.u(r),i=new Error;j.l(o,t=>{if(j.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var a=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+a+": "+o+")",i.name="ChunkLoadError",i.type=a,i.request=o,n[1](i)}},"chunk-"+r,r)}};var r=(r,t)=>{var n,a,[o,i,l]=t,u=0;if(o.some(r=>0!==e[r])){for(n in i)j.o(i,n)&&(j.m[n]=i[n]);l&&l(j)}for(r&&r(t);u<o.length;u++)a=o[u],j.o(e,a)&&e[a]&&e[a][0](),e[a]=0},t=self.webpackChunksignalk_edge_link=self.webpackChunksignalk_edge_link||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})();var P=j(805);signalk_edge_link=P})();
|
|
2
2
|
//# sourceMappingURL=remoteEntry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteEntry.js","mappings":"6CAAIA,EACAC,ECDAC,EAIAC,EAIAC,EAIAC,EAIAC,EAGAC,EAIAC,EAQAC,EAOAC,EAiBAC,EAOAC,EASAC,EAQAC,EAGAC,EAWAC,EA4BAC,EACAC,EAOAC,EAQAC,E,cCzIJ,IAAIC,EAAY,CACf,6BAA8B,IACtBC,QAAQC,IAAI,CAACC,EAAoBC,EAAE,KAAMD,EAAoBC,EAAE,OAAOC,KAAK,IAAM,IAASF,EAAoB,QAGnHjB,EAAM,CAACoB,EAAQC,KAClBJ,EAAoBK,EAAID,EACxBA,EACCJ,EAAoBM,EAAET,EAAWM,GAC9BN,EAAUM,KACVL,QAAQS,UAAUL,KAAK,KACxB,MAAM,IAAIM,MAAM,WAAaL,EAAS,oCAGzCH,EAAoBK,OAAII,EACjBL,GAEJf,EAAO,CAACqB,EAAYC,KACvB,GAAKX,EAAoBY,EAAzB,CACA,IAAIC,EAAO,UACPC,EAAWd,EAAoBY,EAAEC,GACrC,GAAGC,GAAYA,IAAaJ,EAAY,MAAM,IAAIF,MAAM,mGAExD,OADAR,EAAoBY,EAAEC,GAAQH,EACvBV,EAAoBe,EAAEF,EAAMF,EALD,GASnCX,EAAoBgB,EAAEC,EAAS,CAC9BlC,IAAK,IAAM,EACXM,KAAM,IAAM,G,GC5BT6B,EAA2B,CAAC,EAGhC,SAASlB,EAAoBmB,GAE5B,IAAIC,EAAeF,EAAyBC,GAC5C,QAAqBV,IAAjBW,EACH,OAAOA,EAAaH,QAGrB,IAAId,EAASe,EAAyBC,GAAY,CACjDE,GAAIF,EACJG,QAAQ,EACRL,QAAS,CAAC,GAUX,OANAM,EAAoBJ,GAAUhB,EAAQA,EAAOc,QAASjB,GAGtDG,EAAOmB,QAAS,EAGTnB,EAAOc,OACf,CAGAjB,EAAoBwB,EAAID,EAGxBvB,EAAoByB,EAAIP,EC9BxBlB,EAAoB0B,EAAKvB,IACxB,IAAIwB,EAASxB,GAAUA,EAAOyB,WAC7B,IAAOzB,EAAiB,QACxB,IAAM,EAEP,OADAH,EAAoBgB,EAAEW,EAAQ,CAAEE,EAAGF,IAC5BA,GCLR3B,EAAoBgB,EAAI,CAACC,EAASa,KACjC,IAAI,IAAIC,KAAOD,EACX9B,EAAoBM,EAAEwB,EAAYC,KAAS/B,EAAoBM,EAAEW,EAASc,IAC5EC,OAAOC,eAAehB,EAASc,EAAK,CAAEG,YAAY,EAAMnD,IAAK+C,EAAWC,MCJ3E/B,EAAoBmC,EAAI,CAAC,EAGzBnC,EAAoBC,EAAKmC,GACjBtC,QAAQC,IAAIiC,OAAOK,KAAKrC,EAAoBmC,GAAGG,OAAO,CAACC,EAAUR,KACvE/B,EAAoBmC,EAAEJ,GAAKK,EAASG,GAC7BA,GACL,KCNJvC,EAAoBwC,EAAKJ,GAEZA,EAAU,IAAM,CAAC,IAAM,uBAAuB,IAAM,uBAAuB,IAAM,wBAAwBA,GAAW,MCFjIpC,EAAoByC,SAAYL,MCDhCpC,EAAoB0C,EAAI,WACvB,GAA0B,iBAAfC,WAAyB,OAAOA,WAC3C,IACC,OAAOC,MAAQ,IAAIC,SAAS,cAAb,EAChB,CAAE,MAAO5C,GACR,GAAsB,iBAAX6C,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCAxB9C,EAAoBM,EAAI,CAACyC,EAAKC,IAAUhB,OAAOiB,UAAUC,eAAeC,KAAKJ,EAAKC,GVA9ExE,EAAa,CAAC,EACdC,EAAoB,qBAExBuB,EAAoBoD,EAAI,CAACC,EAAKC,EAAMvB,EAAKK,KACxC,GAAG5D,EAAW6E,GAAQ7E,EAAW6E,GAAKE,KAAKD,OAA3C,CACA,IAAIE,EAAQC,EACZ,QAAWhD,IAARsB,EAEF,IADA,IAAI2B,EAAUC,SAASC,qBAAqB,UACpCC,EAAI,EAAGA,EAAIH,EAAQI,OAAQD,IAAK,CACvC,IAAIE,EAAIL,EAAQG,GAChB,GAAGE,EAAEC,aAAa,QAAUX,GAAOU,EAAEC,aAAa,iBAAmBvF,EAAoBsD,EAAK,CAAEyB,EAASO,EAAG,KAAO,CACpH,CAEGP,IACHC,GAAa,GACbD,EAASG,SAASM,cAAc,WAEzBC,QAAU,QACblE,EAAoBmE,IACvBX,EAAOY,aAAa,QAASpE,EAAoBmE,IAElDX,EAAOY,aAAa,eAAgB3F,EAAoBsD,GAExDyB,EAAOa,IAAMhB,GAEd7E,EAAW6E,GAAO,CAACC,GACnB,IAAIgB,EAAmB,CAACC,EAAMC,KAE7BhB,EAAOiB,QAAUjB,EAAOkB,OAAS,KACjCC,aAAaC,GACb,IAAIC,EAAUrG,EAAW6E,GAIzB,UAHO7E,EAAW6E,GAClBG,EAAOsB,YAActB,EAAOsB,WAAWC,YAAYvB,GACnDqB,GAAWA,EAAQG,QAASC,GAAQA,EAAGT,IACpCD,EAAM,OAAOA,EAAKC,IAElBI,EAAUM,WAAWZ,EAAiBa,KAAK,UAAM1E,EAAW,CAAE2E,KAAM,UAAWC,OAAQ7B,IAAW,MACtGA,EAAOiB,QAAUH,EAAiBa,KAAK,KAAM3B,EAAOiB,SACpDjB,EAAOkB,OAASJ,EAAiBa,KAAK,KAAM3B,EAAOkB,QACnDjB,GAAcE,SAAS2B,KAAKC,YAAY/B,EAnCkB,GWH3DxD,EAAoBwF,EAAKvE,IACH,oBAAXwE,QAA0BA,OAAOC,aAC1C1D,OAAOC,eAAehB,EAASwE,OAAOC,YAAa,CAAEC,MAAO,WAE7D3D,OAAOC,eAAehB,EAAS,aAAc,CAAE0E,OAAO,KCLvD3F,EAAoB4F,IAAOzF,IAC1BA,EAAO0F,MAAQ,GACV1F,EAAO2F,WAAU3F,EAAO2F,SAAW,IACjC3F,G,MCHRH,EAAoBY,EAAI,CAAC,EACzB,IAAImF,EAAe,CAAC,EAChBC,EAAa,CAAC,EAClBhG,EAAoBe,EAAI,CAACF,EAAMF,KAC1BA,IAAWA,EAAY,IAE3B,IAAIsF,EAAYD,EAAWnF,GAE3B,GADIoF,IAAWA,EAAYD,EAAWnF,GAAQ,CAAC,KAC5CF,EAAUuF,QAAQD,IAAc,GAAnC,CAGA,GAFAtF,EAAU4C,KAAK0C,GAEZF,EAAalF,GAAO,OAAOkF,EAAalF,GAEvCb,EAAoBM,EAAEN,EAAoBY,EAAGC,KAAOb,EAAoBY,EAAEC,GAAQ,CAAC,GAEvF,IAAIsF,EAAQnG,EAAoBY,EAAEC,GAI9BuF,EAAa,oBAiBb7D,EAAW,GAOf,MALM,YADC1B,GAjBQ,EAACA,EAAMwF,EAASC,EAASC,KACvC,IAAIC,EAAWL,EAAMtF,GAAQsF,EAAMtF,IAAS,CAAC,EACzC4F,EAAgBD,EAASH,KACzBI,IAAmBA,EAAcnF,SAAW,IAAWmF,EAAcF,MAAQA,EAAQH,EAAaK,EAAcC,SAAQF,EAASH,GAAW,CAAEtH,IAgBpH,IAAOiB,EAAoBC,EAAE,KAAKC,KAAK,IAAM,IAAQF,EAAoB,OAhByD0G,KAAMN,EAAYG,OAAO,KAgBxLI,CAAS,QAAS,WAKbZ,EAAalF,GADhB0B,EAASuB,OACehE,QAAQC,IAAIwC,GAAUrC,KAAK,IAAO6F,EAAalF,GAAQ,GADlC,CAnCL,E,WCR7C,IAAI+F,EACA5G,EAAoB0C,EAAEmE,gBAAeD,EAAY5G,EAAoB0C,EAAEoE,SAAW,IACtF,IAAInD,EAAW3D,EAAoB0C,EAAEiB,SACrC,IAAKiD,GAAajD,IACbA,EAASoD,eAAkE,WAAjDpD,EAASoD,cAAcC,QAAQC,gBAC5DL,EAAYjD,EAASoD,cAAc1C,MAC/BuC,GAAW,CACf,IAAIlD,EAAUC,EAASC,qBAAqB,UAC5C,GAAGF,EAAQI,OAEV,IADA,IAAID,EAAIH,EAAQI,OAAS,EAClBD,GAAK,KAAO+C,IAAc,aAAaM,KAAKN,KAAaA,EAAYlD,EAAQG,KAAKQ,GAE3F,CAID,IAAKuC,EAAW,MAAM,IAAIpG,MAAM,yDAChCoG,EAAYA,EAAUO,QAAQ,SAAU,IAAIA,QAAQ,OAAQ,IAAIA,QAAQ,QAAS,IAAIA,QAAQ,YAAa,KAC1GnH,EAAoBoH,EAAIR,C,KblBpBlI,EAAgB2I,IAEnB,IAAID,EAAEA,GAAWA,EAAEE,MAAM,KAAKC,IAAIH,IAAWA,GAAGA,GAAGA,EAAEA,GAAK1F,EAAE,sCAAsC8F,KAAKH,GAAK7B,EAAE9D,EAAE,GAAG0F,EAAE1F,EAAE,IAAI,GAAG,OAAOA,EAAE,KAAK8D,EAAE1B,SAAS0B,EAAEjC,KAAKkE,MAAMjC,EAAE4B,EAAE1F,EAAE,MAAMA,EAAE,KAAK8D,EAAEjC,KAAK,IAAIiC,EAAEjC,KAAKkE,MAAMjC,EAAE4B,EAAE1F,EAAE,MAAM8D,GAExN7G,EAAY,CAACkD,EAAG6F,KAEnB7F,EAAEnD,EAAamD,GAAG6F,EAAEhJ,EAAagJ,GAAG,IAAI,IAAIlC,EAAE,IAAI,CAAC,GAAGA,GAAG3D,EAAEiC,OAAO,OAAO0B,EAAEkC,EAAE5D,QAAQ,aAAa4D,EAAElC,IAAI,GAAG,IAAIvF,EAAE4B,EAAE2D,GAAG9D,UAAUzB,GAAG,GAAG,GAAGuF,GAAGkC,EAAE5D,OAAO,MAAM,KAAKpC,EAAE,IAAIiG,EAAED,EAAElC,GAAGrD,UAAUwF,GAAG,GAAG,GAAGjG,GAAGS,EAAE,MAAM,KAAKT,GAAG,KAAKS,GAAI,KAAKA,GAAG,KAAKT,EAAG,GAAG,KAAKA,GAAG,KAAKA,GAAGzB,GAAG0H,EAAE,OAAO1H,EAAE0H,EAAEnC,GAAG,GAE/Q5G,EAAiBgJ,IAEpB,IAAIpC,EAAEoC,EAAM,GAAGlG,EAAE,GAAG,GAAG,IAAIkG,EAAM9D,OAAO,MAAM,IAAI,GAAG0B,EAAE,GAAG,CAAC9D,GAAG,GAAG8D,EAAE,MAAM,GAAGA,EAAE,IAAI,GAAGA,EAAE,IAAI,GAAGA,EAAE,IAAIA,EAAE,EAAE,IAAI,KAAK,IAAI,IAAIvF,EAAE,EAAE4B,EAAE,EAAEA,EAAE+F,EAAM9D,OAAOjC,IAAK5B,IAAIyB,GAAG,aAAaiG,EAAEC,EAAM/F,KAAK,GAAG,KAAK5B,EAAE,EAAE,IAAI,KAAKA,EAAE,EAAE0H,GAAG,OAAOjG,CAAC,CAAC,IAAIgB,EAAE,GAAG,IAAIb,EAAE,EAAEA,EAAE+F,EAAM9D,OAAOjC,IAAI,CAAC,IAAI8F,EAAEC,EAAM/F,GAAGa,EAAEa,KAAK,IAAIoE,EAAE,OAAOrH,IAAI,IAAI,IAAIqH,EAAE,IAAIrH,IAAI,OAAOA,IAAI,IAAI,IAAIqH,EAAEjF,EAAEmF,MAAM,IAAInF,EAAEmF,MAAMjJ,EAAc+I,GAAG,CAAC,OAAOrH,IAAI,SAASA,IAAI,OAAOoC,EAAEmF,MAAMV,QAAQ,aAAa,KAAK,GAElbtI,EAAU,CAAC+I,EAAOvB,KAErB,GAAG,KAAKuB,EAAM,CAACvB,EAAQ3H,EAAa2H,GAAS,IAAIpG,EAAE2H,EAAM,GAAGpC,EAAEvF,EAAE,EAAEuF,IAAIvF,GAAGA,EAAE,GAAG,IAAI,IAAIyB,EAAE,EAAEmC,EAAE,EAAEhC,GAAE,GAAIgC,IAAInC,IAAI,CAAC,IAAIS,EAAE4B,EAAErB,EAAEmB,EAAE+D,EAAM9D,eAAe8D,EAAM/D,IAAI,GAAG,GAAG,GAAGnC,GAAG2E,EAAQvC,QAAQ,MAAMC,UAAU5B,EAAEkE,EAAQ3E,KAAK,IAAI,OAAOG,IAAI,KAAKa,EAAEmB,EAAE5D,IAAIuF,EAAE,IAAI9C,GAAG8C,GAAG,GAAG,KAAKzB,GAAG,IAAIlC,GAAG,KAAKa,EAAE,OAAM,OAAQ,GAAGb,EAAE,GAAGa,GAAGqB,EAAE,GAAGF,GAAG5D,GAAG,GAAGkC,GAAGyF,EAAM/D,GAAG,OAAM,MAAO,CAAC,GAAG2B,EAAErD,EAAEyF,EAAM/D,GAAG1B,EAAEyF,EAAM/D,GAAG,OAAM,EAAG1B,GAAGyF,EAAM/D,KAAKhC,GAAE,EAAG,MAAM,GAAG,KAAKa,GAAG,KAAKA,EAAE,CAAC,GAAG8C,GAAG3B,GAAG5D,EAAE,OAAM,EAAG4B,GAAE,EAAGgC,GAAG,KAAK,CAAC,GAAGA,GAAG5D,GAAG8D,EAAErB,GAAG8C,EAAE,OAAM,EAAG3D,GAAE,CAAE,KAAK,KAAKa,GAAG,KAAKA,IAAIb,GAAE,EAAGgC,IAAI,CAAC,CAAC,IAAI8D,EAAE,GAAGrH,EAAEqH,EAAEE,IAAI1C,KAAKwC,GAAG,IAAIjG,EAAE,EAAEA,EAAEkG,EAAM9D,OAAOpC,IAAI,CAAC,IAAIc,EAAEoF,EAAMlG,GAAGiG,EAAEpE,KAAK,GAAGf,EAAElC,IAAIA,IAAI,GAAGkC,EAAElC,IAAIA,IAAIkC,EAAE3D,EAAQ2D,EAAE6D,IAAU/F,IAAI,CAAC,QAAQA,KAE1oBxB,EAAS,CAACqH,EAAOpE,IACboE,GAASnG,EAAoBM,EAAE6F,EAAOpE,GAE1ChD,EAAO+I,IACVA,EAAMxG,OAAS,EACRwG,EAAM/I,OAEVC,EAAawH,GACTxE,OAAOK,KAAKmE,GAAUlE,OAAO,CAACyF,EAAU1B,KACzCG,EAASH,GAASE,QACrBwB,EAAS1B,GAAWG,EAASH,IAEvB0B,GACN,CAAC,GAED9I,EAAoB,CAACkH,EAAOpE,EAAKwE,KACpC,IAAIC,EAAWD,EAAQvH,EAAUmH,EAAMpE,IAAQoE,EAAMpE,GAIrD,OAHIA,EAAMC,OAAOK,KAAKmE,GAAUlE,OAAO,CAACT,EAAG6F,KAClC7F,GAAKlD,EAAUkD,EAAG6F,GAAKA,EAAI7F,EACjC,KACW2E,EAASzE,IAEpB7C,EAAwB,CAACiH,EAAOpE,EAAKiG,EAAiBzB,KACzD,IAAIC,EAAWD,EAAQvH,EAAUmH,EAAMpE,IAAQoE,EAAMpE,GAKrD,OAJIA,EAAMC,OAAOK,KAAKmE,GAAUlE,OAAO,CAACT,EAAG6F,KACrC7I,EAAQmJ,EAAiBN,IACtB7F,IAAKlD,EAAUkD,EAAG6F,GADe7F,EACV6F,EAC7B,KACWlB,EAASzE,IAWpB5C,EAA2B,CAACgH,EAAO8B,EAAWlG,EAAKiG,EAAiBzB,KACvE,IAAIC,EAAWL,EAAMpE,GACrB,MAAO,0BAA4BnD,EAAcoJ,GAAmB,KAAOzB,EAAQ,yBAA2B,IAAM,qBAAuBxE,EAAM,0BAA4BkG,EAAtK,0BACmBjG,OAAOK,KAAKmE,GAAUe,IAAKxF,GAC7CA,EAAM,SAAWyE,EAASzE,GAAK2E,MACpCwB,KAAK,OAEL9I,EAAQ+I,IACX,MAAM,IAAI3H,MAAM2H,IAgBb7I,EAAc,CAAC2I,EAAWlG,EAAKqG,IAC3BA,EAAWA,IAfE,EAACH,EAAWlG,IACzB3C,EAAK,iBAAmB2C,EAAM,kCAAoCkG,GAc1CI,CAAeJ,EAAWlG,GAEtDxC,GAXAF,EAAQ4F,GAAO,SAAUgD,EAAWlG,EAAKwE,EAAO9E,EAAGT,GACtD,IAAIsH,EAAUtI,EAAoBe,EAAEkH,GACpC,OAAIK,GAAWA,EAAQpI,OAASqG,EACxB+B,EAAQpI,KAAK+E,EAAGE,KAAKF,EAAIgD,EAAWjI,EAAoBY,EAAEqH,GAAYlG,GAAK,EAAON,EAAGT,IAEtFiE,EAAGgD,EAAWjI,EAAoBY,EAAEqH,GAAYlG,EAAKwE,EAAO9E,EAAGT,EACtE,GAK6B,CAACiH,EAAW9B,EAAOpE,EAAKwE,EAAO6B,IACvDtJ,EAAOqH,EAAOpE,GACZhD,EAAIE,EAAkBkH,EAAOpE,EAAKwE,IADTjH,EAAY2I,EAAWlG,EAAKqG,IAUzD5I,EAAkCH,EAAK,CAAC4I,EAAW9B,EAAOpE,EAAKwE,EAAOyB,EAAiBI,KAC1F,IAAKtJ,EAAOqH,EAAOpE,GAAM,OAAOzC,EAAY2I,EAAWlG,EAAKqG,GAC5D,IAAIG,EAAoBrJ,EAAsBiH,EAAOpE,EAAKiG,EAAiBzB,GAC3E,OAAIgC,EAA0BxJ,EAAIwJ,GAC9BH,EAAiBA,SACrBhJ,EAAKD,EAAyBgH,EAAO8B,EAAWlG,EAAKiG,EAAiBzB,MAuBnE9G,EAAmB,CAAC,EACpBC,EAAyB,CAC5B,KAAM,IAAOF,EAAkB,UAAW,SAAS,EAAO,CAAC,EAAE,GAAG,GAAG,GAAI,IAAOQ,EAAoBC,EAAE,KAAKC,KAAK,IAAM,IAAQF,EAAoB,QAChJ,KAAM,IAAOT,EAAK,UAAW,SAAS,EAAO,IAAOS,EAAoBC,EAAE,KAAKC,KAAK,IAAM,IAAQF,EAAoB,QACtH,KAAM,IAAOR,EAAkB,UAAW,SAAS,EAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,GAAI,IAAOQ,EAAoBC,EAAE,KAAKC,KAAK,IAAM,IAAQF,EAAoB,QAC5J,KAAM,IAAOR,EAAkB,UAAW,SAAS,EAAO,CAAC,EAAE,EAAE,GAAG,GAAI,IAAOQ,EAAoBC,EAAE,KAAKC,KAAK,IAAM,IAAQF,EAAoB,SAG5IL,EAAe,CAClB,IAAO,CACN,KACA,KACA,KACA,OAGEC,EAAwB,CAAC,EAC7BI,EAAoBmC,EAAEqG,SAAW,CAACpG,EAASG,KACvCvC,EAAoBM,EAAEX,EAAcyC,IACtCzC,EAAayC,GAAS4C,QAAS3D,IAC9B,GAAGrB,EAAoBM,EAAEb,EAAkB4B,GAAK,OAAOkB,EAASgB,KAAK9D,EAAiB4B,IACtF,IAAIzB,EAAsByB,GAAK,CAC/B,IAAIoH,EAAanC,IAChB7G,EAAiB4B,GAAM,EACvBrB,EAAoBwB,EAAEH,GAAOlB,WACrBH,EAAoByB,EAAEJ,GAC7BlB,EAAOc,QAAUqF,MAGnB1G,EAAsByB,IAAM,EAC5B,IAAIqH,EAAWC,WACPlJ,EAAiB4B,GACxBrB,EAAoBwB,EAAEH,GAAOlB,IAE5B,aADOH,EAAoByB,EAAEJ,GACvBsH,IAGR,IACC,IAAIL,EAAU5I,EAAuB2B,KAClCiH,EAAQpI,KACVqC,EAASgB,KAAK9D,EAAiB4B,GAAMiH,EAAQpI,KAAKuI,GAAkB,MAAEC,IAChED,EAAUH,EAClB,CAAE,MAAMrI,GAAKyI,EAAQzI,EAAI,CACzB,K,Mc/JH,IAAI2I,EAAkB,CACrB,IAAK,GAGN5I,EAAoBmC,EAAE0G,EAAI,CAACzG,EAASG,KAElC,IAAIuG,EAAqB9I,EAAoBM,EAAEsI,EAAiBxG,GAAWwG,EAAgBxG,QAAW3B,EACtG,GAA0B,IAAvBqI,EAGF,GAAGA,EACFvG,EAASgB,KAAKuF,EAAmB,QAC3B,CAGL,IAAIR,EAAU,IAAIxI,QAAQ,CAACS,EAASwI,IAAYD,EAAqBF,EAAgBxG,GAAW,CAAC7B,EAASwI,IAC1GxG,EAASgB,KAAKuF,EAAmB,GAAKR,GAGtC,IAAIjF,EAAMrD,EAAoBoH,EAAIpH,EAAoBwC,EAAEJ,GAEpDuG,EAAQ,IAAInI,MAgBhBR,EAAoBoD,EAAEC,EAfFmB,IACnB,GAAGxE,EAAoBM,EAAEsI,EAAiBxG,KAEf,KAD1B0G,EAAqBF,EAAgBxG,MACRwG,EAAgBxG,QAAW3B,GACrDqI,GAAoB,CACtB,IAAIE,EAAYxE,IAAyB,SAAfA,EAAMY,KAAkB,UAAYZ,EAAMY,MAChE6D,EAAUzE,GAASA,EAAMa,QAAUb,EAAMa,OAAOhB,IACpDsE,EAAMO,QAAU,iBAAmB9G,EAAU,cAAgB4G,EAAY,KAAOC,EAAU,IAC1FN,EAAM9H,KAAO,iBACb8H,EAAMvD,KAAO4D,EACbL,EAAMQ,QAAUF,EAChBH,EAAmB,GAAGH,EACvB,GAGuC,SAAWvG,EAASA,EAE/D,GAeH,IAAIgH,EAAuB,CAACC,EAA4BC,KACvD,IAGInI,EAAUiB,GAHTmH,EAAUC,EAAaC,GAAWH,EAGhBzF,EAAI,EAC3B,GAAG0F,EAASG,KAAMrI,GAAgC,IAAxBuH,EAAgBvH,IAAa,CACtD,IAAIF,KAAYqI,EACZxJ,EAAoBM,EAAEkJ,EAAarI,KACrCnB,EAAoBwB,EAAEL,GAAYqI,EAAYrI,IAG7CsI,GAAsBA,EAAQzJ,EAClC,CAEA,IADGqJ,GAA4BA,EAA2BC,GACrDzF,EAAI0F,EAASzF,OAAQD,IACzBzB,EAAUmH,EAAS1F,GAChB7D,EAAoBM,EAAEsI,EAAiBxG,IAAYwG,EAAgBxG,IACrEwG,EAAgBxG,GAAS,KAE1BwG,EAAgBxG,GAAW,GAKzBuH,EAAqBC,KAAoC,8BAAIA,KAAoC,+BAAK,GAC1GD,EAAmB3E,QAAQoE,EAAqBjE,KAAK,KAAM,IAC3DwE,EAAmBpG,KAAO6F,EAAqBjE,KAAK,KAAMwE,EAAmBpG,KAAK4B,KAAKwE,G,KClFvF,IAAIE,EAAsB7J,EAAoB,K","sources":["webpack://signalk-edge-link/webpack/runtime/load script","webpack://signalk-edge-link/webpack/runtime/consumes","webpack://signalk-edge-link/webpack/container-entry","webpack://signalk-edge-link/webpack/bootstrap","webpack://signalk-edge-link/webpack/runtime/compat get default export","webpack://signalk-edge-link/webpack/runtime/define property getters","webpack://signalk-edge-link/webpack/runtime/ensure chunk","webpack://signalk-edge-link/webpack/runtime/get javascript chunk filename","webpack://signalk-edge-link/webpack/runtime/get mini-css chunk filename","webpack://signalk-edge-link/webpack/runtime/global","webpack://signalk-edge-link/webpack/runtime/hasOwnProperty shorthand","webpack://signalk-edge-link/webpack/runtime/make namespace object","webpack://signalk-edge-link/webpack/runtime/node module decorator","webpack://signalk-edge-link/webpack/runtime/sharing","webpack://signalk-edge-link/webpack/runtime/publicPath","webpack://signalk-edge-link/webpack/runtime/jsonp chunk loading","webpack://signalk-edge-link/webpack/startup"],"sourcesContent":["var inProgress = {};\nvar dataWebpackPrefix = \"signalk-edge-link:\";\n// loadScript function to load a script via script tag\n__webpack_require__.l = (url, done, key, chunkId) => {\n\tif(inProgress[url]) { inProgress[url].push(done); return; }\n\tvar script, needAttach;\n\tif(key !== undefined) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tfor(var i = 0; i < scripts.length; i++) {\n\t\t\tvar s = scripts[i];\n\t\t\tif(s.getAttribute(\"src\") == url || s.getAttribute(\"data-webpack\") == dataWebpackPrefix + key) { script = s; break; }\n\t\t}\n\t}\n\tif(!script) {\n\t\tneedAttach = true;\n\t\tscript = document.createElement('script');\n\n\t\tscript.charset = 'utf-8';\n\t\tif (__webpack_require__.nc) {\n\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n\t\t}\n\t\tscript.setAttribute(\"data-webpack\", dataWebpackPrefix + key);\n\n\t\tscript.src = url;\n\t}\n\tinProgress[url] = [done];\n\tvar onScriptComplete = (prev, event) => {\n\t\t// avoid mem leaks in IE.\n\t\tscript.onerror = script.onload = null;\n\t\tclearTimeout(timeout);\n\t\tvar doneFns = inProgress[url];\n\t\tdelete inProgress[url];\n\t\tscript.parentNode && script.parentNode.removeChild(script);\n\t\tdoneFns && doneFns.forEach((fn) => (fn(event)));\n\t\tif(prev) return prev(event);\n\t}\n\tvar timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);\n\tscript.onerror = onScriptComplete.bind(null, script.onerror);\n\tscript.onload = onScriptComplete.bind(null, script.onload);\n\tneedAttach && document.head.appendChild(script);\n};","var parseVersion = (str) => {\n\t// see webpack/lib/util/semver.js for original code\n\tvar p=p=>{return p.split(\".\").map(p=>{return+p==p?+p:p})},n=/^([^-+]+)?(?:-([^+]+))?(?:\\+(.+))?$/.exec(str),r=n[1]?p(n[1]):[];return n[2]&&(r.length++,r.push.apply(r,p(n[2]))),n[3]&&(r.push([]),r.push.apply(r,p(n[3]))),r;\n}\nvar versionLt = (a, b) => {\n\t// see webpack/lib/util/semver.js for original code\n\ta=parseVersion(a),b=parseVersion(b);for(var r=0;;){if(r>=a.length)return r<b.length&&\"u\"!=(typeof b[r])[0];var e=a[r],n=(typeof e)[0];if(r>=b.length)return\"u\"==n;var t=b[r],f=(typeof t)[0];if(n!=f)return\"o\"==n&&\"n\"==f||(\"s\"==f||\"u\"==n);if(\"o\"!=n&&\"u\"!=n&&e!=t)return e<t;r++}\n}\nvar rangeToString = (range) => {\n\t// see webpack/lib/util/semver.js for original code\n\tvar r=range[0],n=\"\";if(1===range.length)return\"*\";if(r+.5){n+=0==r?\">=\":-1==r?\"<\":1==r?\"^\":2==r?\"~\":r>0?\"=\":\"!=\";for(var e=1,a=1;a<range.length;a++){e--,n+=\"u\"==(typeof(t=range[a]))[0]?\"-\":(e>0?\".\":\"\")+(e=2,t)}return n}var g=[];for(a=1;a<range.length;a++){var t=range[a];g.push(0===t?\"not(\"+o()+\")\":1===t?\"(\"+o()+\" || \"+o()+\")\":2===t?g.pop()+\" \"+g.pop():rangeToString(t))}return o();function o(){return g.pop().replace(/^\\((.+)\\)$/,\"$1\")}\n}\nvar satisfy = (range, version) => {\n\t// see webpack/lib/util/semver.js for original code\n\tif(0 in range){version=parseVersion(version);var e=range[0],r=e<0;r&&(e=-e-1);for(var n=0,i=1,a=!0;;i++,n++){var f,s,g=i<range.length?(typeof range[i])[0]:\"\";if(n>=version.length||\"o\"==(s=(typeof(f=version[n]))[0]))return!a||(\"u\"==g?i>e&&!r:\"\"==g!=r);if(\"u\"==s){if(!a||\"u\"!=g)return!1}else if(a)if(g==s)if(i<=e){if(f!=range[i])return!1}else{if(r?f>range[i]:f<range[i])return!1;f!=range[i]&&(a=!1)}else if(\"s\"!=g&&\"n\"!=g){if(r||i<=e)return!1;a=!1,i--}else{if(i<=e||s<g!=r)return!1;a=!1}else\"s\"!=g&&\"n\"!=g&&(a=!1,i--)}}var t=[],o=t.pop.bind(t);for(n=1;n<range.length;n++){var u=range[n];t.push(1==u?o()|o():2==u?o()&o():u?satisfy(u,version):!o())}return!!o();\n}\nvar exists = (scope, key) => {\n\treturn scope && __webpack_require__.o(scope, key);\n}\nvar get = (entry) => {\n\tentry.loaded = 1;\n\treturn entry.get()\n};\nvar eagerOnly = (versions) => {\n\treturn Object.keys(versions).reduce((filtered, version) => {\n\t\t\tif (versions[version].eager) {\n\t\t\t\tfiltered[version] = versions[version];\n\t\t\t}\n\t\t\treturn filtered;\n\t}, {});\n};\nvar findLatestVersion = (scope, key, eager) => {\n\tvar versions = eager ? eagerOnly(scope[key]) : scope[key];\n\tvar key = Object.keys(versions).reduce((a, b) => {\n\t\treturn !a || versionLt(a, b) ? b : a;\n\t}, 0);\n\treturn key && versions[key];\n};\nvar findSatisfyingVersion = (scope, key, requiredVersion, eager) => {\n\tvar versions = eager ? eagerOnly(scope[key]) : scope[key];\n\tvar key = Object.keys(versions).reduce((a, b) => {\n\t\tif (!satisfy(requiredVersion, b)) return a;\n\t\treturn !a || versionLt(a, b) ? b : a;\n\t}, 0);\n\treturn key && versions[key]\n};\nvar findSingletonVersionKey = (scope, key, eager) => {\n\tvar versions = eager ? eagerOnly(scope[key]) : scope[key];\n\treturn Object.keys(versions).reduce((a, b) => {\n\t\treturn !a || (!versions[a].loaded && versionLt(a, b)) ? b : a;\n\t}, 0);\n};\nvar getInvalidSingletonVersionMessage = (scope, key, version, requiredVersion) => {\n\treturn \"Unsatisfied version \" + version + \" from \" + (version && scope[key][version].from) + \" of shared singleton module \" + key + \" (required \" + rangeToString(requiredVersion) + \")\"\n};\nvar getInvalidVersionMessage = (scope, scopeName, key, requiredVersion, eager) => {\n\tvar versions = scope[key];\n\treturn \"No satisfying version (\" + rangeToString(requiredVersion) + \")\" + (eager ? \" for eager consumption\" : \"\") + \" of shared module \" + key + \" found in shared scope \" + scopeName + \".\\n\" +\n\t\t\"Available versions: \" + Object.keys(versions).map((key) => {\n\t\treturn key + \" from \" + versions[key].from;\n\t}).join(\", \");\n};\nvar fail = (msg) => {\n\tthrow new Error(msg);\n}\nvar failAsNotExist = (scopeName, key) => {\n\treturn fail(\"Shared module \" + key + \" doesn't exist in shared scope \" + scopeName);\n}\nvar warn = /*#__PURE__*/ (msg) => {\n\tif (typeof console !== \"undefined\" && console.warn) console.warn(msg);\n};\nvar init = (fn) => (function(scopeName, key, eager, c, d) {\n\tvar promise = __webpack_require__.I(scopeName);\n\tif (promise && promise.then && !eager) {\n\t\treturn promise.then(fn.bind(fn, scopeName, __webpack_require__.S[scopeName], key, false, c, d));\n\t}\n\treturn fn(scopeName, __webpack_require__.S[scopeName], key, eager, c, d);\n});\n\nvar useFallback = (scopeName, key, fallback) => {\n\treturn fallback ? fallback() : failAsNotExist(scopeName, key);\n}\nvar load = /*#__PURE__*/ init((scopeName, scope, key, eager, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\treturn get(findLatestVersion(scope, key, eager));\n});\nvar loadVersion = /*#__PURE__*/ init((scopeName, scope, key, eager, requiredVersion, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar satisfyingVersion = findSatisfyingVersion(scope, key, requiredVersion, eager);\n\tif (satisfyingVersion) return get(satisfyingVersion);\n\twarn(getInvalidVersionMessage(scope, scopeName, key, requiredVersion, eager))\n\treturn get(findLatestVersion(scope, key, eager));\n});\nvar loadStrictVersion = /*#__PURE__*/ init((scopeName, scope, key, eager, requiredVersion, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar satisfyingVersion = findSatisfyingVersion(scope, key, requiredVersion, eager);\n\tif (satisfyingVersion) return get(satisfyingVersion);\n\tif (fallback) return fallback();\n\tfail(getInvalidVersionMessage(scope, scopeName, key, requiredVersion, eager));\n});\nvar loadSingleton = /*#__PURE__*/ init((scopeName, scope, key, eager, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar version = findSingletonVersionKey(scope, key, eager);\n\treturn get(scope[key][version]);\n});\nvar loadSingletonVersion = /*#__PURE__*/ init((scopeName, scope, key, eager, requiredVersion, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar version = findSingletonVersionKey(scope, key, eager);\n\tif (!satisfy(requiredVersion, version)) {\n\t\twarn(getInvalidSingletonVersionMessage(scope, key, version, requiredVersion));\n\t}\n\treturn get(scope[key][version]);\n});\nvar loadStrictSingletonVersion = /*#__PURE__*/ init((scopeName, scope, key, eager, requiredVersion, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar version = findSingletonVersionKey(scope, key, eager);\n\tif (!satisfy(requiredVersion, version)) {\n\t\tfail(getInvalidSingletonVersionMessage(scope, key, version, requiredVersion));\n\t}\n\treturn get(scope[key][version]);\n});\nvar installedModules = {};\nvar moduleToHandlerMapping = {\n\t4147: () => (loadStrictVersion(\"default\", \"react\", false, [1,16,13,1], () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540))))))),\n\t4167: () => (load(\"default\", \"react\", false, () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540))))))),\n\t7920: () => (loadStrictVersion(\"default\", \"react\", false, [,[0,17],[1,16,14,0],1], () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540))))))),\n\t8271: () => (loadStrictVersion(\"default\", \"react\", false, [0,0,14,0], () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540)))))))\n};\n// no consumes in initial chunks\nvar chunkMapping = {\n\t\"982\": [\n\t\t4147,\n\t\t4167,\n\t\t7920,\n\t\t8271\n\t]\n};\nvar startedInstallModules = {};\n__webpack_require__.f.consumes = (chunkId, promises) => {\n\tif(__webpack_require__.o(chunkMapping, chunkId)) {\n\t\tchunkMapping[chunkId].forEach((id) => {\n\t\t\tif(__webpack_require__.o(installedModules, id)) return promises.push(installedModules[id]);\n\t\t\tif(!startedInstallModules[id]) {\n\t\t\tvar onFactory = (factory) => {\n\t\t\t\tinstalledModules[id] = 0;\n\t\t\t\t__webpack_require__.m[id] = (module) => {\n\t\t\t\t\tdelete __webpack_require__.c[id];\n\t\t\t\t\tmodule.exports = factory();\n\t\t\t\t}\n\t\t\t};\n\t\t\tstartedInstallModules[id] = true;\n\t\t\tvar onError = (error) => {\n\t\t\t\tdelete installedModules[id];\n\t\t\t\t__webpack_require__.m[id] = (module) => {\n\t\t\t\t\tdelete __webpack_require__.c[id];\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tvar promise = moduleToHandlerMapping[id]();\n\t\t\t\tif(promise.then) {\n\t\t\t\t\tpromises.push(installedModules[id] = promise.then(onFactory)['catch'](onError));\n\t\t\t\t} else onFactory(promise);\n\t\t\t} catch(e) { onError(e); }\n\t\t\t}\n\t\t});\n\t}\n}","var moduleMap = {\n\t\"./PluginConfigurationPanel\": () => {\n\t\treturn Promise.all([__webpack_require__.e(277), __webpack_require__.e(982)]).then(() => (() => ((__webpack_require__(4353)))));\n\t}\n};\nvar get = (module, getScope) => {\n\t__webpack_require__.R = getScope;\n\tgetScope = (\n\t\t__webpack_require__.o(moduleMap, module)\n\t\t\t? moduleMap[module]()\n\t\t\t: Promise.resolve().then(() => {\n\t\t\t\tthrow new Error('Module \"' + module + '\" does not exist in container.');\n\t\t\t})\n\t);\n\t__webpack_require__.R = undefined;\n\treturn getScope;\n};\nvar init = (shareScope, initScope) => {\n\tif (!__webpack_require__.S) return;\n\tvar name = \"default\"\n\tvar oldScope = __webpack_require__.S[name];\n\tif(oldScope && oldScope !== shareScope) throw new Error(\"Container initialization failed as it has already been initialized with a different share scope\");\n\t__webpack_require__.S[name] = shareScope;\n\treturn __webpack_require__.I(name, initScope);\n};\n\n// This exports getters to disallow modifications\n__webpack_require__.d(exports, {\n\tget: () => (get),\n\tinit: () => (init)\n});","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n// expose the module cache\n__webpack_require__.c = __webpack_module_cache__;\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.f = {};\n// This file contains only the entry chunk.\n// The chunk loading function for additional chunks\n__webpack_require__.e = (chunkId) => {\n\treturn Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {\n\t\t__webpack_require__.f[key](chunkId, promises);\n\t\treturn promises;\n\t}, []));\n};","// This function allow to reference async chunks\n__webpack_require__.u = (chunkId) => {\n\t// return url for filenames based on template\n\treturn \"\" + chunkId + \".\" + {\"277\":\"99e19dcb5b778c964ace\",\"540\":\"70a0bc6aadb412703390\",\"982\":\"b207a377ed6542e2fb4a\"}[chunkId] + \".js\";\n};","// This function allow to reference async chunks\n__webpack_require__.miniCssF = (chunkId) => {\n\t// return url for filenames based on template\n\treturn undefined;\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.S = {};\nvar initPromises = {};\nvar initTokens = {};\n__webpack_require__.I = (name, initScope) => {\n\tif(!initScope) initScope = [];\n\t// handling circular init calls\n\tvar initToken = initTokens[name];\n\tif(!initToken) initToken = initTokens[name] = {};\n\tif(initScope.indexOf(initToken) >= 0) return;\n\tinitScope.push(initToken);\n\t// only runs once\n\tif(initPromises[name]) return initPromises[name];\n\t// creates a new share scope if needed\n\tif(!__webpack_require__.o(__webpack_require__.S, name)) __webpack_require__.S[name] = {};\n\t// runs all init snippets from all modules reachable\n\tvar scope = __webpack_require__.S[name];\n\tvar warn = (msg) => {\n\t\tif (typeof console !== \"undefined\" && console.warn) console.warn(msg);\n\t};\n\tvar uniqueName = \"signalk-edge-link\";\n\tvar register = (name, version, factory, eager) => {\n\t\tvar versions = scope[name] = scope[name] || {};\n\t\tvar activeVersion = versions[version];\n\t\tif(!activeVersion || (!activeVersion.loaded && (!eager != !activeVersion.eager ? eager : uniqueName > activeVersion.from))) versions[version] = { get: factory, from: uniqueName, eager: !!eager };\n\t};\n\tvar initExternal = (id) => {\n\t\tvar handleError = (err) => (warn(\"Initialization of sharing external failed: \" + err));\n\t\ttry {\n\t\t\tvar module = __webpack_require__(id);\n\t\t\tif(!module) return;\n\t\t\tvar initFn = (module) => (module && module.init && module.init(__webpack_require__.S[name], initScope))\n\t\t\tif(module.then) return promises.push(module.then(initFn, handleError));\n\t\t\tvar initResult = initFn(module);\n\t\t\tif(initResult && initResult.then) return promises.push(initResult['catch'](handleError));\n\t\t} catch(err) { handleError(err); }\n\t}\n\tvar promises = [];\n\tswitch(name) {\n\t\tcase \"default\": {\n\t\t\tregister(\"react\", \"16.14.0\", () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540))))));\n\t\t}\n\t\tbreak;\n\t}\n\tif(!promises.length) return initPromises[name] = 1;\n\treturn initPromises[name] = Promise.all(promises).then(() => (initPromises[name] = 1));\n};","var scriptUrl;\nif (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \"\";\nvar document = __webpack_require__.g.document;\nif (!scriptUrl && document) {\n\tif (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT')\n\t\tscriptUrl = document.currentScript.src;\n\tif (!scriptUrl) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tif(scripts.length) {\n\t\t\tvar i = scripts.length - 1;\n\t\t\twhile (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;\n\t\t}\n\t}\n}\n// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration\n// or pass an empty string (\"\") and set the __webpack_public_path__ variable from your code to use your own logic.\nif (!scriptUrl) throw new Error(\"Automatic publicPath is not supported in this browser\");\nscriptUrl = scriptUrl.replace(/^blob:/, \"\").replace(/#.*$/, \"\").replace(/\\?.*$/, \"\").replace(/\\/[^\\/]+$/, \"/\");\n__webpack_require__.p = scriptUrl;","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t981: 0\n};\n\n__webpack_require__.f.j = (chunkId, promises) => {\n\t\t// JSONP chunk loading for javascript\n\t\tvar installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;\n\t\tif(installedChunkData !== 0) { // 0 means \"already installed\".\n\n\t\t\t// a Promise means \"currently loading\".\n\t\t\tif(installedChunkData) {\n\t\t\t\tpromises.push(installedChunkData[2]);\n\t\t\t} else {\n\t\t\t\tif(true) { // all chunks have JS\n\t\t\t\t\t// setup Promise in chunk cache\n\t\t\t\t\tvar promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));\n\t\t\t\t\tpromises.push(installedChunkData[2] = promise);\n\n\t\t\t\t\t// start chunk loading\n\t\t\t\t\tvar url = __webpack_require__.p + __webpack_require__.u(chunkId);\n\t\t\t\t\t// create error before stack unwound to get useful stacktrace later\n\t\t\t\t\tvar error = new Error();\n\t\t\t\t\tvar loadingEnded = (event) => {\n\t\t\t\t\t\tif(__webpack_require__.o(installedChunks, chunkId)) {\n\t\t\t\t\t\t\tinstalledChunkData = installedChunks[chunkId];\n\t\t\t\t\t\t\tif(installedChunkData !== 0) installedChunks[chunkId] = undefined;\n\t\t\t\t\t\t\tif(installedChunkData) {\n\t\t\t\t\t\t\t\tvar errorType = event && (event.type === 'load' ? 'missing' : event.type);\n\t\t\t\t\t\t\t\tvar realSrc = event && event.target && event.target.src;\n\t\t\t\t\t\t\t\terror.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';\n\t\t\t\t\t\t\t\terror.name = 'ChunkLoadError';\n\t\t\t\t\t\t\t\terror.type = errorType;\n\t\t\t\t\t\t\t\terror.request = realSrc;\n\t\t\t\t\t\t\t\tinstalledChunkData[1](error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t__webpack_require__.l(url, loadingEnded, \"chunk-\" + chunkId, chunkId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n};\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n// no on chunks loaded\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunksignalk_edge_link\"] = self[\"webpackChunksignalk_edge_link\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// module cache are used so entry inlining is disabled\n// startup\n// Load entry module and return exports\nvar __webpack_exports__ = __webpack_require__(805);\n"],"names":["inProgress","dataWebpackPrefix","parseVersion","versionLt","rangeToString","satisfy","exists","get","eagerOnly","findLatestVersion","findSatisfyingVersion","getInvalidVersionMessage","fail","init","useFallback","load","loadStrictVersion","installedModules","moduleToHandlerMapping","chunkMapping","startedInstallModules","moduleMap","Promise","all","__webpack_require__","e","then","module","getScope","R","o","resolve","Error","undefined","shareScope","initScope","S","name","oldScope","I","d","exports","__webpack_module_cache__","moduleId","cachedModule","id","loaded","__webpack_modules__","m","c","n","getter","__esModule","a","definition","key","Object","defineProperty","enumerable","f","chunkId","keys","reduce","promises","u","miniCssF","g","globalThis","this","Function","window","obj","prop","prototype","hasOwnProperty","call","l","url","done","push","script","needAttach","scripts","document","getElementsByTagName","i","length","s","getAttribute","createElement","charset","nc","setAttribute","src","onScriptComplete","prev","event","onerror","onload","clearTimeout","timeout","doneFns","parentNode","removeChild","forEach","fn","setTimeout","bind","type","target","head","appendChild","r","Symbol","toStringTag","value","nmd","paths","children","initPromises","initTokens","initToken","indexOf","scope","uniqueName","version","factory","eager","versions","activeVersion","from","register","scriptUrl","importScripts","location","currentScript","tagName","toUpperCase","test","replace","p","str","split","map","exec","apply","b","t","range","pop","entry","filtered","requiredVersion","scopeName","join","msg","fallback","failAsNotExist","promise","satisfyingVersion","consumes","onFactory","onError","error","installedChunks","j","installedChunkData","reject","errorType","realSrc","message","request","webpackJsonpCallback","parentChunkLoadingFunction","data","chunkIds","moreModules","runtime","some","chunkLoadingGlobal","self","__webpack_exports__"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"remoteEntry.js","mappings":"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","sources":["webpack://signalk-edge-link/webpack/runtime/load script","webpack://signalk-edge-link/webpack/runtime/consumes","webpack://signalk-edge-link/webpack/container-entry","webpack://signalk-edge-link/webpack/bootstrap","webpack://signalk-edge-link/webpack/runtime/compat get default export","webpack://signalk-edge-link/webpack/runtime/define property getters","webpack://signalk-edge-link/webpack/runtime/ensure chunk","webpack://signalk-edge-link/webpack/runtime/get javascript chunk filename","webpack://signalk-edge-link/webpack/runtime/get mini-css chunk filename","webpack://signalk-edge-link/webpack/runtime/global","webpack://signalk-edge-link/webpack/runtime/hasOwnProperty shorthand","webpack://signalk-edge-link/webpack/runtime/make namespace object","webpack://signalk-edge-link/webpack/runtime/node module decorator","webpack://signalk-edge-link/webpack/runtime/sharing","webpack://signalk-edge-link/webpack/runtime/publicPath","webpack://signalk-edge-link/webpack/runtime/jsonp chunk loading","webpack://signalk-edge-link/webpack/startup"],"sourcesContent":["var inProgress = {};\nvar dataWebpackPrefix = \"signalk-edge-link:\";\n// loadScript function to load a script via script tag\n__webpack_require__.l = (url, done, key, chunkId) => {\n\tif(inProgress[url]) { inProgress[url].push(done); return; }\n\tvar script, needAttach;\n\tif(key !== undefined) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tfor(var i = 0; i < scripts.length; i++) {\n\t\t\tvar s = scripts[i];\n\t\t\tif(s.getAttribute(\"src\") == url || s.getAttribute(\"data-webpack\") == dataWebpackPrefix + key) { script = s; break; }\n\t\t}\n\t}\n\tif(!script) {\n\t\tneedAttach = true;\n\t\tscript = document.createElement('script');\n\n\t\tscript.charset = 'utf-8';\n\t\tif (__webpack_require__.nc) {\n\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n\t\t}\n\t\tscript.setAttribute(\"data-webpack\", dataWebpackPrefix + key);\n\n\t\tscript.src = url;\n\t}\n\tinProgress[url] = [done];\n\tvar onScriptComplete = (prev, event) => {\n\t\t// avoid mem leaks in IE.\n\t\tscript.onerror = script.onload = null;\n\t\tclearTimeout(timeout);\n\t\tvar doneFns = inProgress[url];\n\t\tdelete inProgress[url];\n\t\tscript.parentNode && script.parentNode.removeChild(script);\n\t\tdoneFns && doneFns.forEach((fn) => (fn(event)));\n\t\tif(prev) return prev(event);\n\t}\n\tvar timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);\n\tscript.onerror = onScriptComplete.bind(null, script.onerror);\n\tscript.onload = onScriptComplete.bind(null, script.onload);\n\tneedAttach && document.head.appendChild(script);\n};","var parseVersion = (str) => {\n\t// see webpack/lib/util/semver.js for original code\n\tvar p=p=>{return p.split(\".\").map(p=>{return+p==p?+p:p})},n=/^([^-+]+)?(?:-([^+]+))?(?:\\+(.+))?$/.exec(str),r=n[1]?p(n[1]):[];return n[2]&&(r.length++,r.push.apply(r,p(n[2]))),n[3]&&(r.push([]),r.push.apply(r,p(n[3]))),r;\n}\nvar versionLt = (a, b) => {\n\t// see webpack/lib/util/semver.js for original code\n\ta=parseVersion(a),b=parseVersion(b);for(var r=0;;){if(r>=a.length)return r<b.length&&\"u\"!=(typeof b[r])[0];var e=a[r],n=(typeof e)[0];if(r>=b.length)return\"u\"==n;var t=b[r],f=(typeof t)[0];if(n!=f)return\"o\"==n&&\"n\"==f||(\"s\"==f||\"u\"==n);if(\"o\"!=n&&\"u\"!=n&&e!=t)return e<t;r++}\n}\nvar rangeToString = (range) => {\n\t// see webpack/lib/util/semver.js for original code\n\tvar r=range[0],n=\"\";if(1===range.length)return\"*\";if(r+.5){n+=0==r?\">=\":-1==r?\"<\":1==r?\"^\":2==r?\"~\":r>0?\"=\":\"!=\";for(var e=1,a=1;a<range.length;a++){e--,n+=\"u\"==(typeof(t=range[a]))[0]?\"-\":(e>0?\".\":\"\")+(e=2,t)}return n}var g=[];for(a=1;a<range.length;a++){var t=range[a];g.push(0===t?\"not(\"+o()+\")\":1===t?\"(\"+o()+\" || \"+o()+\")\":2===t?g.pop()+\" \"+g.pop():rangeToString(t))}return o();function o(){return g.pop().replace(/^\\((.+)\\)$/,\"$1\")}\n}\nvar satisfy = (range, version) => {\n\t// see webpack/lib/util/semver.js for original code\n\tif(0 in range){version=parseVersion(version);var e=range[0],r=e<0;r&&(e=-e-1);for(var n=0,i=1,a=!0;;i++,n++){var f,s,g=i<range.length?(typeof range[i])[0]:\"\";if(n>=version.length||\"o\"==(s=(typeof(f=version[n]))[0]))return!a||(\"u\"==g?i>e&&!r:\"\"==g!=r);if(\"u\"==s){if(!a||\"u\"!=g)return!1}else if(a)if(g==s)if(i<=e){if(f!=range[i])return!1}else{if(r?f>range[i]:f<range[i])return!1;f!=range[i]&&(a=!1)}else if(\"s\"!=g&&\"n\"!=g){if(r||i<=e)return!1;a=!1,i--}else{if(i<=e||s<g!=r)return!1;a=!1}else\"s\"!=g&&\"n\"!=g&&(a=!1,i--)}}var t=[],o=t.pop.bind(t);for(n=1;n<range.length;n++){var u=range[n];t.push(1==u?o()|o():2==u?o()&o():u?satisfy(u,version):!o())}return!!o();\n}\nvar exists = (scope, key) => {\n\treturn scope && __webpack_require__.o(scope, key);\n}\nvar get = (entry) => {\n\tentry.loaded = 1;\n\treturn entry.get()\n};\nvar eagerOnly = (versions) => {\n\treturn Object.keys(versions).reduce((filtered, version) => {\n\t\t\tif (versions[version].eager) {\n\t\t\t\tfiltered[version] = versions[version];\n\t\t\t}\n\t\t\treturn filtered;\n\t}, {});\n};\nvar findLatestVersion = (scope, key, eager) => {\n\tvar versions = eager ? eagerOnly(scope[key]) : scope[key];\n\tvar key = Object.keys(versions).reduce((a, b) => {\n\t\treturn !a || versionLt(a, b) ? b : a;\n\t}, 0);\n\treturn key && versions[key];\n};\nvar findSatisfyingVersion = (scope, key, requiredVersion, eager) => {\n\tvar versions = eager ? eagerOnly(scope[key]) : scope[key];\n\tvar key = Object.keys(versions).reduce((a, b) => {\n\t\tif (!satisfy(requiredVersion, b)) return a;\n\t\treturn !a || versionLt(a, b) ? b : a;\n\t}, 0);\n\treturn key && versions[key]\n};\nvar findSingletonVersionKey = (scope, key, eager) => {\n\tvar versions = eager ? eagerOnly(scope[key]) : scope[key];\n\treturn Object.keys(versions).reduce((a, b) => {\n\t\treturn !a || (!versions[a].loaded && versionLt(a, b)) ? b : a;\n\t}, 0);\n};\nvar getInvalidSingletonVersionMessage = (scope, key, version, requiredVersion) => {\n\treturn \"Unsatisfied version \" + version + \" from \" + (version && scope[key][version].from) + \" of shared singleton module \" + key + \" (required \" + rangeToString(requiredVersion) + \")\"\n};\nvar getInvalidVersionMessage = (scope, scopeName, key, requiredVersion, eager) => {\n\tvar versions = scope[key];\n\treturn \"No satisfying version (\" + rangeToString(requiredVersion) + \")\" + (eager ? \" for eager consumption\" : \"\") + \" of shared module \" + key + \" found in shared scope \" + scopeName + \".\\n\" +\n\t\t\"Available versions: \" + Object.keys(versions).map((key) => {\n\t\treturn key + \" from \" + versions[key].from;\n\t}).join(\", \");\n};\nvar fail = (msg) => {\n\tthrow new Error(msg);\n}\nvar failAsNotExist = (scopeName, key) => {\n\treturn fail(\"Shared module \" + key + \" doesn't exist in shared scope \" + scopeName);\n}\nvar warn = /*#__PURE__*/ (msg) => {\n\tif (typeof console !== \"undefined\" && console.warn) console.warn(msg);\n};\nvar init = (fn) => (function(scopeName, key, eager, c, d) {\n\tvar promise = __webpack_require__.I(scopeName);\n\tif (promise && promise.then && !eager) {\n\t\treturn promise.then(fn.bind(fn, scopeName, __webpack_require__.S[scopeName], key, false, c, d));\n\t}\n\treturn fn(scopeName, __webpack_require__.S[scopeName], key, eager, c, d);\n});\n\nvar useFallback = (scopeName, key, fallback) => {\n\treturn fallback ? fallback() : failAsNotExist(scopeName, key);\n}\nvar load = /*#__PURE__*/ init((scopeName, scope, key, eager, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\treturn get(findLatestVersion(scope, key, eager));\n});\nvar loadVersion = /*#__PURE__*/ init((scopeName, scope, key, eager, requiredVersion, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar satisfyingVersion = findSatisfyingVersion(scope, key, requiredVersion, eager);\n\tif (satisfyingVersion) return get(satisfyingVersion);\n\twarn(getInvalidVersionMessage(scope, scopeName, key, requiredVersion, eager))\n\treturn get(findLatestVersion(scope, key, eager));\n});\nvar loadStrictVersion = /*#__PURE__*/ init((scopeName, scope, key, eager, requiredVersion, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar satisfyingVersion = findSatisfyingVersion(scope, key, requiredVersion, eager);\n\tif (satisfyingVersion) return get(satisfyingVersion);\n\tif (fallback) return fallback();\n\tfail(getInvalidVersionMessage(scope, scopeName, key, requiredVersion, eager));\n});\nvar loadSingleton = /*#__PURE__*/ init((scopeName, scope, key, eager, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar version = findSingletonVersionKey(scope, key, eager);\n\treturn get(scope[key][version]);\n});\nvar loadSingletonVersion = /*#__PURE__*/ init((scopeName, scope, key, eager, requiredVersion, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar version = findSingletonVersionKey(scope, key, eager);\n\tif (!satisfy(requiredVersion, version)) {\n\t\twarn(getInvalidSingletonVersionMessage(scope, key, version, requiredVersion));\n\t}\n\treturn get(scope[key][version]);\n});\nvar loadStrictSingletonVersion = /*#__PURE__*/ init((scopeName, scope, key, eager, requiredVersion, fallback) => {\n\tif (!exists(scope, key)) return useFallback(scopeName, key, fallback);\n\tvar version = findSingletonVersionKey(scope, key, eager);\n\tif (!satisfy(requiredVersion, version)) {\n\t\tfail(getInvalidSingletonVersionMessage(scope, key, version, requiredVersion));\n\t}\n\treturn get(scope[key][version]);\n});\nvar installedModules = {};\nvar moduleToHandlerMapping = {\n\t4147: () => (loadStrictVersion(\"default\", \"react\", false, [1,16,13,1], () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540))))))),\n\t4167: () => (load(\"default\", \"react\", false, () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540))))))),\n\t7920: () => (loadStrictVersion(\"default\", \"react\", false, [,[0,17],[1,16,14,0],1], () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540))))))),\n\t8271: () => (loadStrictVersion(\"default\", \"react\", false, [0,0,14,0], () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540)))))))\n};\n// no consumes in initial chunks\nvar chunkMapping = {\n\t\"982\": [\n\t\t4147,\n\t\t4167,\n\t\t7920,\n\t\t8271\n\t]\n};\nvar startedInstallModules = {};\n__webpack_require__.f.consumes = (chunkId, promises) => {\n\tif(__webpack_require__.o(chunkMapping, chunkId)) {\n\t\tchunkMapping[chunkId].forEach((id) => {\n\t\t\tif(__webpack_require__.o(installedModules, id)) return promises.push(installedModules[id]);\n\t\t\tif(!startedInstallModules[id]) {\n\t\t\tvar onFactory = (factory) => {\n\t\t\t\tinstalledModules[id] = 0;\n\t\t\t\t__webpack_require__.m[id] = (module) => {\n\t\t\t\t\tdelete __webpack_require__.c[id];\n\t\t\t\t\tmodule.exports = factory();\n\t\t\t\t}\n\t\t\t};\n\t\t\tstartedInstallModules[id] = true;\n\t\t\tvar onError = (error) => {\n\t\t\t\tdelete installedModules[id];\n\t\t\t\t__webpack_require__.m[id] = (module) => {\n\t\t\t\t\tdelete __webpack_require__.c[id];\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tvar promise = moduleToHandlerMapping[id]();\n\t\t\t\tif(promise.then) {\n\t\t\t\t\tpromises.push(installedModules[id] = promise.then(onFactory)['catch'](onError));\n\t\t\t\t} else onFactory(promise);\n\t\t\t} catch(e) { onError(e); }\n\t\t\t}\n\t\t});\n\t}\n}","var moduleMap = {\n\t\"./PluginConfigurationPanel\": () => {\n\t\treturn Promise.all([__webpack_require__.e(277), __webpack_require__.e(982)]).then(() => (() => ((__webpack_require__(4353)))));\n\t}\n};\nvar get = (module, getScope) => {\n\t__webpack_require__.R = getScope;\n\tgetScope = (\n\t\t__webpack_require__.o(moduleMap, module)\n\t\t\t? moduleMap[module]()\n\t\t\t: Promise.resolve().then(() => {\n\t\t\t\tthrow new Error('Module \"' + module + '\" does not exist in container.');\n\t\t\t})\n\t);\n\t__webpack_require__.R = undefined;\n\treturn getScope;\n};\nvar init = (shareScope, initScope) => {\n\tif (!__webpack_require__.S) return;\n\tvar name = \"default\"\n\tvar oldScope = __webpack_require__.S[name];\n\tif(oldScope && oldScope !== shareScope) throw new Error(\"Container initialization failed as it has already been initialized with a different share scope\");\n\t__webpack_require__.S[name] = shareScope;\n\treturn __webpack_require__.I(name, initScope);\n};\n\n// This exports getters to disallow modifications\n__webpack_require__.d(exports, {\n\tget: () => (get),\n\tinit: () => (init)\n});","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n// expose the module cache\n__webpack_require__.c = __webpack_module_cache__;\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.f = {};\n// This file contains only the entry chunk.\n// The chunk loading function for additional chunks\n__webpack_require__.e = (chunkId) => {\n\treturn Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {\n\t\t__webpack_require__.f[key](chunkId, promises);\n\t\treturn promises;\n\t}, []));\n};","// This function allow to reference async chunks\n__webpack_require__.u = (chunkId) => {\n\t// return url for filenames based on template\n\treturn \"\" + chunkId + \".\" + {\"277\":\"99e19dcb5b778c964ace\",\"540\":\"70a0bc6aadb412703390\",\"982\":\"63949a2b2f6c5854e034\"}[chunkId] + \".js\";\n};","// This function allow to reference async chunks\n__webpack_require__.miniCssF = (chunkId) => {\n\t// return url for filenames based on template\n\treturn undefined;\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.S = {};\nvar initPromises = {};\nvar initTokens = {};\n__webpack_require__.I = (name, initScope) => {\n\tif(!initScope) initScope = [];\n\t// handling circular init calls\n\tvar initToken = initTokens[name];\n\tif(!initToken) initToken = initTokens[name] = {};\n\tif(initScope.indexOf(initToken) >= 0) return;\n\tinitScope.push(initToken);\n\t// only runs once\n\tif(initPromises[name]) return initPromises[name];\n\t// creates a new share scope if needed\n\tif(!__webpack_require__.o(__webpack_require__.S, name)) __webpack_require__.S[name] = {};\n\t// runs all init snippets from all modules reachable\n\tvar scope = __webpack_require__.S[name];\n\tvar warn = (msg) => {\n\t\tif (typeof console !== \"undefined\" && console.warn) console.warn(msg);\n\t};\n\tvar uniqueName = \"signalk-edge-link\";\n\tvar register = (name, version, factory, eager) => {\n\t\tvar versions = scope[name] = scope[name] || {};\n\t\tvar activeVersion = versions[version];\n\t\tif(!activeVersion || (!activeVersion.loaded && (!eager != !activeVersion.eager ? eager : uniqueName > activeVersion.from))) versions[version] = { get: factory, from: uniqueName, eager: !!eager };\n\t};\n\tvar initExternal = (id) => {\n\t\tvar handleError = (err) => (warn(\"Initialization of sharing external failed: \" + err));\n\t\ttry {\n\t\t\tvar module = __webpack_require__(id);\n\t\t\tif(!module) return;\n\t\t\tvar initFn = (module) => (module && module.init && module.init(__webpack_require__.S[name], initScope))\n\t\t\tif(module.then) return promises.push(module.then(initFn, handleError));\n\t\t\tvar initResult = initFn(module);\n\t\t\tif(initResult && initResult.then) return promises.push(initResult['catch'](handleError));\n\t\t} catch(err) { handleError(err); }\n\t}\n\tvar promises = [];\n\tswitch(name) {\n\t\tcase \"default\": {\n\t\t\tregister(\"react\", \"16.14.0\", () => (__webpack_require__.e(540).then(() => (() => (__webpack_require__(6540))))));\n\t\t}\n\t\tbreak;\n\t}\n\tif(!promises.length) return initPromises[name] = 1;\n\treturn initPromises[name] = Promise.all(promises).then(() => (initPromises[name] = 1));\n};","var scriptUrl;\nif (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \"\";\nvar document = __webpack_require__.g.document;\nif (!scriptUrl && document) {\n\tif (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT')\n\t\tscriptUrl = document.currentScript.src;\n\tif (!scriptUrl) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tif(scripts.length) {\n\t\t\tvar i = scripts.length - 1;\n\t\t\twhile (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;\n\t\t}\n\t}\n}\n// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration\n// or pass an empty string (\"\") and set the __webpack_public_path__ variable from your code to use your own logic.\nif (!scriptUrl) throw new Error(\"Automatic publicPath is not supported in this browser\");\nscriptUrl = scriptUrl.replace(/^blob:/, \"\").replace(/#.*$/, \"\").replace(/\\?.*$/, \"\").replace(/\\/[^\\/]+$/, \"/\");\n__webpack_require__.p = scriptUrl;","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t981: 0\n};\n\n__webpack_require__.f.j = (chunkId, promises) => {\n\t\t// JSONP chunk loading for javascript\n\t\tvar installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;\n\t\tif(installedChunkData !== 0) { // 0 means \"already installed\".\n\n\t\t\t// a Promise means \"currently loading\".\n\t\t\tif(installedChunkData) {\n\t\t\t\tpromises.push(installedChunkData[2]);\n\t\t\t} else {\n\t\t\t\tif(true) { // all chunks have JS\n\t\t\t\t\t// setup Promise in chunk cache\n\t\t\t\t\tvar promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));\n\t\t\t\t\tpromises.push(installedChunkData[2] = promise);\n\n\t\t\t\t\t// start chunk loading\n\t\t\t\t\tvar url = __webpack_require__.p + __webpack_require__.u(chunkId);\n\t\t\t\t\t// create error before stack unwound to get useful stacktrace later\n\t\t\t\t\tvar error = new Error();\n\t\t\t\t\tvar loadingEnded = (event) => {\n\t\t\t\t\t\tif(__webpack_require__.o(installedChunks, chunkId)) {\n\t\t\t\t\t\t\tinstalledChunkData = installedChunks[chunkId];\n\t\t\t\t\t\t\tif(installedChunkData !== 0) installedChunks[chunkId] = undefined;\n\t\t\t\t\t\t\tif(installedChunkData) {\n\t\t\t\t\t\t\t\tvar errorType = event && (event.type === 'load' ? 'missing' : event.type);\n\t\t\t\t\t\t\t\tvar realSrc = event && event.target && event.target.src;\n\t\t\t\t\t\t\t\terror.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';\n\t\t\t\t\t\t\t\terror.name = 'ChunkLoadError';\n\t\t\t\t\t\t\t\terror.type = errorType;\n\t\t\t\t\t\t\t\terror.request = realSrc;\n\t\t\t\t\t\t\t\tinstalledChunkData[1](error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t__webpack_require__.l(url, loadingEnded, \"chunk-\" + chunkId, chunkId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n};\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n// no on chunks loaded\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunksignalk_edge_link\"] = self[\"webpackChunksignalk_edge_link\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// module cache are used so entry inlining is disabled\n// startup\n// Load entry module and return exports\nvar __webpack_exports__ = __webpack_require__(805);\n"],"names":["inProgress","dataWebpackPrefix","parseVersion","versionLt","rangeToString","satisfy","exists","get","eagerOnly","findLatestVersion","findSatisfyingVersion","getInvalidVersionMessage","fail","init","useFallback","load","loadStrictVersion","installedModules","moduleToHandlerMapping","chunkMapping","startedInstallModules","moduleMap","Promise","all","__webpack_require__","e","then","module","getScope","R","o","resolve","Error","undefined","shareScope","initScope","S","name","oldScope","I","d","exports","__webpack_module_cache__","moduleId","cachedModule","id","loaded","__webpack_modules__","m","c","n","getter","__esModule","a","definition","key","Object","defineProperty","enumerable","f","chunkId","keys","reduce","promises","u","miniCssF","g","globalThis","this","Function","window","obj","prop","prototype","hasOwnProperty","call","l","url","done","push","script","needAttach","scripts","document","getElementsByTagName","i","length","s","getAttribute","createElement","charset","nc","setAttribute","src","onScriptComplete","prev","event","onerror","onload","clearTimeout","timeout","doneFns","parentNode","removeChild","forEach","fn","setTimeout","bind","type","target","head","appendChild","r","Symbol","toStringTag","value","nmd","paths","children","initPromises","initTokens","initToken","indexOf","scope","uniqueName","version","factory","eager","versions","activeVersion","from","register","scriptUrl","importScripts","location","currentScript","tagName","toUpperCase","test","replace","p","str","split","map","exec","apply","b","t","range","pop","entry","filtered","requiredVersion","scopeName","join","msg","fallback","failAsNotExist","promise","satisfyingVersion","consumes","onFactory","onError","error","installedChunks","j","installedChunkData","reject","errorType","realSrc","message","request","webpackJsonpCallback","parentChunkLoadingFunction","data","chunkIds","moreModules","runtime","some","chunkLoadingGlobal","self","__webpack_exports__"],"sourceRoot":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"982.b207a377ed6542e2fb4a.js","mappings":"4LAEO,MAAMA,EAAiC,qCAgBxCC,EAAkC,CACtCC,MAAO,KACPC,gBAAiB,iCACjBC,WAAY,gBAIZC,qBAAqB,EACrBC,WAAY,QAsFP,SAASC,EAASC,EAAyBC,EAAoB,CAAC,GACrE,MAAMC,EApFR,WACE,GAAsB,oBAAXC,OACT,OAAOV,EAGT,MAAMW,EAAUD,OAAOE,mBACvB,OAAKD,GAA8B,iBAAZA,EAIhB,IAAKX,KAAwBW,GAH3BX,CAIX,CAyEiBa,GACTZ,EAxER,SAAsBQ,GACpB,GAAIA,EAAOR,MACT,OAAOa,OAAOL,EAAOR,OAAOc,OAG9B,GAAsB,oBAAXL,OACT,MAAO,GAOT,GAAID,EAAOL,qBAAuBK,EAAON,WAAY,CACnD,MAAMa,EAAiB,IAAIC,gBAAgBP,OAAOQ,SAASC,QAAQC,IAAIX,EAAON,YAC9E,GAAIa,EACF,OAAOA,EAAeD,MAE1B,CAEA,GAAIN,EAAOP,iBAAmBQ,OAAOW,aAAc,CACjD,MAAMC,EAAmBZ,OAAOW,aAAaE,QAAQd,EAAOP,iBAC5D,GAAIoB,EACF,OAAOA,EAAiBP,MAE5B,CAEA,MAAO,EACT,CA4CgBS,CAAaf,GACrBgB,EAAU,IAAIC,QAAQlB,EAAKiB,SAAW,CAAC,GAG7C,OA9CF,SAA2BA,EAAkBxB,EAAeI,GAC1D,IAAKJ,EACH,OAAOwB,EAGT,MAAME,GAAkBtB,GAAc,QAAQuB,cAEzB,sBAAnBD,GACmB,UAAnBA,GACmB,SAAnBA,GAEAF,EAAQI,IAAI,oBAAqB5B,GAGd,kBAAnB0B,GACmB,WAAnBA,GACmB,SAAnBA,GAEAF,EAAQI,IAAI,gBAAiB,UAAU5B,IAG3C,CAuBE6B,CAAkBL,EAASxB,EAAOQ,EAAOJ,YAElC0B,MAAMxB,EAAO,IACfC,EACHiB,WAEJ,CCzGO,MCKMO,EAA6D,CACxEC,KAAM,CACJC,KAAM,SACNC,MAAO,kBACPC,YACE,2IACFC,QAAS,aACTC,UAAW,IAEbC,WAAY,CACVL,KAAM,SACNC,MAAO,iBACPC,YAAa,yDACbC,QAAS,SACTG,MAAO,CACL,CAAEC,MAAO,SAAUN,MAAO,8BAC1B,CAAEM,MAAO,SAAUN,MAAO,6BAG9BO,QAAS,CACPR,KAAM,SACNC,MAAO,WACPC,YAAa,4DACbC,QAAS,KACTM,QAAS,KACTC,QAAS,OAEXC,UAAW,CACTX,KAAM,SACNC,MAAO,iBACPC,YACE,oFACFU,UAAW,GACXR,UAAW,GACXS,QAAS,mDAEXC,gBAAiB,CACfd,KAAM,UACNC,MAAO,qCACPC,YAAa,6ED5CgB,IC4C+Ea,eAAe,kOAC3HZ,SAAS,GAEXa,WAAY,CACVhB,KAAM,UACNC,MAAO,kBACPC,YAAa,uEACbC,SAAS,GAEXc,kBAAmB,CACjBjB,KAAM,UACNC,MAAO,sBACPC,YAAa,+EACbC,SAAS,GAEXe,gBAAiB,CACflB,KAAM,SACNC,MAAO,mBACPC,YACE,4KACFC,QAAS,EACTG,MAAO,CACL,CAAEC,MAAO,EAAGN,MAAO,+BACnB,CAAEM,MAAO,EAAGN,MAAO,0DACnB,CAAEM,MAAO,EAAGN,MAAO,0DAOZkB,EAA4D,CACvEC,WAAY,CACVpB,KAAM,SACNC,MAAO,iBACPC,YAAa,0DACbC,QAAS,aAEXkB,mBAAoB,CAClBrB,KAAM,UACNC,MAAO,+BACPC,YAAa,wEACbC,QAAS,GACTM,QAAS,GACTC,QAAS,MAEXY,YAAa,CACXtB,KAAM,SACNC,MAAO,4BACPC,YAAa,oDACbC,QAAS,aAEXoB,SAAU,CACRvB,KAAM,SACNC,MAAO,yBACPC,YAAa,2DACbC,QAAS,GACTM,QAAS,EACTC,QAAS,OAEXc,iBAAkB,CAChBxB,KAAM,SACNC,MAAO,2BACPC,YAAa,4CACbC,QAAS,EACTM,QAAS,GACTC,QAAS,IAEXe,kBAAmB,CACjBzB,KAAM,SACNC,MAAO,wCACPC,YACE,sHACFC,QAAS,KACTM,QAAS,IACTC,QAAS,OAMAgB,EAA4C,CACvD1B,KAAM,SACNC,MAAO,oCACPC,YACE,0FACFyB,WAAY,CACVC,oBAAqB,CACnB5B,KAAM,SACNC,MAAO,wBACPC,YAAa,sEACbC,QAAS,IACTM,QAAS,IACTC,QAAS,KAEXmB,eAAgB,CACd7B,KAAM,SACNC,MAAO,0BACPC,YAAa,gFACbC,QAAS,EACTM,QAAS,EACTC,QAAS,IAEXoB,iBAAkB,CAChB9B,KAAM,SACNC,MAAO,0BACPC,YAAa,2DACbC,QAAS,KACTM,QAAS,IACTC,QAAS,KAEXqB,iBAAkB,CAChB/B,KAAM,SACNC,MAAO,0BACPC,YAAa,mDACbC,QAAS,IACTM,QAAS,IACTC,QAAS,KAEXsB,wBAAyB,CACvBhC,KAAM,SACNC,MAAO,wBACPC,YAAa,8CACbC,QAAS,GACTM,QAAS,EACTC,QAAS,IAEXuB,gBAAiB,CACfjC,KAAM,SACNC,MAAO,0BACPC,YAAa,qEACbC,QAAS,IACTM,QAAS,IACTC,QAAS,KAEXwB,uBAAwB,CACtBlC,KAAM,UACNC,MAAO,6BACPC,YAAa,uEACbC,SAAS,GAEXgC,kBAAmB,CACjBnC,KAAM,SACNC,MAAO,2BACPC,YAAa,oEACbC,QAAS,KACTM,QAAS,IACTC,QAAS,MAEX0B,qBAAsB,CACpBpC,KAAM,UACNC,MAAO,yBACPC,YAAa,gFACbC,SAAS,GAEXkC,kBAAmB,CACjBrC,KAAM,SACNC,MAAO,sBACPC,YAAa,6DACbC,QAAS,IACTM,QAAS,GACTC,QAAS,KAEX4B,wBAAyB,CACvBtC,KAAM,SACNC,MAAO,+BACPC,YAAa,+DACbC,QAAS,IACTM,QAAS,GACTC,QAAS,KAEX6B,iBAAkB,CAChBvC,KAAM,SACNC,MAAO,wBACPC,YAAa,8DACbC,QAAS,IACTM,QAAS,IACTC,QAAS,QAOF8B,EAA4C,CACvDxC,KAAM,SACNC,MAAO,oCACPC,YAAa,6EACbyB,WAAY,CACVc,YAAa,CACXzC,KAAM,SACNC,MAAO,oBACPC,YAAa,iDACbC,QAAS,IACTM,QAAS,GACTC,QAAS,KAEXgC,kBAAmB,CACjB1C,KAAM,SACNC,MAAO,2BACPC,YAAa,uEACbC,QAAS,IACTM,QAAS,IACTC,QAAS,KAEXiC,WAAY,CACV3C,KAAM,SACNC,MAAO,mBACPC,YAAa,uEACbC,QAAS,IACTM,QAAS,GACTC,QAAS,OAOFkC,EAA4C,CACvD5C,KAAM,SACNC,MAAO,0CACPC,YACE,0GACFyB,WAAY,CACVkB,QAAS,CACP7C,KAAM,UACNC,MAAO,4BACPC,YAAa,iEACbC,SAAS,GAEX2C,UAAW,CACT9C,KAAM,SACNC,MAAO,kBACPC,YAAa,kDACbC,QAAS,IACTM,QAAS,GACTC,QAAS,KAEXqC,kBAAmB,CACjB/C,KAAM,SACNC,MAAO,2BACPC,YAAa,wCACbC,QAAS,IACTM,QAAS,IACTC,QAAS,KAEXsC,cAAe,CACbhD,KAAM,SACNC,MAAO,2BACPC,YAAa,iCACbC,QAAS,IACTM,QAAS,GACTC,QAAS,KAEXuC,cAAe,CACbjD,KAAM,SACNC,MAAO,2BACPC,YAAa,iCACbC,QAAS,IACTM,QAAS,IACTC,QAAS,OAOFwC,EAAkC,CAC7ClD,KAAM,SACNC,MAAO,kCACPC,YACE,gHACFyB,WAAY,CACVkB,QAAS,CACP7C,KAAM,UACNC,MAAO,4BACPC,YAAa,oDACbC,SAAS,GAEXgD,KAAM,CACJnD,KAAM,SACNC,MAAO,eACPC,YAAa,0BACbC,QAAS,cACTG,MAAO,CACL,CACEC,MAAO,cACPN,MAAO,4DAIbmD,QAAS,CACPpD,KAAM,SACNC,MAAO,eACPC,YAAa,uCACbyB,WAAY,CACV0B,QAAS,CAAErD,KAAM,SAAUC,MAAO,iBAAkBE,QAAS,aAC7DmD,KAAM,CACJtD,KAAM,SACNC,MAAO,WACPE,QAAS,KACTM,QAAS,KACTC,QAAS,OAEX6C,UAAW,CACTvD,KAAM,SACNC,MAAO,4BACPC,YAAa,sCAInBsD,OAAQ,CACNxD,KAAM,SACNC,MAAO,cACPC,YAAa,gDACbyB,WAAY,CACV0B,QAAS,CAAErD,KAAM,SAAUC,MAAO,iBAAkBE,QAAS,aAC7DmD,KAAM,CACJtD,KAAM,SACNC,MAAO,WACPE,QAAS,KACTM,QAAS,KACTC,QAAS,OAEX6C,UAAW,CACTvD,KAAM,SACNC,MAAO,4BACPC,YAAa,sCAInBuD,SAAU,CACRzD,KAAM,SACNC,MAAO,sBACPC,YAAa,wCACbyB,WAAY,CACV+B,aAAc,CACZ1D,KAAM,SACNC,MAAO,qBACPE,QAAS,IACTM,QAAS,IACTC,QAAS,KAEXiD,cAAe,CACb3D,KAAM,SACNC,MAAO,8BACPE,QAAS,GACTM,QAAS,IACTC,QAAS,IAEXkD,oBAAqB,CACnB5D,KAAM,SACNC,MAAO,6BACPE,QAAS,IACTM,QAAS,IACTC,QAAS,KAEXmD,cAAe,CACb7D,KAAM,SACNC,MAAO,sBACPE,QAAS,IACTM,QAAS,IACTC,QAAS,KAEXoD,iBAAkB,CAChB9D,KAAM,SACNC,MAAO,yBACPE,QAAS,IACTM,QAAS,IACTC,QAAS,SASNqD,EAA8C,CACzD/D,KAAM,UACNC,MAAO,gCACPC,YAAa,8DACbC,SAAS,GAKE6D,EAA0C,CACrDhE,KAAM,SACNC,MAAO,2CACPC,YAAa,uEACbyB,WAAY,CACVsC,IAAK,CACHjE,KAAM,SACNC,MAAO,iBACP0B,WAAY,CACVuC,QAAS,CAAElE,KAAM,SAAUC,MAAO,mBAAoBE,QAAS,KAC/DgE,SAAU,CAAEnE,KAAM,SAAUC,MAAO,oBAAqBE,QAAS,OAGrEiE,WAAY,CACVpE,KAAM,SACNC,MAAO,yBACP0B,WAAY,CACVuC,QAAS,CAAElE,KAAM,SAAUC,MAAO,qBAAsBE,QAAS,KACjEgE,SAAU,CAAEnE,KAAM,SAAUC,MAAO,sBAAuBE,QAAS,MAGvEkE,eAAgB,CACdrE,KAAM,SACNC,MAAO,6BACP0B,WAAY,CACVuC,QAAS,CAAElE,KAAM,SAAUC,MAAO,2BAA4BE,QAAS,KACvEgE,SAAU,CAAEnE,KAAM,SAAUC,MAAO,4BAA6BE,QAAS,OAG7EmE,OAAQ,CACNtE,KAAM,SACNC,MAAO,oBACP0B,WAAY,CACVuC,QAAS,CAAElE,KAAM,SAAUC,MAAO,sBAAuBE,QAAS,KAClEgE,SAAU,CAAEnE,KAAM,SAAUC,MAAO,uBAAwBE,QAAS,OAGxEoE,WAAY,CACVvE,KAAM,SACNC,MAAO,yBACP0B,WAAY,CACVuC,QAAS,CAAElE,KAAM,SAAUC,MAAO,sBAAuBE,QAAS,KAClEgE,SAAU,CAAEnE,KAAM,SAAUC,MAAO,uBAAwBE,QAAS,SAsDrE,SAASqE,EACdC,EACAvD,GAEA,MAAMwD,EAAqBC,OAAOzD,IAAoB,EAChD0D,EAAwC,IAAK9E,GAC7C+E,EAAW,CAAC,aAAc,UAAW,aAgB3C,OAdIJ,GACFK,OAAOC,OAAOH,EAAOzD,GACrByD,EAAMI,oBAAsBjB,EAC5Bc,EAASI,KAAK,aAAc,cAAe,YACvCP,IACFE,EAAMM,YAAcxD,EACpBkD,EAAMO,kBAAoBvC,EAC1BgC,EAAMQ,QAAUlC,EAChB0B,EAAMS,gBAAkBrB,IAEjBU,IACTE,EAAMM,YAAc1C,GAGf,CAAExC,KAAM,SAAU6E,WAAUlD,WAAYiD,EACjD,CC/iBA,MAAMU,EAAW,6BAMjB,IAAIC,EAAS,EACb,SAASC,IAAmB,MAAO,QAAQC,KAAKC,WAAWH,GAAU,CA8BrE,SAASI,EAAwB5F,GAC/B,MAAO,CACL6F,IAAKJ,IACLzF,KAAMA,GAAQ,SACdM,WAAY,SACZG,QAAS,KACTG,UAAW,GACXG,iBAAiB,EACjBE,YAAY,EACZC,mBAAmB,EACnB+D,qBAAqB,EACrB9D,gBAAiB,EACjBE,WAAY,YACZC,mBAAoB,GACpBC,YAAa,YACbC,SAAU,GACVC,iBAAkB,EAEtB,CAEA,SAASqE,EAAwB9F,GAC/B,MAAO,CACL6F,IAAKJ,IACLzF,KAAMA,GAAQ,SACdM,WAAY,SACZG,QAAS,KACTG,UAAW,GACXG,iBAAiB,EACjBE,YAAY,EACZC,mBAAmB,EACnBC,gBAAiB,EAErB,CAGA,SAAS4E,EAAOC,GACd,OAAOA,EAAKH,IAAOG,EAA0B,IAAKA,EAAMH,IAAKJ,IAC/D,CAOA,SAASQ,EAAmBD,GAC1B,MACME,EAASzB,EADsB,WAApBuB,EAAK1F,WAC+B0F,EAAK7E,kBACpD,IAAE0E,KAAQM,GAAaH,EAE7B,MAAO,KADU,QAAoB,KAAWE,EAAQC,GACDN,MACzD,CAKA,SAASO,EAAgBC,GACvB,GAAc,OAAVA,GAAmC,iBAAVA,EAAsB,OAAOC,KAAKC,UAAUF,GACzE,GAAIG,MAAMC,QAAQJ,GAChB,MAAO,IAAMA,EAAMK,IAAIN,GAAiBO,KAAK,KAAO,IAEtD,MAAMC,EAAMP,EAEZ,MAAO,IADMtB,OAAO8B,KAAKD,GAAKE,OACZJ,IAAKK,GAAMT,KAAKC,UAAUQ,GAAK,IAAMX,EAAgBQ,EAAIG,KAAKJ,KAAK,KAAO,GAC9F,CAwBA,MAAMK,EAA2B,CAC/B,WAAY,CACV,OAAQ,aAAc,aAAc,UAAW,YAAa,kBAAmB,kBAC/E,aAAc,oBAAqB,cAAe,WAAY,mBAC9D,qBAAsB,cAAe,oBAAqB,UAAW,sBAAuB,mBAE9FpG,UAAW,CAAE,YAAa,WAAY,UAAW,oEACjDG,gBAAiB,CAAE,UAAW,iEAC9BT,WAAY,CAAE,YAAa,UAC3B6E,YAAa,CACX,gBAAiB,uBAEnBC,kBAAmB,CACjB,gBAAiB,uBAEnBC,QAAS,CACP,gBAAiB,uBAEnBC,gBAAiB,CACf,gBAAiB,wBAIf2B,EAA2B,CAC/B,WAAY,CACV,OAAQ,aAAc,UAAW,YAAa,kBAAmB,aAAc,oBAC/E,kBAAmB,eAErBrG,UAAW,CAAE,YAAa,WAAY,UAAW,oEACjDG,gBAAiB,CAAE,UAAW,iEAC9BT,WAAY,CAAE,YAAa,WAIvB4G,EAAgB,CAAC,OAAQ,UAAW,YAAa,kBAAmB,aAAc,oBAAqB,mBA4K7G,SAASC,GAAe,KAAEnB,EAAI,MAAEoB,EAAK,WAAEC,EAAU,SAAEC,EAAQ,SAAEC,EAAQ,SAAEC,EAAQ,SAAEC,IAC/E,MAAM/C,EAA+B,WAApBsB,EAAK1F,WAChB4F,EAASzB,EAA4BC,EAAUsB,EAAK7E,iBACpDuG,EAAWhD,EAAWsC,EAAiBC,EACvCU,EAAYjD,EAAW,SAAW,SAClCkD,GAAe5B,EAAKhG,MAAQ,cAAcoH,EAAQ,KAAKtI,QA6BvD,IAAE+G,KAAQM,GAAaH,EAE7B,OACE,uBAAK6B,UAAU,aACb,uBAAKA,UAAU,mBAAmBC,QAASP,EAAUQ,KAAK,SAAQ,gBAAgBT,GAChF,wBAAMO,UAAW,eAAcnD,EAAW,oBAAsB,sBAC7DiD,GAEH,wBAAME,UAAU,mBAAmBD,GACnC,wBAAMC,UAAU,oBAAoBP,EAAW,IAAW,KAC1D,0BACEO,UAAU,kBACVG,SAAUX,GAAc,EACxBS,QAAUG,IAAQA,EAAEC,kBAAmBT,KACvCvH,MAAOmH,GAAc,EAAI,oCAAsC,0BAAwB,WAK1FC,GACC,uBAAKO,UAAU,kBACb,gBAAC,KAAI,CACH3B,OAAQA,EACRwB,SAAUA,EACVvB,SAAUA,EACVgC,UAAW,KACXX,SArDV,SAA0BS,GACxB,MAAMG,EAAuBH,EAAE9B,SAC/B,GAAIiC,EAAK9H,aAAe0F,EAAK1F,WAAY,CACvC,MAGM+H,EAAyB,IAHE,WAApBD,EAAK9H,WACdwF,EAAwBsC,EAAKpI,MAC7B4F,EAAwBwC,EAAKpI,MACS6F,IAAKG,EAAKH,KACpD,IAAK,MAAMkB,KAAKG,OACEoB,IAAZF,EAAKrB,KAAqBsB,EAAmCtB,GAAKqB,EAAKrB,IAI7E,OAFAsB,EAAO/H,WAAa8H,EAAK9H,gBACzBkH,EAASa,EAEX,CAMA,MAAME,EAA2B,IAAKH,EAAMvC,IAAKG,EAAKH,MAC9CA,IAAK2C,KAASC,GAAMF,GACpB1C,IAAK6C,KAASC,GAAM3C,GAhQhC,SAA0ByC,EAA4BE,GACpD,MAAMC,EAAQ7D,OAAO8B,KAAK4B,GACpBI,EAAQ9D,OAAO8B,KAAK8B,GAC1B,GAAIC,EAAME,SAAWD,EAAMC,OAAU,OAAO,EAC5C,IAAK,MAAM/B,KAAK6B,EAAO,CACrB,IAAK7D,OAAOgE,UAAUC,eAAeC,KAAKN,EAAG5B,GAAM,OAAO,EAC1D,MAAMmC,EAAKT,EAAE1B,GACPoC,EAAKR,EAAE5B,GACb,GAAImC,IAAOC,EAAX,CACA,GAAW,OAAPD,GAAsB,OAAPC,GAA6B,iBAAPD,GAAiC,iBAAPC,EAInE,OAAO,EAHL,GAAI/C,EAAgB8C,KAAQ9C,EAAgB+C,GAAO,OAAO,CAFjC,CAM7B,CACA,OAAO,CACT,EAiPQC,CAAiBX,EAAGE,IACxBnB,EAASe,EACX,EA8BUc,SAAU,OACVC,cAAc,GAGd,8BAMZ,CAiRA,QA7QA,SAAkCC,GAChC,MAAOC,EAAaC,IAAkB,IAAAC,UAA2B,KAC1DC,EAAoBC,IAAyB,IAAAF,UAAiB,KAC9DG,EAA2BC,IAAgC,IAAAJ,WAAkB,IAC7EK,EAASC,IAAc,IAAAN,WAAS,IAChCO,EAAWC,IAAgB,IAAAR,UAAwB,OACnDS,EAAYC,IAAiB,IAAAV,UAA4B,OACzDW,EAAyBC,IAA8B,IAAAZ,UAAwB,OAC/Ea,EAAeC,IAAoB,IAAAd,UAAwB,IAC3De,EAASC,IAAc,IAAAhB,WAAS,GACjCiB,GAAY,IAAAC,SAAO,IAGzB,IAAAC,WAAU,MACRC,iBACE,IACE,MAAMC,QAAY1M,EAAS,GAAGkH,mBAC9B,GAAmB,MAAfwF,EAAIC,OACN,MAAM,IAAIC,MAAMnN,GAElB,IAAKiN,EAAIG,GAAM,MAAM,IAAID,MAAM,QAAQF,EAAIC,WAAWD,EAAII,cAC1D,MAAMC,QAAaL,EAAIM,OACvB,IAAKD,EAAKE,QAAW,MAAM,IAAIL,MAAMG,EAAKG,OAAS,gCAEnD,MAAMC,EAAMJ,EAAKK,eAAiB,CAAC,EACnC,IAAIC,EAEFA,EADElF,MAAMC,QAAQ+E,EAAIhC,cAAgBgC,EAAIhC,YAAYV,OAAS,EACtD0C,EAAIhC,YAAY9C,IAAKiF,GAAmC1F,EAAmBF,EAAO4F,KAChFH,EAAIlL,WACN,CAAC2F,EAAmBF,EAAOyF,KAE3B,CAAC5F,KAEV6D,EAAeiC,GACf9B,EAAwD,iBAA3B4B,EAAI7B,mBAAkC6B,EAAI7B,mBAAqB,IAC5FG,GAA+D,IAAlC0B,EAAI3B,2BACjCW,EAAiB,GACjBE,GAAW,EACb,CAAE,MAAOkB,GACP1B,EAAa0B,aAAeX,MAAQW,EAAIC,QAAUhN,OAAO+M,GAC3D,C,QACE5B,GAAW,EACb,CACF,CACA8B,IACC,IAGH,MAAMC,EAAcvC,EACjBwC,OAAQL,GAAuB,WAAjBA,EAAErL,YAChBoG,IAAKiF,GAAMA,EAAElL,SACVwL,EAAmB,IAAIC,IAC3BH,EAAYC,OAAO,CAACG,EAAGC,IAAML,EAAYM,QAAQF,KAAOC,IAI1D,SAASE,IACP5B,GAAW,GACXN,EAAc,MACdE,EAA2B,KAC7B,CAuCA,MAAMiC,GAAa,IAAAC,aAAY1B,UAC7B,IAAIH,EAAU8B,QAAd,CACA,GAA2B,IAAvBjD,EAAYV,OAMd,OALAwB,EAA2B,2DAC3BF,EAAc,CACZnK,KAAM,QACN4L,QAAS,qEAMb,GADAvB,EAA2B,MACvB2B,EAAiBS,KAAO,EAC1BtC,EAAc,CACZnK,KAAM,QACN4L,QAAS,oCAAoC,IAAII,GAAkBtF,KAAK,uDAH5E,CAQAgE,EAAU8B,SAAU,EACpBrC,EAAc,CAAEnK,KAAM,SAAU4L,QAAS,4BACzC,IACE,MAAMc,EAAUnD,EAAY9C,IAAI,EAAGb,SAAQ+G,KAAWA,GAChD7B,QAAY1M,EAAS,GAAGkH,kBAA0B,CACtDsH,OAAQ,OACRrN,QAAS,CAAE,eAAgB,oBAC3B4L,KAAM9E,KAAKC,UAAU,CACnBiD,YAAamD,EACbhD,mBAAoBA,EACpBE,0BAA2BA,MAG/B,GAAmB,MAAfkB,EAAIC,OACN,MAAM,IAAIC,MAAMnN,GAElB,MAAMsN,QAAaL,EAAIM,OACvB,IAAIN,EAAIG,KAAME,EAAKE,QAIjB,MAAM,IAAIL,MAAMG,EAAKG,OAAS,kBAH9BnB,EAAc,CAAEnK,KAAM,UAAW4L,QAAST,EAAKS,SAAW,8CAC1DnB,GAAW,EAIf,CAAE,MAAOkB,GACPxB,EAAc,CAAEnK,KAAM,QAAS4L,QAASD,aAAeX,MAAQW,EAAIC,QAAUhN,OAAO+M,IACtF,C,QACEjB,EAAU8B,SAAU,CACtB,CA7BA,CAjBiC,GA+ChC,CAACjD,EAAayC,EAAkBtC,EAAoBE,IAGvD,OAAIE,EACK,uBAAK+C,MAAO,CAAEC,QAAS,OAAQC,UAAW,WAAU,4BAGzD/C,EAEA,uBAAK6C,MAAO,CAAEC,QAAS,SACrB,uBAAKlF,UAAU,+BACb,8D,IAA+CoC,IAOrD,uBAAKpC,UAAU,eACb,6BAvZM,uzHAyZL4C,GAAgC,WAArBN,GAAYlK,MACtB,uBAAK4H,UAAU,qBACb,iCACA,0DAIHsC,GACC,uBAAKtC,UAAW,0BAA6C,WAApBsC,EAAWlK,KAAoB,SAA+B,YAApBkK,EAAWlK,KAAqB,UAAY,UAC5HkK,EAAW0B,SAKhB,uBAAKhE,UAAU,wBACb,sDACA,uBAAKA,UAAU,oBACb,yBAAOoF,QAAQ,mBAAiB,wBAChC,yBACEC,GAAG,kBACHjN,KAAK,WACLoG,MAAOsD,EACPwD,YAAY,8BACZ3F,SAAWS,IAAQ2B,EAAsB3B,EAAEmF,OAAO/G,OAAQiG,KAC1De,aAAa,iBAEf,uBAAKxF,UAAU,mB,sHAEuB,IACpC,kE,sFAIJ,uBAAKA,UAAU,oBACb,6BACE,yBACE5H,KAAK,WACLqN,QAASzD,EACTrC,SAAWS,IAAQ6B,EAA6B7B,EAAEmF,OAAOE,SAAUhB,O,gCAIvE,uBAAKzE,UAAU,mBAAiB,2KAOnC2B,EAAY9C,IAAI,CAACV,EAAMuH,IACtB,uBAAKC,IAAKxH,EAAKH,KACb,gBAACsB,EAAc,CACbnB,KAAMA,EACNoB,MAAOmG,EACPlG,WAAYmC,EAAYV,OACxBxB,SAAUiD,IAAkBgD,EAC5BhG,SAAU,IAjIpB,SAAsBgG,GACpB/C,EAAkBiD,GAAUA,IAASF,EAAM,KAAOA,EACpD,CA+H0BG,CAAaH,GAC7B/F,SAAWmG,GAnKrB,SAA0BJ,EAAaI,GACrClE,EAAgBgE,GAASA,EAAK/G,IAAI,CAACiF,EAAGS,IAAOA,IAAMmB,EAAMI,EAAOhC,IAChEW,GACF,CAgK8CsB,CAAiBL,EAAKI,GAC1DlG,SAAU,IA7IpB,SAA0B8F,GACxB9D,EAAgBgE,IACd,GAAIA,EAAK3E,QAAU,EAAG,OAAO2E,EAC7B,MAAMrF,EAAOqF,EAAKzB,OAAO,CAAC6B,EAAGzB,IAAMA,IAAMmB,GAEzC,OADA/C,EAAkBsD,GAAmC,OAAjBA,GAAyBA,GAAgBP,GAAOO,EAAe,EAAIA,EAAe,EAAIA,GACnH1F,IAETkE,GACF,CAqI0ByB,CAAiBR,KAEd,WAApBvH,EAAK1F,YAA2B2L,EAAiB+B,IAAIhI,EAAKvF,UACzD,uBAAKoH,UAAU,iB,QACP7B,EAAKvF,Q,kFAMnB,uBAAKoH,UAAU,gBACb,0BAAQA,UAAU,8BAA8BC,QA1KtD,WACE2B,EAAgBgE,IACd,MAAMrF,EAAO,IAAIqF,EAAM3H,EAAwB,UAAU2H,EAAK3E,OAAS,MAEvE,OADA0B,EAAiBpC,EAAKU,OAAS,GACxBV,IAETkE,GACF,GAmKwE,gBAGlE,0BAAQzE,UAAU,8BAA8BC,QApKtD,WACE2B,EAAgBgE,IACd,MAAMrF,EAAO,IAAIqF,EAAM7H,EAAwB,UAAU6H,EAAK3E,OAAS,MAEvE,OADA0B,EAAiBpC,EAAKU,OAAS,GACxBV,IAETkE,GACF,GA6JwE,gBAGlE,0BACEzE,UAAU,4BACVC,QAASyE,EACTvE,SAAWmC,GAAkC,WAApBA,EAAWlK,MAA6C,IAAvBuJ,EAAYV,QAErE2B,EAAU,eAAiB,sBAE7BJ,GACC,wBAAMyC,MAAO,CAAEmB,MAAO,UAAWC,SAAU,UAAWC,WAAY,MAC/D9D,GAGL,wBAAMyC,MAAO,CAAEoB,SAAU,UAAWD,MAAO,YACxCzE,EAAYV,O,cAA0C,IAAvBU,EAAYV,OAAe,IAAM,GAChE,MACAU,EAAYwC,OAAQL,GAAuB,WAAjBA,EAAErL,YAAyBwI,O,UACW,IAAhEU,EAAYwC,OAAQL,GAAuB,WAAjBA,EAAErL,YAAyBwI,OAAe,IAAM,GAC1E,KACAU,EAAYwC,OAAQL,GAAuB,WAAjBA,EAAErL,YAAyBwI,O,UACW,IAAhEU,EAAYwC,OAAQL,GAAuB,WAAjBA,EAAErL,YAAyBwI,OAAe,IAAM,KAKrF,C","sources":["webpack://signalk-edge-link/./src/webapp/utils/apiFetch.ts","webpack://signalk-edge-link/./src/shared/crypto-constants.ts","webpack://signalk-edge-link/./src/shared/connection-schema.ts","webpack://signalk-edge-link/./src/webapp/components/PluginConfigurationPanel.tsx"],"sourcesContent":["/// <reference lib=\"dom\" />\r\n\r\nexport const MANAGEMENT_TOKEN_ERROR_MESSAGE = \"Management token required/invalid.\";\r\n\r\ninterface AuthConfig {\r\n token: string | null;\r\n localStorageKey: string;\r\n queryParam: string;\r\n includeTokenInQuery: boolean;\r\n headerMode: string;\r\n}\r\n\r\ndeclare global {\r\n interface Window {\r\n __EDGE_LINK_AUTH__?: Partial<AuthConfig>;\r\n }\r\n}\r\n\r\nconst DEFAULT_AUTH_CONFIG: AuthConfig = {\r\n token: null,\r\n localStorageKey: \"signalkEdgeLinkManagementToken\",\r\n queryParam: \"edgeLinkToken\",\r\n // Default to false: query-parameter tokens leak into browser history, server\r\n // access logs, and Referer headers. Set includeTokenInQuery: true in\r\n // window.__EDGE_LINK_AUTH__ only when you explicitly need URL-based auth.\r\n includeTokenInQuery: false,\r\n headerMode: \"both\"\r\n};\r\n\r\nfunction readRuntimeAuthConfig(): AuthConfig {\r\n if (typeof window === \"undefined\") {\r\n return DEFAULT_AUTH_CONFIG;\r\n }\r\n\r\n const runtime = window.__EDGE_LINK_AUTH__;\r\n if (!runtime || typeof runtime !== \"object\") {\r\n return DEFAULT_AUTH_CONFIG;\r\n }\r\n\r\n return { ...DEFAULT_AUTH_CONFIG, ...runtime };\r\n}\r\n\r\nfunction resolveToken(config: AuthConfig): string {\r\n if (config.token) {\r\n return String(config.token).trim();\r\n }\r\n\r\n if (typeof window === \"undefined\") {\r\n return \"\";\r\n }\r\n\r\n // SECURITY NOTE: Query parameter tokens can leak into browser history, server\r\n // access logs, and Referer headers. Prefer localStorage or\r\n // window.__EDGE_LINK_AUTH__.token for production deployments. Set\r\n // includeTokenInQuery: false in __EDGE_LINK_AUTH__ to disable this path.\r\n if (config.includeTokenInQuery && config.queryParam) {\r\n const tokenFromQuery = new URLSearchParams(window.location.search).get(config.queryParam);\r\n if (tokenFromQuery) {\r\n return tokenFromQuery.trim();\r\n }\r\n }\r\n\r\n if (config.localStorageKey && window.localStorage) {\r\n const tokenFromStorage = window.localStorage.getItem(config.localStorageKey);\r\n if (tokenFromStorage) {\r\n return tokenFromStorage.trim();\r\n }\r\n }\r\n\r\n return \"\";\r\n}\r\n\r\nfunction attachAuthHeaders(headers: Headers, token: string, headerMode: string): Headers {\r\n if (!token) {\r\n return headers;\r\n }\r\n\r\n const normalizedMode = (headerMode || \"both\").toLowerCase();\r\n if (\r\n normalizedMode === \"x-edge-link-token\" ||\r\n normalizedMode === \"token\" ||\r\n normalizedMode === \"both\"\r\n ) {\r\n headers.set(\"X-Edge-Link-Token\", token);\r\n }\r\n if (\r\n normalizedMode === \"authorization\" ||\r\n normalizedMode === \"bearer\" ||\r\n normalizedMode === \"both\"\r\n ) {\r\n headers.set(\"Authorization\", `Bearer ${token}`);\r\n }\r\n return headers;\r\n}\r\n\r\nexport function getAuthToken(): string {\r\n const config = readRuntimeAuthConfig();\r\n return resolveToken(config);\r\n}\r\n\r\nexport function getTokenHelpText(): string {\r\n const config = readRuntimeAuthConfig();\r\n const modeText =\r\n config.headerMode && String(config.headerMode).toLowerCase() === \"authorization\"\r\n ? \"Authorization: Bearer <token>\"\r\n : config.headerMode && String(config.headerMode).toLowerCase() === \"x-edge-link-token\"\r\n ? \"X-Edge-Link-Token\"\r\n : \"X-Edge-Link-Token and Authorization: Bearer <token>\";\r\n\r\n return `The server-side token is configured in plugin settings (managementApiToken) or via the SIGNALK_EDGE_LINK_MANAGEMENT_TOKEN environment variable. To authenticate from the browser, provide the token using window.__EDGE_LINK_AUTH__.token, query parameter \"${config.queryParam}\", or localStorage key \"${config.localStorageKey}\". Requests send ${modeText} when a token is available.`;\r\n}\r\n\r\nexport function apiFetch(input: string | Request, init: RequestInit = {}): Promise<Response> {\r\n const config = readRuntimeAuthConfig();\r\n const token = resolveToken(config);\r\n const headers = new Headers(init.headers || {});\r\n attachAuthHeaders(headers, token, config.headerMode);\r\n\r\n return fetch(input, {\r\n ...init,\r\n headers\r\n });\r\n}\r\n","\"use strict\";\r\n\r\n/**\r\n * Shared crypto constants that must stay in sync between the backend crypto\r\n * module and any UI copy that describes key-derivation behaviour. Kept under\r\n * `src/shared/` so both the server-side build and the webapp bundle can\r\n * reference the same value.\r\n */\r\n\r\n/**\r\n * PBKDF2-SHA256 iteration count used by {@link deriveKeyFromPassphrase} and\r\n * by the opt-in 32-char ASCII key stretching path in {@link normalizeKey}.\r\n *\r\n * Tuned to the NIST SP 800-132 recommendation (≥ 600,000) and takes roughly\r\n * ~300 ms on modern server hardware. The derived key is cached per-process\r\n * so the cost is paid at most once per unique (key, salt) pair.\r\n */\r\nexport const PBKDF2_ITERATIONS = 600_000;\r\n","/**\r\n * Single source of truth for the connection configuration schema.\r\n *\r\n * Both the backend `plugin.schema` in `src/index.ts` (used by Signal K's\r\n * default admin UI and served via the `/plugin-schema` route for default\r\n * extraction) and the frontend RJSF form in\r\n * `src/webapp/components/PluginConfigurationPanel.tsx` consume the fragments\r\n * exported here. Adding or editing a connection field must happen in this\r\n * module; the two consumers then render it identically.\r\n *\r\n * The fragments are typed as plain `Record<string, unknown>` so they can be\r\n * imported by both the server-side TypeScript build and the webapp build\r\n * without pulling `@rjsf/utils` into the server bundle. The webapp casts\r\n * results to `RJSFSchema` at call sites.\r\n */\r\n\r\nimport { PBKDF2_ITERATIONS } from \"./crypto-constants\";\r\n\r\nexport type SchemaFragment = Record<string, unknown>;\r\n\r\n// ── Common (client + server) ──────────────────────────────────────────────────\r\n\r\nexport const commonConnectionProperties: Record<string, SchemaFragment> = {\r\n name: {\r\n type: \"string\",\r\n title: \"Connection Name\",\r\n description:\r\n \"Human-readable label for this connection (e.g. 'Shore Server', 'Sat Client'). Used to namespace config files and Signal K metrics paths.\",\r\n default: \"connection\",\r\n maxLength: 40\r\n },\r\n serverType: {\r\n type: \"string\",\r\n title: \"Operation Mode\",\r\n description: \"Select Server to receive data, or Client to send data.\",\r\n default: \"client\",\r\n oneOf: [\r\n { const: \"server\", title: \"Server Mode – Receive Data\" },\r\n { const: \"client\", title: \"Client Mode – Send Data\" }\r\n ]\r\n },\r\n udpPort: {\r\n type: \"number\",\r\n title: \"UDP Port\",\r\n description: \"UDP port for data transmission (must match on both ends).\",\r\n default: 4446,\r\n minimum: 1024,\r\n maximum: 65535\r\n },\r\n secretKey: {\r\n type: \"string\",\r\n title: \"Encryption Key\",\r\n description:\r\n \"32-byte secret key: 32-character ASCII, 64-character hex, or 44-character base64.\",\r\n minLength: 32,\r\n maxLength: 64,\r\n pattern: \"^(?:.{32}|[0-9a-fA-F]{64}|[A-Za-z0-9+/]{43}=?)$\"\r\n },\r\n stretchAsciiKey: {\r\n type: \"boolean\",\r\n title: \"Stretch 32-char ASCII Key (PBKDF2)\",\r\n description: `When the secretKey is 32-character ASCII, route it through PBKDF2-SHA256 (${PBKDF2_ITERATIONS.toLocaleString(\"en-US\")} iterations) to raise it to full 256-bit AES strength. Hex and base64 keys are unaffected. BOTH ENDS OF THE CONNECTION MUST USE THE SAME SETTING — otherwise authentication will fail and every packet will be dropped.`,\r\n default: false\r\n },\r\n useMsgpack: {\r\n type: \"boolean\",\r\n title: \"Use MessagePack\",\r\n description: \"Binary serialization for smaller payloads (must match on both ends).\",\r\n default: false\r\n },\r\n usePathDictionary: {\r\n type: \"boolean\",\r\n title: \"Use Path Dictionary\",\r\n description: \"Encode paths as numeric IDs for bandwidth savings (must match on both ends).\",\r\n default: false\r\n },\r\n protocolVersion: {\r\n type: \"number\",\r\n title: \"Protocol Version\",\r\n description:\r\n \"v1: encrypted UDP. v2 adds reliable delivery and metrics. v3 keeps the v2 data path and authenticates control packets (ACK/NAK/HEARTBEAT/HELLO). Must match on both ends.\",\r\n default: 1,\r\n oneOf: [\r\n { const: 1, title: \"v1 – Standard encrypted UDP\" },\r\n { const: 2, title: \"v2 – Reliability, congestion control, bonding, metrics\" },\r\n { const: 3, title: \"v3 - v2 features with authenticated control packets\" }\r\n ]\r\n }\r\n};\r\n\r\n// ── Client-only transport / reachability fields ───────────────────────────────\r\n\r\nexport const clientTransportProperties: Record<string, SchemaFragment> = {\r\n udpAddress: {\r\n type: \"string\",\r\n title: \"Server Address\",\r\n description: \"IP address or hostname of the remote Signal K endpoint.\",\r\n default: \"127.0.0.1\"\r\n },\r\n helloMessageSender: {\r\n type: \"integer\",\r\n title: \"Heartbeat Interval (seconds)\",\r\n description: \"Send periodic heartbeat messages to keep NAT/firewall mappings alive.\",\r\n default: 60,\r\n minimum: 10,\r\n maximum: 3600\r\n },\r\n testAddress: {\r\n type: \"string\",\r\n title: \"Connectivity Test Address\",\r\n description: \"Host used for reachability checks (e.g. 8.8.8.8).\",\r\n default: \"127.0.0.1\"\r\n },\r\n testPort: {\r\n type: \"number\",\r\n title: \"Connectivity Test Port\",\r\n description: \"Port used for reachability checks (e.g. 53, 80, or 443).\",\r\n default: 80,\r\n minimum: 1,\r\n maximum: 65535\r\n },\r\n pingIntervalTime: {\r\n type: \"number\",\r\n title: \"Check Interval (minutes)\",\r\n description: \"Frequency of network reachability checks.\",\r\n default: 1,\r\n minimum: 0.1,\r\n maximum: 60\r\n },\r\n heartbeatInterval: {\r\n type: \"number\",\r\n title: \"NAT Keepalive Heartbeat Interval (ms)\",\r\n description:\r\n \"v2/v3 only. How often to send UDP heartbeat packets for NAT traversal. Typical NAT timeouts range from 30s to 120s.\",\r\n default: 25000,\r\n minimum: 5000,\r\n maximum: 120000\r\n }\r\n};\r\n\r\n// ── v2/v3 reliability (client pipeline — retransmit queue) ────────────────────\r\n\r\nexport const clientReliabilityProperty: SchemaFragment = {\r\n type: \"object\",\r\n title: \"Reliability Settings (v2/v3 only)\",\r\n description:\r\n \"Requires Protocol v2 or v3. Controls retransmit queue behavior and packet retry limits.\",\r\n properties: {\r\n retransmitQueueSize: {\r\n type: \"number\",\r\n title: \"Retransmit Queue Size\",\r\n description: \"Maximum number of sent packets stored for potential retransmission.\",\r\n default: 5000,\r\n minimum: 100,\r\n maximum: 50000\r\n },\r\n maxRetransmits: {\r\n type: \"number\",\r\n title: \"Max Retransmit Attempts\",\r\n description: \"Maximum resend attempts before a packet is dropped from the retransmit queue.\",\r\n default: 3,\r\n minimum: 1,\r\n maximum: 20\r\n },\r\n retransmitMaxAge: {\r\n type: \"number\",\r\n title: \"Retransmit Max Age (ms)\",\r\n description: \"Expire stale unacknowledged packets older than this age.\",\r\n default: 120000,\r\n minimum: 1000,\r\n maximum: 300000\r\n },\r\n retransmitMinAge: {\r\n type: \"number\",\r\n title: \"Retransmit Min Age (ms)\",\r\n description: \"Minimum packet age before expiration is allowed.\",\r\n default: 10000,\r\n minimum: 200,\r\n maximum: 30000\r\n },\r\n retransmitRttMultiplier: {\r\n type: \"number\",\r\n title: \"RTT Expiry Multiplier\",\r\n description: \"Dynamic expiry age = RTT × this multiplier.\",\r\n default: 12,\r\n minimum: 2,\r\n maximum: 20\r\n },\r\n ackIdleDrainAge: {\r\n type: \"number\",\r\n title: \"ACK Idle Drain Age (ms)\",\r\n description: \"If ACKs are idle longer than this, expiry becomes more aggressive.\",\r\n default: 20000,\r\n minimum: 500,\r\n maximum: 30000\r\n },\r\n forceDrainAfterAckIdle: {\r\n type: \"boolean\",\r\n title: \"Force Drain After ACK Idle\",\r\n description: \"When enabled, clear retransmit queue if no ACKs arrive for too long.\",\r\n default: false\r\n },\r\n forceDrainAfterMs: {\r\n type: \"number\",\r\n title: \"Force Drain Timeout (ms)\",\r\n description: \"ACK idle duration before force-draining retransmit queue to zero.\",\r\n default: 45000,\r\n minimum: 2000,\r\n maximum: 120000\r\n },\r\n recoveryBurstEnabled: {\r\n type: \"boolean\",\r\n title: \"Recovery Burst Enabled\",\r\n description: \"When ACKs return after outage, rapidly retransmit queued packets to catch up.\",\r\n default: true\r\n },\r\n recoveryBurstSize: {\r\n type: \"number\",\r\n title: \"Recovery Burst Size\",\r\n description: \"Max queued packets to retransmit per recovery burst cycle.\",\r\n default: 100,\r\n minimum: 10,\r\n maximum: 1000\r\n },\r\n recoveryBurstIntervalMs: {\r\n type: \"number\",\r\n title: \"Recovery Burst Interval (ms)\",\r\n description: \"Interval between recovery burst cycles while backlog exists.\",\r\n default: 200,\r\n minimum: 50,\r\n maximum: 5000\r\n },\r\n recoveryAckGapMs: {\r\n type: \"number\",\r\n title: \"Recovery ACK Gap (ms)\",\r\n description: \"Minimum ACK silence before triggering fast recovery bursts.\",\r\n default: 4000,\r\n minimum: 500,\r\n maximum: 120000\r\n }\r\n }\r\n};\r\n\r\n// ── v2/v3 reliability (server pipeline — ACK/NAK timing) ──────────────────────\r\n\r\nexport const serverReliabilityProperty: SchemaFragment = {\r\n type: \"object\",\r\n title: \"Reliability Settings (v2/v3 only)\",\r\n description: \"Requires Protocol v2 or v3. Controls ACK/NAK timing for reliable delivery.\",\r\n properties: {\r\n ackInterval: {\r\n type: \"number\",\r\n title: \"ACK Interval (ms)\",\r\n description: \"How often server sends cumulative ACK updates.\",\r\n default: 100,\r\n minimum: 20,\r\n maximum: 5000\r\n },\r\n ackResendInterval: {\r\n type: \"number\",\r\n title: \"ACK Resend Interval (ms)\",\r\n description: \"Re-send duplicate ACK periodically to recover from lost ACK packets.\",\r\n default: 1000,\r\n minimum: 100,\r\n maximum: 10000\r\n },\r\n nakTimeout: {\r\n type: \"number\",\r\n title: \"NAK Timeout (ms)\",\r\n description: \"Delay before requesting retransmission for missing sequence numbers.\",\r\n default: 100,\r\n minimum: 20,\r\n maximum: 5000\r\n }\r\n }\r\n};\r\n\r\n// ── v2/v3 congestion control (client) ─────────────────────────────────────────\r\n\r\nexport const congestionControlProperty: SchemaFragment = {\r\n type: \"object\",\r\n title: \"Dynamic Congestion Control (v2/v3 only)\",\r\n description:\r\n \"Requires Protocol v2 or v3. AIMD algorithm to dynamically adjust send rate based on network conditions.\",\r\n properties: {\r\n enabled: {\r\n type: \"boolean\",\r\n title: \"Enable Congestion Control\",\r\n description: \"Automatically adjust delta timer based on RTT and packet loss.\",\r\n default: false\r\n },\r\n targetRTT: {\r\n type: \"number\",\r\n title: \"Target RTT (ms)\",\r\n description: \"RTT threshold above which send rate is reduced.\",\r\n default: 200,\r\n minimum: 50,\r\n maximum: 2000\r\n },\r\n nominalDeltaTimer: {\r\n type: \"number\",\r\n title: \"Nominal Delta Timer (ms)\",\r\n description: \"Preferred steady-state send interval.\",\r\n default: 1000,\r\n minimum: 100,\r\n maximum: 10000\r\n },\r\n minDeltaTimer: {\r\n type: \"number\",\r\n title: \"Minimum Delta Timer (ms)\",\r\n description: \"Fastest allowed send interval.\",\r\n default: 100,\r\n minimum: 50,\r\n maximum: 1000\r\n },\r\n maxDeltaTimer: {\r\n type: \"number\",\r\n title: \"Maximum Delta Timer (ms)\",\r\n description: \"Slowest allowed send interval.\",\r\n default: 5000,\r\n minimum: 1000,\r\n maximum: 30000\r\n }\r\n }\r\n};\r\n\r\n// ── v2/v3 connection bonding (client) ─────────────────────────────────────────\r\n\r\nexport const bondingProperty: SchemaFragment = {\r\n type: \"object\",\r\n title: \"Connection Bonding (v2/v3 only)\",\r\n description:\r\n \"Requires Protocol v2 or v3. Dual-link bonding with automatic failover between primary and backup connections.\",\r\n properties: {\r\n enabled: {\r\n type: \"boolean\",\r\n title: \"Enable Connection Bonding\",\r\n description: \"Enable dual-link bonding with automatic failover.\",\r\n default: false\r\n },\r\n mode: {\r\n type: \"string\",\r\n title: \"Bonding Mode\",\r\n description: \"Bonding operating mode.\",\r\n default: \"main-backup\",\r\n oneOf: [\r\n {\r\n const: \"main-backup\",\r\n title: \"Main/Backup – Failover to backup when primary degrades\"\r\n }\r\n ]\r\n },\r\n primary: {\r\n type: \"object\",\r\n title: \"Primary Link\",\r\n description: \"Primary connection (e.g. LTE modem).\",\r\n properties: {\r\n address: { type: \"string\", title: \"Server Address\", default: \"127.0.0.1\" },\r\n port: {\r\n type: \"number\",\r\n title: \"UDP Port\",\r\n default: 4446,\r\n minimum: 1024,\r\n maximum: 65535\r\n },\r\n interface: {\r\n type: \"string\",\r\n title: \"Bind Interface (optional)\",\r\n description: \"Network interface IP to bind to.\"\r\n }\r\n }\r\n },\r\n backup: {\r\n type: \"object\",\r\n title: \"Backup Link\",\r\n description: \"Backup connection (e.g. Starlink, satellite).\",\r\n properties: {\r\n address: { type: \"string\", title: \"Server Address\", default: \"127.0.0.1\" },\r\n port: {\r\n type: \"number\",\r\n title: \"UDP Port\",\r\n default: 4447,\r\n minimum: 1024,\r\n maximum: 65535\r\n },\r\n interface: {\r\n type: \"string\",\r\n title: \"Bind Interface (optional)\",\r\n description: \"Network interface IP to bind to.\"\r\n }\r\n }\r\n },\r\n failover: {\r\n type: \"object\",\r\n title: \"Failover Thresholds\",\r\n description: \"Configure when failover is triggered.\",\r\n properties: {\r\n rttThreshold: {\r\n type: \"number\",\r\n title: \"RTT Threshold (ms)\",\r\n default: 500,\r\n minimum: 100,\r\n maximum: 5000\r\n },\r\n lossThreshold: {\r\n type: \"number\",\r\n title: \"Packet Loss Threshold (0-1)\",\r\n default: 0.1,\r\n minimum: 0.01,\r\n maximum: 0.5\r\n },\r\n healthCheckInterval: {\r\n type: \"number\",\r\n title: \"Health Check Interval (ms)\",\r\n default: 1000,\r\n minimum: 500,\r\n maximum: 10000\r\n },\r\n failbackDelay: {\r\n type: \"number\",\r\n title: \"Failback Delay (ms)\",\r\n default: 30000,\r\n minimum: 5000,\r\n maximum: 300000\r\n },\r\n heartbeatTimeout: {\r\n type: \"number\",\r\n title: \"Heartbeat Timeout (ms)\",\r\n default: 5000,\r\n minimum: 1000,\r\n maximum: 30000\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\n// ── Client-only notifications toggle ──────────────────────────────────────────\r\n\r\nexport const enableNotificationsProperty: SchemaFragment = {\r\n type: \"boolean\",\r\n title: \"Enable Signal K Notifications\",\r\n description: \"Emit Signal K notifications for alerts and failover events.\",\r\n default: false\r\n};\r\n\r\n// ── v2/v3 monitoring alert thresholds (client) ────────────────────────────────\r\n\r\nexport const alertThresholdsProperty: SchemaFragment = {\r\n type: \"object\",\r\n title: \"Monitoring Alert Thresholds (v2/v3 only)\",\r\n description: \"Customize warning/critical thresholds for network monitoring alerts.\",\r\n properties: {\r\n rtt: {\r\n type: \"object\",\r\n title: \"RTT Thresholds\",\r\n properties: {\r\n warning: { type: \"number\", title: \"Warning RTT (ms)\", default: 300 },\r\n critical: { type: \"number\", title: \"Critical RTT (ms)\", default: 800 }\r\n }\r\n },\r\n packetLoss: {\r\n type: \"object\",\r\n title: \"Packet Loss Thresholds\",\r\n properties: {\r\n warning: { type: \"number\", title: \"Warning Loss Ratio\", default: 0.03 },\r\n critical: { type: \"number\", title: \"Critical Loss Ratio\", default: 0.1 }\r\n }\r\n },\r\n retransmitRate: {\r\n type: \"object\",\r\n title: \"Retransmit Rate Thresholds\",\r\n properties: {\r\n warning: { type: \"number\", title: \"Warning Retransmit Ratio\", default: 0.05 },\r\n critical: { type: \"number\", title: \"Critical Retransmit Ratio\", default: 0.15 }\r\n }\r\n },\r\n jitter: {\r\n type: \"object\",\r\n title: \"Jitter Thresholds\",\r\n properties: {\r\n warning: { type: \"number\", title: \"Warning Jitter (ms)\", default: 100 },\r\n critical: { type: \"number\", title: \"Critical Jitter (ms)\", default: 300 }\r\n }\r\n },\r\n queueDepth: {\r\n type: \"object\",\r\n title: \"Queue Depth Thresholds\",\r\n properties: {\r\n warning: { type: \"number\", title: \"Warning Queue Depth\", default: 100 },\r\n critical: { type: \"number\", title: \"Critical Queue Depth\", default: 500 }\r\n }\r\n }\r\n }\r\n};\r\n\r\n// ── Builder consumed by the backend (`plugin.schema` in src/index.ts) ─────────\r\n\r\n/**\r\n * Build the `connections[]` item schema used by Signal K's default admin UI\r\n * and served via `GET /plugin-schema`. Client-only fields live under\r\n * `dependencies.serverType.oneOf` so they appear only in client mode.\r\n */\r\nexport function buildConnectionItemSchema(): SchemaFragment {\r\n return {\r\n type: \"object\",\r\n title: \"Connection\",\r\n required: [\"serverType\", \"udpPort\", \"secretKey\"],\r\n properties: { ...commonConnectionProperties },\r\n dependencies: {\r\n serverType: {\r\n oneOf: [\r\n {\r\n properties: {\r\n serverType: { enum: [\"server\"] },\r\n reliability: serverReliabilityProperty\r\n }\r\n },\r\n {\r\n properties: {\r\n serverType: { enum: [\"client\"] },\r\n ...clientTransportProperties,\r\n reliability: clientReliabilityProperty,\r\n congestionControl: congestionControlProperty,\r\n bonding: bondingProperty,\r\n enableNotifications: enableNotificationsProperty,\r\n alertThresholds: alertThresholdsProperty\r\n },\r\n required: [\"udpAddress\", \"testAddress\", \"testPort\"]\r\n }\r\n ]\r\n }\r\n }\r\n };\r\n}\r\n\r\n// ── Builder consumed by the webapp (PluginConfigurationPanel.tsx) ─────────────\r\n\r\n/**\r\n * Build the flat per-connection schema consumed by the webapp RJSF form.\r\n * Unlike the backend variant this is a flat object that is rebuilt whenever\r\n * the user toggles `serverType` or `protocolVersion` so RJSF re-renders with\r\n * the right subset of fields.\r\n */\r\nexport function buildWebappConnectionSchema(\r\n isClient: boolean,\r\n protocolVersion: number | undefined\r\n): SchemaFragment {\r\n const isReliableProtocol = Number(protocolVersion) >= 2;\r\n const props: Record<string, SchemaFragment> = { ...commonConnectionProperties };\r\n const required = [\"serverType\", \"udpPort\", \"secretKey\"];\r\n\r\n if (isClient) {\r\n Object.assign(props, clientTransportProperties);\r\n props.enableNotifications = enableNotificationsProperty;\r\n required.push(\"udpAddress\", \"testAddress\", \"testPort\");\r\n if (isReliableProtocol) {\r\n props.reliability = clientReliabilityProperty;\r\n props.congestionControl = congestionControlProperty;\r\n props.bonding = bondingProperty;\r\n props.alertThresholds = alertThresholdsProperty;\r\n }\r\n } else if (isReliableProtocol) {\r\n props.reliability = serverReliabilityProperty;\r\n }\r\n\r\n return { type: \"object\", required, properties: props };\r\n}\r\n","import React from 'react';\r\nimport { useState, useEffect, useCallback, useRef } from 'react';\r\nimport Form from \"@rjsf/core\";\r\nimport validator from \"@rjsf/validator-ajv8\";\r\nimport { RJSFSchema, UiSchema, getDefaultFormState } from \"@rjsf/utils\";\r\nimport { apiFetch, MANAGEMENT_TOKEN_ERROR_MESSAGE } from \"../utils/apiFetch\";\r\nimport { buildWebappConnectionSchema } from \"../../shared/connection-schema\";\r\n\r\nconst API_BASE = \"/plugins/signalk-edge-link\";\r\n\r\n// ── Stable ID helper ──────────────────────────────────────────────────────────\r\n// Each connection object carries a frontend-only `_id` for use as React key.\r\n// It is stripped before the array is POSTed to the backend.\r\n\r\nlet _idSeq = 0;\r\nfunction makeId(): string { return `skel-${Date.now()}-${++_idSeq}`; }\r\n\r\n// ── Types ─────────────────────────────────────────────────────────────────────\r\n\r\ninterface ConnectionData {\r\n _id: string;\r\n name?: string;\r\n serverType?: string;\r\n udpPort?: number;\r\n secretKey?: string;\r\n stretchAsciiKey?: boolean;\r\n useMsgpack?: boolean;\r\n usePathDictionary?: boolean;\r\n enableNotifications?: boolean;\r\n protocolVersion?: number;\r\n udpAddress?: string;\r\n helloMessageSender?: number;\r\n testAddress?: string;\r\n testPort?: number;\r\n pingIntervalTime?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface SaveStatus {\r\n type: \"saving\" | \"success\" | \"error\";\r\n message: string;\r\n}\r\n\r\n// ── Default config factories ──────────────────────────────────────────────────\r\n\r\nfunction defaultClientConnection(name?: string): ConnectionData {\r\n return {\r\n _id: makeId(),\r\n name: name || \"client\",\r\n serverType: \"client\",\r\n udpPort: 4446,\r\n secretKey: \"\",\r\n stretchAsciiKey: false,\r\n useMsgpack: false,\r\n usePathDictionary: false,\r\n enableNotifications: false,\r\n protocolVersion: 1,\r\n udpAddress: \"127.0.0.1\",\r\n helloMessageSender: 60,\r\n testAddress: \"127.0.0.1\",\r\n testPort: 80,\r\n pingIntervalTime: 1\r\n };\r\n}\r\n\r\nfunction defaultServerConnection(name?: string): ConnectionData {\r\n return {\r\n _id: makeId(),\r\n name: name || \"server\",\r\n serverType: \"server\",\r\n udpPort: 4446,\r\n secretKey: \"\",\r\n stretchAsciiKey: false,\r\n useMsgpack: false,\r\n usePathDictionary: false,\r\n protocolVersion: 1\r\n };\r\n}\r\n\r\n/** Attach a stable _id to loaded connections that don't already have one. */\r\nfunction withId(conn: Omit<ConnectionData, \"_id\"> & { _id?: string }): ConnectionData {\r\n return conn._id ? (conn as ConnectionData) : { ...conn, _id: makeId() };\r\n}\r\n\r\n// Fill schema defaults into loaded form data so RJSF has nothing to augment on\r\n// mount — otherwise RJSF fires a synthetic onChange for every field that is\r\n// defined in the schema but absent from the persisted config (e.g.\r\n// stretchAsciiKey on pre-existing connections), which would trip the dirty flag\r\n// and surface \"Unsaved changes\" immediately after a fresh load.\r\nfunction withSchemaDefaults(conn: ConnectionData): ConnectionData {\r\n const isClient = conn.serverType !== \"server\";\r\n const schema = buildWebappConnectionSchema(isClient, conn.protocolVersion) as RJSFSchema;\r\n const { _id, ...formData } = conn;\r\n const enriched = getDefaultFormState(validator, schema, formData) as Record<string, unknown>;\r\n return { ...(enriched as Omit<ConnectionData, \"_id\">), _id };\r\n}\r\n\r\n// Deep equality that is insensitive to key insertion order (unlike\r\n// JSON.stringify). Used to decide whether an RJSF onChange carries a real\r\n// field-level difference.\r\nfunction stableStringify(value: unknown): string {\r\n if (value === null || typeof value !== \"object\") { return JSON.stringify(value); }\r\n if (Array.isArray(value)) {\r\n return \"[\" + value.map(stableStringify).join(\",\") + \"]\";\r\n }\r\n const obj = value as Record<string, unknown>;\r\n const keys = Object.keys(obj).sort();\r\n return \"{\" + keys.map((k) => JSON.stringify(k) + \":\" + stableStringify(obj[k])).join(\",\") + \"}\";\r\n}\r\n\r\nfunction connectionsEqual(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\r\n const aKeys = Object.keys(a);\r\n const bKeys = Object.keys(b);\r\n if (aKeys.length !== bKeys.length) { return false; }\r\n for (const k of aKeys) {\r\n if (!Object.prototype.hasOwnProperty.call(b, k)) { return false; }\r\n const av = a[k];\r\n const bv = b[k];\r\n if (av === bv) { continue; }\r\n if (av !== null && bv !== null && typeof av === \"object\" && typeof bv === \"object\") {\r\n if (stableStringify(av) !== stableStringify(bv)) { return false; }\r\n continue;\r\n }\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\n// ── Schema ────────────────────────────────────────────────────────────────────\r\n// Single source of truth for field definitions: src/shared/connection-schema.ts\r\n// (also consumed by plugin.schema in src/index.ts).\r\n\r\nconst uiSchemaClient: UiSchema = {\r\n \"ui:order\": [\r\n \"name\", \"serverType\", \"udpAddress\", \"udpPort\", \"secretKey\", \"stretchAsciiKey\", \"protocolVersion\",\r\n \"useMsgpack\", \"usePathDictionary\", \"testAddress\", \"testPort\", \"pingIntervalTime\",\r\n \"helloMessageSender\", \"reliability\", \"congestionControl\", \"bonding\", \"enableNotifications\", \"alertThresholds\"\r\n ],\r\n secretKey: { \"ui:widget\": \"password\", \"ui:help\": \"Use 32-character ASCII, 64-character hex, or 44-character base64\" },\r\n stretchAsciiKey: { \"ui:help\": \"Only applies to 32-char ASCII keys. Must match on both peers.\" },\r\n serverType: { \"ui:widget\": \"select\" },\r\n reliability: {\r\n \"ui:classNames\": \"skel-optional-group\"\r\n },\r\n congestionControl: {\r\n \"ui:classNames\": \"skel-optional-group\"\r\n },\r\n bonding: {\r\n \"ui:classNames\": \"skel-optional-group\"\r\n },\r\n alertThresholds: {\r\n \"ui:classNames\": \"skel-optional-group\"\r\n }\r\n};\r\n\r\nconst uiSchemaServer: UiSchema = {\r\n \"ui:order\": [\r\n \"name\", \"serverType\", \"udpPort\", \"secretKey\", \"stretchAsciiKey\", \"useMsgpack\", \"usePathDictionary\",\r\n \"protocolVersion\", \"reliability\"\r\n ],\r\n secretKey: { \"ui:widget\": \"password\", \"ui:help\": \"Use 32-character ASCII, 64-character hex, or 44-character base64\" },\r\n stretchAsciiKey: { \"ui:help\": \"Only applies to 32-char ASCII keys. Must match on both peers.\" },\r\n serverType: { \"ui:widget\": \"select\" }\r\n};\r\n\r\n// Shared fields preserved when the user toggles server <-> client mode\r\nconst SHARED_FIELDS = [\"name\", \"udpPort\", \"secretKey\", \"stretchAsciiKey\", \"useMsgpack\", \"usePathDictionary\", \"protocolVersion\"];\r\n\r\n// ── Styles ────────────────────────────────────────────────────────────────────\r\n// Using `skel-` prefix (Signal K Edge Link) to avoid collisions with other\r\n// plugins that may inject CSS into the same admin panel page.\r\n\r\nconst css = `\r\n.skel-config { font-family: inherit; }\r\n.skel-dirty-banner {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 14px;\r\n background: #fff3cd;\r\n color: #664d03;\r\n border: 1px solid #ffe69c;\r\n border-radius: 4px;\r\n margin-bottom: 12px;\r\n font-size: 0.88rem;\r\n}\r\n.skel-card {\r\n border: 1px solid #dee2e6;\r\n border-radius: 6px;\r\n margin-bottom: 12px;\r\n overflow: hidden;\r\n}\r\n.skel-card-header {\r\n display: flex;\r\n align-items: center;\r\n padding: 10px 14px;\r\n background: #f8f9fa;\r\n cursor: pointer;\r\n user-select: none;\r\n gap: 10px;\r\n}\r\n.skel-card-header:hover { background: #e9ecef; }\r\n.skel-badge {\r\n display: inline-block;\r\n padding: 2px 8px;\r\n border-radius: 12px;\r\n font-size: 0.75rem;\r\n font-weight: 600;\r\n text-transform: uppercase;\r\n letter-spacing: 0.03em;\r\n}\r\n.skel-badge-server { background: #cfe2ff; color: #084298; }\r\n.skel-badge-client { background: #d1e7dd; color: #0a3622; }\r\n.skel-card-title { font-weight: 600; flex: 1; }\r\n.skel-expand-icon { font-size: 0.8rem; color: #6c757d; }\r\n.skel-btn-remove {\r\n background: none;\r\n border: 1px solid #dc3545;\r\n color: #dc3545;\r\n border-radius: 4px;\r\n padding: 2px 8px;\r\n font-size: 0.8rem;\r\n cursor: pointer;\r\n}\r\n.skel-btn-remove:hover { background: #dc3545; color: white; }\r\n.skel-btn-remove:disabled { opacity: 0.4; cursor: default; border-color: #aaa; color: #aaa; }\r\n.skel-btn-remove:disabled:hover { background: none; }\r\n.skel-card-body { padding: 16px; border-top: 1px solid #dee2e6; }\r\n.skel-toolbar {\r\n display: flex;\r\n gap: 10px;\r\n align-items: center;\r\n margin-top: 16px;\r\n padding-top: 16px;\r\n border-top: 1px solid #dee2e6;\r\n flex-wrap: wrap;\r\n}\r\n.skel-btn {\r\n padding: 7px 16px;\r\n border-radius: 4px;\r\n font-size: 0.95rem;\r\n cursor: pointer;\r\n border: none;\r\n}\r\n.skel-btn-primary { background: #0d6efd; color: white; }\r\n.skel-btn-primary:hover { background: #0b5ed7; }\r\n.skel-btn-primary:disabled { background: #6c757d; cursor: default; }\r\n.skel-btn-secondary { background: white; color: #0d6efd; border: 1px solid #0d6efd; }\r\n.skel-btn-secondary:hover { background: #e7f0ff; }\r\n.skel-alert {\r\n padding: 10px 14px;\r\n border-radius: 4px;\r\n margin-bottom: 14px;\r\n font-size: 0.9rem;\r\n}\r\n.skel-alert-success { background: #d1e7dd; color: #0a3622; border: 1px solid #a3cfbb; }\r\n.skel-alert-error { background: #f8d7da; color: #58151c; border: 1px solid #f1aeb5; }\r\n.skel-alert-saving { background: #fff3cd; color: #664d03; border: 1px solid #ffe69c; }\r\n.skel-dup-warn { font-size: 0.8rem; color: #dc3545; margin-top: 4px; }\r\n.skel-plugin-settings {\r\n border: 1px solid #dee2e6;\r\n border-radius: 6px;\r\n margin-bottom: 20px;\r\n padding: 16px;\r\n background: #f8f9fa;\r\n}\r\n.skel-plugin-settings h3 {\r\n margin: 0 0 12px;\r\n font-size: 1rem;\r\n font-weight: 600;\r\n}\r\n.skel-field-group {\r\n margin-bottom: 14px;\r\n}\r\n.skel-field-group label {\r\n display: block;\r\n font-weight: 500;\r\n margin-bottom: 4px;\r\n font-size: 0.9rem;\r\n}\r\n.skel-field-group input[type=\"text\"],\r\n.skel-field-group input[type=\"password\"] {\r\n width: 100%;\r\n max-width: 420px;\r\n padding: 6px 10px;\r\n border: 1px solid #ced4da;\r\n border-radius: 4px;\r\n font-size: 0.9rem;\r\n}\r\n.skel-field-group input[type=\"checkbox\"] {\r\n margin-right: 6px;\r\n}\r\n.skel-field-desc {\r\n font-size: 0.8rem;\r\n color: #5c6773;\r\n margin-top: 3px;\r\n}\r\n.skel-config .field-description {\r\n color: #5c6773;\r\n font-size: 0.83rem;\r\n line-height: 1.35;\r\n}\r\n.skel-config legend,\r\n.skel-config label {\r\n line-height: 1.2;\r\n overflow-wrap: anywhere;\r\n}\r\n.skel-optional-group {\r\n margin-top: 12px;\r\n border: 1px dashed #ccd5df;\r\n border-radius: 6px;\r\n padding: 10px 12px 4px;\r\n background: #fbfcfe;\r\n}\r\n.skel-optional-group legend {\r\n font-size: 0.92rem;\r\n margin-bottom: 6px;\r\n}\r\n.skel-optional-group .form-group {\r\n margin-bottom: 10px;\r\n}\r\n.skel-optional-group .form-control {\r\n max-width: 340px;\r\n}\r\n`;\r\n\r\n// ── ConnectionCard ────────────────────────────────────────────────────────────\r\n\r\ninterface ConnectionCardProps {\r\n conn: ConnectionData;\r\n index: number;\r\n totalCount: number;\r\n expanded: boolean;\r\n onToggle: () => void;\r\n onChange: (data: ConnectionData) => void;\r\n onRemove: () => void;\r\n}\r\n\r\nfunction ConnectionCard({ conn, index, totalCount, expanded, onToggle, onChange, onRemove }: ConnectionCardProps) {\r\n const isClient = conn.serverType !== \"server\";\r\n const schema = buildWebappConnectionSchema(isClient, conn.protocolVersion) as RJSFSchema;\r\n const uiSchema = isClient ? uiSchemaClient : uiSchemaServer;\r\n const modeLabel = isClient ? \"Client\" : \"Server\";\r\n const displayName = (conn.name || `Connection ${index + 1}`).trim();\r\n\r\n function handleFormChange(e: any) {\r\n const next: ConnectionData = e.formData;\r\n if (next.serverType !== conn.serverType) {\r\n const base = next.serverType === \"server\"\r\n ? defaultServerConnection(next.name)\r\n : defaultClientConnection(next.name);\r\n const merged: ConnectionData = { ...base, _id: conn._id };\r\n for (const k of SHARED_FIELDS) {\r\n if (next[k] !== undefined) { (merged as Record<string, unknown>)[k] = next[k]; }\r\n }\r\n merged.serverType = next.serverType;\r\n onChange(merged);\r\n return;\r\n }\r\n // Skip propagation when the incoming form data is identical to the current\r\n // connection — RJSF can fire onChange with no effective diff (e.g. after\r\n // internal re-renders), and we do not want that to trip the dirty flag.\r\n // Order-insensitive compare so a reshuffled-but-equivalent formData does\r\n // not look like a real edit.\r\n const proposed: ConnectionData = { ...next, _id: conn._id };\r\n const { _id: _aId, ...a } = proposed;\r\n const { _id: _bId, ...b } = conn;\r\n if (connectionsEqual(a, b)) { return; }\r\n onChange(proposed);\r\n }\r\n\r\n // Strip the frontend-only _id before passing to RJSF\r\n const { _id, ...formData } = conn;\r\n\r\n return (\r\n <div className=\"skel-card\">\r\n <div className=\"skel-card-header\" onClick={onToggle} role=\"button\" aria-expanded={expanded}>\r\n <span className={`skel-badge ${isClient ? \"skel-badge-client\" : \"skel-badge-server\"}`}>\r\n {modeLabel}\r\n </span>\r\n <span className=\"skel-card-title\">{displayName}</span>\r\n <span className=\"skel-expand-icon\">{expanded ? \"\\u25B2\" : \"\\u25BC\"}</span>\r\n <button\r\n className=\"skel-btn-remove\"\r\n disabled={totalCount <= 1}\r\n onClick={(e) => { e.stopPropagation(); onRemove(); }}\r\n title={totalCount <= 1 ? \"Cannot remove the only connection\" : \"Remove this connection\"}\r\n >\r\n Remove\r\n </button>\r\n </div>\r\n {expanded && (\r\n <div className=\"skel-card-body\">\r\n <Form\r\n schema={schema}\r\n uiSchema={uiSchema}\r\n formData={formData}\r\n validator={validator}\r\n onChange={handleFormChange}\r\n onSubmit={() => {}}\r\n liveValidate={false}\r\n >\r\n {/* Hide the default submit button – saving is done from the outer toolbar */}\r\n <div />\r\n </Form>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// ── Main panel ────────────────────────────────────────────────────────────────\r\n\r\nfunction PluginConfigurationPanel(_props: Record<string, unknown>) {\r\n const [connections, setConnections] = useState<ConnectionData[]>([]);\r\n const [managementApiToken, setManagementApiToken] = useState<string>(\"\");\r\n const [requireManagementApiToken, setRequireManagementApiToken] = useState<boolean>(false);\r\n const [loading, setLoading] = useState(true);\r\n const [loadError, setLoadError] = useState<string | null>(null);\r\n const [saveStatus, setSaveStatus] = useState<SaveStatus | null>(null);\r\n const [inlineValidationMessage, setInlineValidationMessage] = useState<string | null>(null);\r\n const [expandedIndex, setExpandedIndex] = useState<number | null>(0);\r\n const [isDirty, setIsDirty] = useState(false);\r\n const savingRef = useRef(false);\r\n\r\n // ── Load config ─────────────────────────────────────────────────────────────\r\n useEffect(() => {\r\n async function load() {\r\n try {\r\n const res = await apiFetch(`${API_BASE}/plugin-config`);\r\n if (res.status === 401) {\r\n throw new Error(MANAGEMENT_TOKEN_ERROR_MESSAGE);\r\n }\r\n if (!res.ok) { throw new Error(`HTTP ${res.status}: ${res.statusText}`); }\r\n const body = await res.json();\r\n if (!body.success) { throw new Error(body.error || \"Failed to load configuration\"); }\r\n\r\n const cfg = body.configuration || {};\r\n let list: ConnectionData[];\r\n if (Array.isArray(cfg.connections) && cfg.connections.length > 0) {\r\n list = cfg.connections.map((c: Omit<ConnectionData, \"_id\">) => withSchemaDefaults(withId(c)));\r\n } else if (cfg.serverType) {\r\n list = [withSchemaDefaults(withId(cfg))];\r\n } else {\r\n list = [defaultClientConnection()];\r\n }\r\n setConnections(list);\r\n setManagementApiToken(typeof cfg.managementApiToken === \"string\" ? cfg.managementApiToken : \"\");\r\n setRequireManagementApiToken(cfg.requireManagementApiToken === true);\r\n setExpandedIndex(0);\r\n setIsDirty(false);\r\n } catch (err: unknown) {\r\n setLoadError(err instanceof Error ? err.message : String(err));\r\n } finally {\r\n setLoading(false);\r\n }\r\n }\r\n load();\r\n }, []);\r\n\r\n // ── Duplicate server-port detection ─────────────────────────────────────────\r\n const serverPorts = connections\r\n .filter((c) => c.serverType === \"server\")\r\n .map((c) => c.udpPort);\r\n const duplicatePortSet = new Set(\r\n serverPorts.filter((p, i) => serverPorts.indexOf(p) !== i)\r\n );\r\n\r\n // ── Handlers ─────────────────────────────────────────────────────────────────\r\n function markDirty() {\r\n setIsDirty(true);\r\n setSaveStatus(null);\r\n setInlineValidationMessage(null);\r\n }\r\n\r\n function updateConnection(idx: number, data: ConnectionData) {\r\n setConnections((prev) => prev.map((c, i) => (i === idx ? data : c)));\r\n markDirty();\r\n }\r\n\r\n function addServer() {\r\n setConnections((prev) => {\r\n const next = [...prev, defaultServerConnection(`server-${prev.length + 1}`)];\r\n setExpandedIndex(next.length - 1);\r\n return next;\r\n });\r\n markDirty();\r\n }\r\n\r\n function addClient() {\r\n setConnections((prev) => {\r\n const next = [...prev, defaultClientConnection(`client-${prev.length + 1}`)];\r\n setExpandedIndex(next.length - 1);\r\n return next;\r\n });\r\n markDirty();\r\n }\r\n\r\n function removeConnection(idx: number) {\r\n setConnections((prev) => {\r\n if (prev.length <= 1) return prev;\r\n const next = prev.filter((_, i) => i !== idx);\r\n setExpandedIndex((prevExpanded) => (prevExpanded !== null && prevExpanded >= idx && prevExpanded > 0 ? prevExpanded - 1 : prevExpanded));\r\n return next;\r\n });\r\n markDirty();\r\n }\r\n\r\n function toggleExpand(idx: number) {\r\n setExpandedIndex((prev) => (prev === idx ? null : idx));\r\n }\r\n\r\n const handleSave = useCallback(async () => {\r\n if (savingRef.current) { return; }\r\n if (connections.length === 0) {\r\n setInlineValidationMessage(\"At least one connection is required before saving.\");\r\n setSaveStatus({\r\n type: \"error\",\r\n message: \"Cannot save an empty configuration. Add at least one connection.\"\r\n });\r\n return;\r\n }\r\n\r\n setInlineValidationMessage(null);\r\n if (duplicatePortSet.size > 0) {\r\n setSaveStatus({\r\n type: \"error\",\r\n message: `Duplicate server ports detected: ${[...duplicatePortSet].join(\", \")}. Each server must use a unique UDP port.`\r\n });\r\n return;\r\n }\r\n\r\n savingRef.current = true;\r\n setSaveStatus({ type: \"saving\", message: \"Saving configuration...\" });\r\n try {\r\n const payload = connections.map(({ _id, ...rest }) => rest);\r\n const res = await apiFetch(`${API_BASE}/plugin-config`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n connections: payload,\r\n managementApiToken: managementApiToken,\r\n requireManagementApiToken: requireManagementApiToken\r\n })\r\n });\r\n if (res.status === 401) {\r\n throw new Error(MANAGEMENT_TOKEN_ERROR_MESSAGE);\r\n }\r\n const body = await res.json();\r\n if (res.ok && body.success) {\r\n setSaveStatus({ type: \"success\", message: body.message || \"Configuration saved. Plugin restarting...\" });\r\n setIsDirty(false);\r\n } else {\r\n throw new Error(body.error || \"Failed to save\");\r\n }\r\n } catch (err: unknown) {\r\n setSaveStatus({ type: \"error\", message: err instanceof Error ? err.message : String(err) });\r\n } finally {\r\n savingRef.current = false;\r\n }\r\n }, [connections, duplicatePortSet, managementApiToken, requireManagementApiToken]);\r\n\r\n // ── Render ────────────────────────────────────────────────────────────────────\r\n if (loading) {\r\n return <div style={{ padding: \"20px\", textAlign: \"center\" }}>Loading configuration...</div>;\r\n }\r\n\r\n if (loadError) {\r\n return (\r\n <div style={{ padding: \"20px\" }}>\r\n <div className=\"skel-alert skel-alert-error\">\r\n <strong>Error loading configuration:</strong> {loadError}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"skel-config\">\r\n <style>{css}</style>\r\n\r\n {isDirty && saveStatus?.type !== \"saving\" && (\r\n <div className=\"skel-dirty-banner\">\r\n <span>⚠</span>\r\n <span>You have unsaved changes.</span>\r\n </div>\r\n )}\r\n\r\n {saveStatus && (\r\n <div className={`skel-alert skel-alert-${saveStatus.type === \"saving\" ? \"saving\" : saveStatus.type === \"success\" ? \"success\" : \"error\"}`}>\r\n {saveStatus.message}\r\n </div>\r\n )}\r\n\r\n {/* Plugin-level security settings */}\r\n <div className=\"skel-plugin-settings\">\r\n <h3>Plugin Security Settings</h3>\r\n <div className=\"skel-field-group\">\r\n <label htmlFor=\"skel-mgmt-token\">Management API Token</label>\r\n <input\r\n id=\"skel-mgmt-token\"\r\n type=\"password\"\r\n value={managementApiToken}\r\n placeholder=\"Leave empty for open access\"\r\n onChange={(e) => { setManagementApiToken(e.target.value); markDirty(); }}\r\n autoComplete=\"new-password\"\r\n />\r\n <div className=\"skel-field-desc\">\r\n Shared secret to protect the management API endpoints. Strongly recommended for\r\n production. Can also be set via the{\" \"}\r\n <code>SIGNALK_EDGE_LINK_MANAGEMENT_TOKEN</code> environment variable (env var takes\r\n priority). Leave empty to allow open access.\r\n </div>\r\n </div>\r\n <div className=\"skel-field-group\">\r\n <label>\r\n <input\r\n type=\"checkbox\"\r\n checked={requireManagementApiToken}\r\n onChange={(e) => { setRequireManagementApiToken(e.target.checked); markDirty(); }}\r\n />\r\n Require Management API Token\r\n </label>\r\n <div className=\"skel-field-desc\">\r\n When enabled, all management API requests are rejected if no token is configured\r\n (fail-closed). When disabled, requests are allowed if no token is set (open access).\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {connections.map((conn, idx) => (\r\n <div key={conn._id}>\r\n <ConnectionCard\r\n conn={conn}\r\n index={idx}\r\n totalCount={connections.length}\r\n expanded={expandedIndex === idx}\r\n onToggle={() => toggleExpand(idx)}\r\n onChange={(data: ConnectionData) => updateConnection(idx, data)}\r\n onRemove={() => removeConnection(idx)}\r\n />\r\n {conn.serverType === \"server\" && duplicatePortSet.has(conn.udpPort) && (\r\n <div className=\"skel-dup-warn\">\r\n Port {conn.udpPort} is used by multiple server connections. Each server requires a unique port.\r\n </div>\r\n )}\r\n </div>\r\n ))}\r\n\r\n <div className=\"skel-toolbar\">\r\n <button className=\"skel-btn skel-btn-secondary\" onClick={addServer}>\r\n + Add Server\r\n </button>\r\n <button className=\"skel-btn skel-btn-secondary\" onClick={addClient}>\r\n + Add Client\r\n </button>\r\n <button\r\n className=\"skel-btn skel-btn-primary\"\r\n onClick={handleSave}\r\n disabled={(saveStatus && saveStatus.type === \"saving\") || connections.length === 0}\r\n >\r\n {isDirty ? \"Save Changes\" : \"Save Configuration\"}\r\n </button>\r\n {inlineValidationMessage && (\r\n <span style={{ color: \"#dc3545\", fontSize: \"0.85rem\", fontWeight: 500 }}>\r\n {inlineValidationMessage}\r\n </span>\r\n )}\r\n <span style={{ fontSize: \"0.85rem\", color: \"#6c757d\" }}>\r\n {connections.length} connection{connections.length !== 1 ? \"s\" : \"\"}\r\n {\" \\u00B7 \"}\r\n {connections.filter((c) => c.serverType === \"server\").length} server\r\n {connections.filter((c) => c.serverType === \"server\").length !== 1 ? \"s\" : \"\"}\r\n {\", \"}\r\n {connections.filter((c) => c.serverType !== \"server\").length} client\r\n {connections.filter((c) => c.serverType !== \"server\").length !== 1 ? \"s\" : \"\"}\r\n </span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nexport default PluginConfigurationPanel;\r\n"],"names":["MANAGEMENT_TOKEN_ERROR_MESSAGE","DEFAULT_AUTH_CONFIG","token","localStorageKey","queryParam","includeTokenInQuery","headerMode","apiFetch","input","init","config","window","runtime","__EDGE_LINK_AUTH__","readRuntimeAuthConfig","String","trim","tokenFromQuery","URLSearchParams","location","search","get","localStorage","tokenFromStorage","getItem","resolveToken","headers","Headers","normalizedMode","toLowerCase","set","attachAuthHeaders","fetch","commonConnectionProperties","name","type","title","description","default","maxLength","serverType","oneOf","const","udpPort","minimum","maximum","secretKey","minLength","pattern","stretchAsciiKey","toLocaleString","useMsgpack","usePathDictionary","protocolVersion","clientTransportProperties","udpAddress","helloMessageSender","testAddress","testPort","pingIntervalTime","heartbeatInterval","clientReliabilityProperty","properties","retransmitQueueSize","maxRetransmits","retransmitMaxAge","retransmitMinAge","retransmitRttMultiplier","ackIdleDrainAge","forceDrainAfterAckIdle","forceDrainAfterMs","recoveryBurstEnabled","recoveryBurstSize","recoveryBurstIntervalMs","recoveryAckGapMs","serverReliabilityProperty","ackInterval","ackResendInterval","nakTimeout","congestionControlProperty","enabled","targetRTT","nominalDeltaTimer","minDeltaTimer","maxDeltaTimer","bondingProperty","mode","primary","address","port","interface","backup","failover","rttThreshold","lossThreshold","healthCheckInterval","failbackDelay","heartbeatTimeout","enableNotificationsProperty","alertThresholdsProperty","rtt","warning","critical","packetLoss","retransmitRate","jitter","queueDepth","buildWebappConnectionSchema","isClient","isReliableProtocol","Number","props","required","Object","assign","enableNotifications","push","reliability","congestionControl","bonding","alertThresholds","API_BASE","_idSeq","makeId","Date","now","defaultClientConnection","_id","defaultServerConnection","withId","conn","withSchemaDefaults","schema","formData","stableStringify","value","JSON","stringify","Array","isArray","map","join","obj","keys","sort","k","uiSchemaClient","uiSchemaServer","SHARED_FIELDS","ConnectionCard","index","totalCount","expanded","onToggle","onChange","onRemove","uiSchema","modeLabel","displayName","className","onClick","role","disabled","e","stopPropagation","validator","next","merged","undefined","proposed","_aId","a","_bId","b","aKeys","bKeys","length","prototype","hasOwnProperty","call","av","bv","connectionsEqual","onSubmit","liveValidate","_props","connections","setConnections","useState","managementApiToken","setManagementApiToken","requireManagementApiToken","setRequireManagementApiToken","loading","setLoading","loadError","setLoadError","saveStatus","setSaveStatus","inlineValidationMessage","setInlineValidationMessage","expandedIndex","setExpandedIndex","isDirty","setIsDirty","savingRef","useRef","useEffect","async","res","status","Error","ok","statusText","body","json","success","error","cfg","configuration","list","c","err","message","load","serverPorts","filter","duplicatePortSet","Set","p","i","indexOf","markDirty","handleSave","useCallback","current","size","payload","rest","method","style","padding","textAlign","htmlFor","id","placeholder","target","autoComplete","checked","idx","key","prev","toggleExpand","data","updateConnection","_","prevExpanded","removeConnection","has","color","fontSize","fontWeight"],"sourceRoot":""}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
(()=>{"use strict";var e,t,n={9217(){const e="Management token required/invalid.",t={token:null,localStorageKey:"signalkEdgeLinkManagementToken",queryParam:"edgeLinkToken",includeTokenInQuery:!1,headerMode:"both"};function n(){if("undefined"==typeof window)return t;const e=window.__EDGE_LINK_AUTH__;return e&&"object"==typeof e?{...t,...e}:t}const i="/plugins/signalk-edge-link";function s(e){return String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}const a=(e,t,n,i="")=>`\n <div class="config-section">\n <div class="card">\n <div class="card-header">\n <h2>${s(e)}</h2>\n ${t?`<p class="subtitle">${s(t)}</p>`:""}\n </div>\n <div class="card-content">\n <div id="${n}" class="${i||n+"-info"}">\n <p>Loading ${s(e.toLowerCase())}...</p>\n </div>\n </div>\n </div>\n </div>\n`,o=(e,t,n=!1)=>`\n <div class="stat-item${n?" error":""}">\n <span class="stat-label">${s(e)}:</span>\n <span class="stat-value">${s(t)}</span>\n </div>\n`,r=(e,t,n="")=>`\n <div class="metric-item${n?" "+n:""}">\n <div class="metric-label">${s(e)}</div>\n <div class="metric-value">${s(t)}</div>\n </div>\n`,c=(e,t,n="")=>`\n <div class="metric-item${n?" "+n:""}">\n <div class="metric-label">${s(e)}</div>\n <div class="metric-value">${t}</div>\n </div>\n`,l=(e,t,n=!1,i=!1)=>`\n <div class="bw-stat${n?" highlight":""}">\n <span class="bw-label">${s(e)}:</span>\n <span class="bw-value${i?" success-text":""}">${s(t)}</span>\n </div>\n`,d=(e,t,n,i="")=>`\n <section class="page-group"${i?` id="${i}"`:""}>\n <div class="page-group-header">\n <h2>${s(e)}</h2>\n ${t?`<p>${s(t)}</p>`:""}\n </div>\n <div class="page-group-content">\n ${n}\n </div>\n </section>\n`;class u{constructor(){this.connections=[],this.activeConnectionId=null,this.pluginConfig=null,this.pluginSchema=null,this.schemaCurrentMode=null,this.metricsInterval=null,this.syncTimeout=null,this.tokenHelpText=function(){const e=n(),t=e.headerMode&&"authorization"===String(e.headerMode).toLowerCase()?"Authorization: Bearer <token>":e.headerMode&&"x-edge-link-token"===String(e.headerMode).toLowerCase()?"X-Edge-Link-Token":"X-Edge-Link-Token and Authorization: Bearer <token>";return`The server-side token is configured in plugin settings (managementApiToken) or via the SIGNALK_EDGE_LINK_MANAGEMENT_TOKEN environment variable. To authenticate from the browser, provide the token using window.__EDGE_LINK_AUTH__.token, query parameter "${e.queryParam}", or localStorage key "${e.localStorageKey}". Requests send ${t} when a token is available.`}(),this.deltaTimerConfig=null,this.subscriptionConfig=null,this.sentenceFilterConfig=null,this.protocolVersion=1,this.isServerMode=!1,this._refreshInFlight=!1,this._notificationTimer=null,this.init()}async init(){try{await this.loadPluginConfiguration(!1),await this.fetchConnections(),this.renderPage(),this.startMetricsRefresh()}catch(e){console.error("Initialization error:",e),this.showNotification("Failed to initialize application: "+(e instanceof Error?e.message:String(e)),"error")}}async fetchConnections(){try{const e=await this.request(`${i}/connections`);e.ok&&(this.connections=await e.json())}catch(e){}if(!this.connections||0===this.connections.length){const e=this.detectModeFromConfig();this.connections=[{id:"_legacy",name:"Default",type:e}]}this.activeConnectionId||(this.activeConnectionId=this.connections[0].id)}detectModeFromConfig(){if(this.pluginConfig){const e=this.normalizeServerType(this.pluginConfig.serverType);if(e)return e}return this.schemaCurrentMode?this.schemaCurrentMode:"client"}getActiveConnection(){return this.connections.find(e=>e.id===this.activeConnectionId)||this.connections[0]}isLegacyMode(){return 1===this.connections.length&&"_legacy"===this.connections[0].id}metricsPath(e){return"_legacy"===e?`${i}/metrics`:`${i}/connections/${encodeURIComponent(e)}/metrics`}configPath(e,t){return"_legacy"===e?`${i}/config/${t}`:`${i}/connections/${encodeURIComponent(e)}/config/${t}`}monitoringPath(e,t){return"_legacy"===e?`${i}/monitoring/${t}`:`${i}/connections/${encodeURIComponent(e)}/monitoring/${t}`}congestionPath(e){return"_legacy"===e?`${i}/congestion`:`${i}/connections/${encodeURIComponent(e)}/congestion`}bondingPath(e){return"_legacy"===e?`${i}/bonding`:`${i}/connections/${encodeURIComponent(e)}/bonding`}bondingFailoverPath(e){return"_legacy"===e?`${i}/bonding/failover`:`${i}/connections/${encodeURIComponent(e)}/bonding/failover`}async request(t,i={}){const s=await function(e,t={}){const i=n(),s=function(e){if(e.token)return String(e.token).trim();if("undefined"==typeof window)return"";if(e.includeTokenInQuery&&e.queryParam){const t=new URLSearchParams(window.location.search).get(e.queryParam);if(t)return t.trim()}if(e.localStorageKey&&window.localStorage){const t=window.localStorage.getItem(e.localStorageKey);if(t)return t.trim()}return""}(i),a=new Headers(t.headers||{});return function(e,t,n){if(!t)return e;const i=(n||"both").toLowerCase();"x-edge-link-token"!==i&&"token"!==i&&"both"!==i||e.set("X-Edge-Link-Token",t),"authorization"!==i&&"bearer"!==i&&"both"!==i||e.set("Authorization",`Bearer ${t}`)}(a,s,i.headerMode),fetch(e,{...t,headers:a})}(t,i);if(401===s.status){const t=new Error(e);throw t.isUnauthorized=!0,t}return s}authFailureMessage(t){return`${e} Failed while ${t}. ${this.tokenHelpText}`}renderPage(){this.renderTabs(),this.renderConnectionContent()}renderTabs(){const e=document.getElementById("connectionTabs");if(e){if(this.connections.length<=1)return e.innerHTML="",void(e.style.display="none");e.style.display="",e.innerHTML=`<div class="tabs-container">${this.connections.map(e=>{const t="server"===e.type?"🖥":"📱",n=!1===e.healthy?'<span class="tab-status-dot error"></span>':e.readyToSend||"server"===e.type?'<span class="tab-status-dot ok"></span>':'<span class="tab-status-dot warning"></span>';return`<button class="connection-tab${e.id===this.activeConnectionId?" active":""}"\n data-connection-id="${this.escapeHtml(e.id)}">\n ${n}\n <span class="tab-icon">${t}</span>\n <span class="tab-name">${this.escapeHtml(e.name||e.id)}</span>\n <span class="tab-type">${this.escapeHtml(e.type)}</span>\n </button>`}).join("")}</div>`,e.querySelectorAll(".connection-tab").forEach(e=>{e.addEventListener("click",()=>{const t=e.dataset.connectionId;t!==this.activeConnectionId&&(this.activeConnectionId=t,this.renderPage(),this.loadConnectionData())})})}}renderConnectionContent(){const e=document.getElementById("connectionContent");if(!e)return;const t=this.getActiveConnection();this.isServerMode="server"===t.type,this.isServerMode?this.renderServerContent(e):this.renderClientContent(e),this.setupEventListeners(),this.loadConnectionData()}renderServerContent(e){const t=a("Performance Metrics","Real-time reception statistics (auto-refreshes every 15 seconds)","metrics")+'<div id="monitoringSection" style="display:none;">'+a("Network Quality","Link quality score and network health indicators","networkQuality")+a("Bandwidth Monitor","Network reception statistics","bandwidth")+a("Path Analytics","Incoming data volume by SignalK path","pathAnalytics")+a("Monitoring & Alerts","Packet loss, retransmission tracking, and alert thresholds","monitoringAlerts")+"</div>";e.innerHTML=d("Operations & Monitoring","Track reception quality, throughput, and runtime behavior.",t,"operationsGroup")+d("Advanced","Full plugin configurator (JSON editor).",this.renderPluginConfigurationCard(),"advancedGroup")}renderClientContent(e){const t=this.renderDeltaTimerCard()+this.renderSubscriptionCard()+this.renderSentenceFilterCard(),n=a("Performance Metrics","Real-time transmission statistics (auto-refreshes every 15 seconds)","metrics")+'<div id="congestionSection" class="config-section" style="display:none;">'+a("Network Quality","Link quality score and network health indicators","networkQuality")+a("Bandwidth Monitor","Real-time data transmission statistics","bandwidth")+a("Path Analytics","Data volume by subscription path","pathAnalytics")+a("Congestion Control","AIMD congestion control state and delta timer auto-adjustment","congestionControl")+'</div><div id="bondingSection" class="config-section" style="display:none;">'+a("Connection Bonding","Multi-link bonding status and failover control","bondingStatus")+'</div><div id="monitoringSection" style="display:none;">'+a("Monitoring & Alerts","Packet loss, retransmission tracking, and alert thresholds","monitoringAlerts")+"</div>"+a("Status",null,"status","status-info");e.innerHTML=d("Configuration","Set up transmission behavior and plugin-level parameters.",t,"configurationGroup")+d("Operations & Monitoring","Track transmission quality, reliability, and runtime performance.",n,"operationsGroup")+d("Advanced","Full plugin configurator (JSON editor).",this.renderPluginConfigurationCard(),"advancedGroup")}renderDeltaTimerCard(){return'\n <div class="config-section">\n <div class="card">\n <div class="card-header">\n <h2>Delta Timer Configuration</h2>\n <p>Controls how often deltas are collected and sent (in milliseconds)</p>\n </div>\n <div class="card-content">\n <div class="form-group">\n <label for="deltaTimer">Delta Timer (ms):</label>\n <input type="number" id="deltaTimer" min="100" max="10000" step="100" placeholder="1000" />\n <small class="help-text">\n Lower values = more frequent updates, higher bandwidth usage<br>\n Higher values = better compression ratio, lower bandwidth usage\n </small>\n </div>\n <button id="saveDeltaTimer" class="btn btn-primary">Save Delta Timer</button>\n </div>\n </div>\n </div>\n '}renderSubscriptionCard(){return'\n <div class="config-section">\n <div class="card">\n <div class="card-header">\n <h2>Subscription Configuration</h2>\n <p>Define which SignalK data paths to subscribe to</p>\n </div>\n <div class="card-content">\n <div class="form-group">\n <label for="context">Context:</label>\n <input type="text" id="context" placeholder="*" />\n <small class="help-text">\n Context for the subscription (e.g., "vessels.self", "*" for all)\n </small>\n </div>\n <div class="subscription-paths">\n <h3>Subscription Paths</h3>\n <div id="pathsList" class="paths-list"></div>\n <button id="addPath" class="btn btn-secondary">Add Path</button>\n </div>\n <div class="json-editor">\n <h3>JSON Editor</h3>\n <textarea id="subscriptionJson" rows="10" placeholder=\'{"context": "*", "subscribe": [{"path": "*"}]}\'></textarea>\n <small class="help-text">Advanced: Edit the raw JSON configuration</small>\n </div>\n <button id="saveSubscription" class="btn btn-primary">Save Subscription</button>\n </div>\n </div>\n </div>\n '}renderSentenceFilterCard(){return'\n <div class="config-section">\n <div class="card">\n <div class="card-header">\n <h2>Sentence Filter</h2>\n <p>Exclude NMEA sentences from transmission (reduces bandwidth)</p>\n </div>\n <div class="card-content">\n <div class="form-group">\n <label for="sentenceFilter">Excluded Sentences:</label>\n <input type="text" id="sentenceFilter" placeholder="" autocomplete="off" />\n <small class="help-text">\n Comma-separated list of NMEA sentence types to exclude.\n </small>\n </div>\n <button id="saveSentenceFilter" class="btn btn-primary">Save Sentence Filter</button>\n </div>\n </div>\n </div>\n '}renderPluginConfigurationCard(){return`\n <div class="config-section">\n <div class="card">\n <div class="card-header">\n <h2>Full Plugin Configuration</h2>\n <p>All parameters from <code>/plugin-config</code> (advanced JSON editor)</p>\n </div>\n <div class="card-content">\n <div id="pluginConfigSummary" class="plugin-config-summary">\n <p>Loading plugin configuration...</p>\n </div>\n <div class="json-editor plugin-config-editor">\n <h3>Plugin Config JSON</h3>\n <textarea\n id="pluginConfigJson"\n rows="20"\n placeholder='{"serverType":"client","udpPort":4446,"secretKey":"..."}'\n ></textarea>\n <small class="help-text">\n This editor exposes all available plugin fields. Save triggers plugin restart when supported.\n </small>\n <small class="help-text">${this.escapeHtml(this.tokenHelpText)}</small>\n </div>\n <div class="plugin-config-actions">\n <button id="savePluginConfig" class="btn btn-primary">Save Full Plugin Config</button>\n <button id="reloadPluginConfig" class="btn btn-secondary">Reload From Server</button>\n <button id="loadDefaultPluginConfig" class="btn btn-secondary">Load Schema Defaults</button>\n </div>\n </div>\n </div>\n </div>\n `}async loadConnectionData(){const e=this.getActiveConnection().id;this.isServerMode?this.updatePluginConfigUI():(await this.loadConfigurations(e),this.updateUI(),this.updateStatus()),await this.loadMetrics(e)}async loadPluginConfiguration(e=!0){try{const[e,t]=await Promise.all([this.request(`${i}/plugin-config`),this.request(`${i}/plugin-schema`)]);if(!e.ok)throw new Error(`Failed to load plugin configuration (${e.status})`);const n=await e.json(),s=n&&n.configuration&&"object"==typeof n.configuration&&!Array.isArray(n.configuration)?n.configuration:{};if(t.ok){const e=await t.json();e&&e.schema&&"object"==typeof e.schema&&(this.pluginSchema=e.schema),!e||"server"!==e.currentMode&&"client"!==e.currentMode||(this.schemaCurrentMode=e.currentMode)}return this.pluginConfig=this.buildCompletePluginConfig(s),!0}catch(t){if(e){const e=t;this.showNotification(e.isUnauthorized?this.authFailureMessage("loading plugin config"):"Error loading plugin config: "+e.message,"warning")}return!1}}async loadConfigurations(e){try{const[t,n,i]=await Promise.all([this.request(this.configPath(e,"delta_timer.json")),this.request(this.configPath(e,"subscription.json")),this.request(this.configPath(e,"sentence_filter.json"))]);this.deltaTimerConfig=t.ok?await t.json():null,this.subscriptionConfig=n.ok?await n.json():null,this.sentenceFilterConfig=i.ok?await i.json():null}catch(e){const t=e;this.showNotification(t.isUnauthorized?this.authFailureMessage("loading connection configuration"):"Error loading configurations: "+t.message,"error")}}async loadMetrics(e){e||(e=this.activeConnectionId);try{const t=await this.request(this.metricsPath(e));if(t.ok){const n=await t.json();this.protocolVersion=n.protocolVersion||1,this.updateMetricsDisplay(n),this.protocolVersion>=2&&this.loadV2Data(e)}}catch(e){console.error("Error loading metrics:",e.message)}}async loadV2Data(e){const t=!this.isServerMode,n=[this.request(this.monitoringPath(e,"alerts")).catch(()=>null),this.request(this.monitoringPath(e,"packet-loss")).catch(()=>null),this.request(this.monitoringPath(e,"retransmissions")).catch(()=>null)];t&&n.push(this.request(this.congestionPath(e)).catch(()=>null),this.request(this.bondingPath(e)).catch(()=>null));const i=await Promise.all(n),[s,a,o,r,c]=i,l={};if(s&&s.ok&&(l.alerts=await s.json()),a&&a.ok&&(l.packetLoss=await a.json()),o&&o.ok&&(l.retransmissions=await o.json()),this.updateMonitoringDisplay(l),t&&r&&r.ok){const e=await r.json();this.updateCongestionDisplay(e)}if(t&&c&&c.ok){const e=await c.json();this.updateBondingDisplay(e)}}startMetricsRefresh(){this.metricsInterval&&clearInterval(this.metricsInterval),this.metricsInterval=setInterval(()=>{this._refreshInFlight||(this._refreshInFlight=!0,this.refreshActiveTab().finally(()=>{this._refreshInFlight=!1}))},15e3)}async refreshActiveTab(){try{const e=await this.request(`${i}/connections`);if(e.ok){const t=await e.json();t.length>0&&(this.connections=t,this.renderTabs())}}catch(e){}await this.loadMetrics(this.activeConnectionId)}setupEventListeners(){const e=document.getElementById("saveDeltaTimer");e&&e.addEventListener("click",()=>this.saveDeltaTimer());const t=document.getElementById("saveSubscription");t&&t.addEventListener("click",()=>this.saveSubscription());const n=document.getElementById("saveSentenceFilter");n&&n.addEventListener("click",()=>this.saveSentenceFilter());const i=document.getElementById("addPath");i&&i.addEventListener("click",()=>this.addPathItem());const s=document.getElementById("subscriptionJson");s&&s.addEventListener("input",()=>{this.syncTimeout&&clearTimeout(this.syncTimeout),this.syncTimeout=setTimeout(()=>this.syncFromJson(),300)});const a=document.getElementById("context");a&&a.addEventListener("input",()=>this.updateJsonFromForm());const o=document.getElementById("savePluginConfig");o&&o.addEventListener("click",()=>this.savePluginConfig());const r=document.getElementById("reloadPluginConfig");r&&r.addEventListener("click",()=>this.reloadPluginConfiguration());const c=document.getElementById("loadDefaultPluginConfig");c&&c.addEventListener("click",()=>this.loadDefaultPluginConfiguration())}updateUI(){if(this.updatePluginConfigUI(),this.deltaTimerConfig&&this.deltaTimerConfig.deltaTimer){const e=document.getElementById("deltaTimer");e&&(e.value=String(this.deltaTimerConfig.deltaTimer))}if(this.subscriptionConfig){const e=this.subscriptionConfig,t=document.getElementById("context");t&&(t.value=e.context||"*");const n=document.getElementById("pathsList");n&&(n.innerHTML="",e.subscribe&&Array.isArray(e.subscribe)&&e.subscribe.forEach(e=>this.addPathItem(e.path)));const i=document.getElementById("subscriptionJson");i&&(i.value=JSON.stringify(this.subscriptionConfig,null,2))}if(this.sentenceFilterConfig&&Array.isArray(this.sentenceFilterConfig.excludedSentences)){const e=document.getElementById("sentenceFilter");e&&(e.value=this.sentenceFilterConfig.excludedSentences.join(", "))}}updatePluginConfigUI(){const e=document.getElementById("pluginConfigJson"),t=document.getElementById("pluginConfigSummary");if(e){if(!this.pluginConfig)return e.value="{}",void(t&&(t.innerHTML="<p>Plugin config unavailable.</p>"));if(e.value=JSON.stringify(this.pluginConfig,null,2),t){const e=Array.isArray(this.pluginConfig.connections)&&this.pluginConfig.connections.length>0;let n="Top-level",i="Top-Level Fields",s=this.pluginConfig;if(e){const e=this.pluginConfig.connections.length,t=this.connections.findIndex(e=>e.id===this.activeConnectionId),a=t>=0&&t<e?t:0,o=this.pluginConfig.connections[a];s=o&&"object"==typeof o&&!Array.isArray(o)?o:{},n=`Connection ${a+1}/${e}`,i="Connection Fields"}const a=this.normalizeServerType(s.serverType)||"client",r=Number(s.protocolVersion)>=2?Number(s.protocolVersion):1,c=Object.keys(s).length;t.innerHTML=`\n <div class="plugin-summary-grid">\n ${o("Scope",n)}\n ${o("Mode",a.toUpperCase())}\n ${o("Protocol","v"+String(r))}\n ${o(i,String(c))}\n </div>\n `}}}addPathItem(e=""){const t=document.getElementById("pathsList");if(!t)return;const n=document.createElement("div");n.className="path-item";const i=document.createElement("input");i.type="text",i.value=e,i.placeholder="navigation.position",i.className="path-input";const s=document.createElement("button");s.type="button",s.className="btn btn-danger",s.textContent="Remove",i.addEventListener("input",()=>this.updateJsonFromForm()),s.addEventListener("click",()=>{n.remove(),this.updateJsonFromForm()}),n.appendChild(i),n.appendChild(s),t.appendChild(n),this.updateJsonFromForm()}updateJsonFromForm(){const e=document.getElementById("context"),t=e&&e.value||"*",n=document.querySelectorAll(".path-input"),i={context:t,subscribe:Array.from(n).map(e=>({path:e.value})).filter(e=>""!==e.path.trim())},s=document.getElementById("subscriptionJson");s&&(s.value=JSON.stringify(i,null,2))}syncFromJson(){try{const e=document.getElementById("subscriptionJson");if(!e)return;const t=JSON.parse(e.value),n=document.getElementById("context");n&&(n.value=t.context||"*");const i=document.getElementById("pathsList");i&&(i.innerHTML="",t.subscribe&&Array.isArray(t.subscribe)&&t.subscribe.forEach(e=>this.addPathItem(e.path||"")))}catch(e){console.warn("Invalid JSON in editor:",e.message)}}async saveConfig(e,t,n,i){const s=this.activeConnectionId;try{if(!(await this.request(this.configPath(s,e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).ok)throw new Error("Failed to save configuration");this[n]=t,this.showNotification(`${i} saved successfully!`,"success"),this.updateStatus()}catch(e){const t=e;this.showNotification(t.isUnauthorized?this.authFailureMessage(`saving ${i.toLowerCase()}`):`Error saving ${i.toLowerCase()}: `+t.message,"error")}}async saveDeltaTimer(){const e=parseInt(document.getElementById("deltaTimer").value);isNaN(e)||e<100||e>1e4?this.showNotification("Delta timer must be between 100 and 10000 milliseconds","error"):await this.saveConfig("delta_timer.json",{deltaTimer:e},"deltaTimerConfig","Delta timer configuration")}async saveSubscription(){try{const e=document.getElementById("subscriptionJson").value,t=JSON.parse(e);if(!t.context)throw new Error("Context is required");if(!t.subscribe||!Array.isArray(t.subscribe))throw new Error("Subscribe array is required");await this.saveConfig("subscription.json",t,"subscriptionConfig","Subscription configuration")}catch(e){this.showNotification("Error saving subscription: "+e.message,"error")}}async saveSentenceFilter(){const e=document.getElementById("sentenceFilter").value.split(",").map(e=>e.trim().toUpperCase()).filter(e=>e.length>0);await this.saveConfig("sentence_filter.json",{excludedSentences:e},"sentenceFilterConfig","Sentence filter")}async savePluginConfig(){const e=document.getElementById("pluginConfigJson");if(e)try{const t=JSON.parse(e.value);if(!t||"object"!=typeof t||Array.isArray(t))throw new Error("Plugin configuration must be a JSON object");const n=this.deepClone(t),s=this.normalizeServerType(n.serverType);s&&(n.serverType=s);const a=await this.request(`${i}/plugin-config`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),o=await a.json().catch(()=>({}));if(!a.ok||!o.success)throw new Error(o.error||`Failed to save plugin configuration (${a.status})`);this.pluginConfig=this.buildCompletePluginConfig(n),this.updatePluginConfigUI(),this.showNotification(o.message||"Plugin configuration saved. Refresh to apply changes.","success")}catch(e){const t=e;this.showNotification(t.isUnauthorized?this.authFailureMessage("saving full plugin config"):"Error saving full plugin config: "+t.message,"error")}}async reloadPluginConfiguration(){await this.loadPluginConfiguration(!0)&&(this.updatePluginConfigUI(),this.showNotification("Plugin configuration reloaded.","success"))}loadDefaultPluginConfiguration(){this.pluginConfig=this.buildCompletePluginConfig({}),this.updatePluginConfigUI(),this.showNotification("Loaded schema defaults into editor. Save to apply.","warning")}updateMetricsDisplay(e){this.updateNetworkQualityDisplay(e),this.updateBandwidthDisplay(e),this.updatePathAnalyticsDisplay(e);const t=document.getElementById("metrics");if(!t)return;const n="client"===e.mode,{stats:i,status:a,uptime:l}=e,d=i.errorCounts&&i.errorCounts.crypto||0,u=i.malformedPackets||0,h=i.udpSendErrors>0||i.compressionErrors>0||i.encryptionErrors>0||i.subscriptionErrors>0||d>0||u>0,g=e.protocolVersion||1,p=g>=2?`v${g}`:"v1",m=[r("Uptime",l.formatted),r("Mode",n?"Client":"Server"),c("Protocol",`<span class="protocol-badge protocol-${s(p)}">${s(p.toUpperCase())}</span>`),r("Status",a.readyToSend?"Ready":"Not Ready",a.readyToSend?"success":"error"),n?r("Buffered Deltas",a.deltasBuffered):""].join(""),v=i.subscriptionErrors,f=n?o("Subscription Errors",v,v>0):"";let y=`\n <h4>Performance Metrics</h4>\n <div class="metrics-grid">${m}</div>\n <div class="metrics-stats">\n <h5>Transmission Statistics</h5>\n <div class="stats-grid">${[n?o("Deltas Sent",i.deltasSent.toLocaleString()):o("Deltas Received",i.deltasReceived.toLocaleString()),n?o("UDP Send Errors",i.udpSendErrors,i.udpSendErrors>0):"",n?o("UDP Retries",i.udpRetries):"",o("Compression Errors",i.compressionErrors,i.compressionErrors>0),o("Encryption Errors",i.encryptionErrors,i.encryptionErrors>0),f,!n&&i.duplicatePackets>0?o("Duplicate Packets",i.duplicatePackets.toLocaleString()):"",g>=3?o("Auth Failures (V3)",d,d>0):"",o("Malformed Packets",u,u>0)].join("")}</div>\n </div>\n `;if(n&&e.smartBatching){const t=e.smartBatching,n=t.earlySends+t.timerSends,i=n>0?Math.round(t.earlySends/n*100):0;y+=`\n <div class="metrics-stats">\n <h5>Smart Batching</h5>\n <div class="stats-grid">\n ${o("Avg Bytes/Delta",t.avgBytesPerDelta+" bytes")}\n ${o("Max Deltas/Batch",t.maxDeltasPerBatch)}\n ${o("Early Sends",t.earlySends.toLocaleString()+" ("+i+"%)")}\n ${o("Timer Sends",t.timerSends.toLocaleString())}\n ${o("Oversized Packets",t.oversizedPackets,t.oversizedPackets>0)}\n </div>\n </div>\n `}if(Array.isArray(e.recentErrors)&&e.recentErrors.length>0){const t=[...e.recentErrors].reverse().map(e=>{const t=Date.now()-e.timestamp,n=t<6e4?`${Math.floor(t/1e3)}s ago`:`${Math.floor(t/6e4)}m ago`;return`\n <div class="recent-error-item">\n <span class="error-category-badge">${this.escapeHtml(e.category)}</span>\n <span class="recent-error-msg">${this.escapeHtml(e.message)}</span>\n <span class="recent-error-time">${this.escapeHtml(n)}</span>\n </div>\n `}).join("");y+=`\n <div class="metrics-error">\n <h5>Recent Errors (${e.recentErrors.length})</h5>\n <div class="recent-errors-list">${t}</div>\n </div>\n `}else if(e.lastError){const t=e.lastError.timeAgo,n=t<6e4?`${Math.floor(t/1e3)}s ago`:`${Math.floor(t/6e4)}m ago`;y+=`\n <div class="metrics-error">\n <h5>Last Error</h5>\n <div class="error-message">${this.escapeHtml(e.lastError.message)}</div>\n <div class="error-time">Occurred ${n}</div>\n </div>\n `}else h||(y+='\n <div class="metrics-success">\n <div class="success-message">No errors detected</div>\n </div>\n ');t.innerHTML=y}updateNetworkQualityDisplay(e){const t=document.getElementById("networkQuality");if(!t||!e.networkQuality)return;const n=e.networkQuality,i="client"===e.mode;let s="N/A",a="#9E9E9E";void 0!==n.linkQuality&&(n.linkQuality>=90?(s="Excellent",a="#4CAF50"):n.linkQuality>=70?(s="Good",a="#FFC107"):n.linkQuality>=50?(s="Fair",a="#FF9800"):(s="Poor",a="#F44336"));const c=void 0!==n.linkQuality?n.linkQuality:0,l=c/100*180,d=Math.PI,u=d+l*Math.PI/180,h=50+40*Math.cos(d),g=50+40*Math.sin(d),p=50+40*Math.cos(u),m=50+40*Math.sin(u),v=`\n <svg viewBox="0 0 100 55" class="quality-gauge" preserveAspectRatio="xMidYMid meet">\n <path d="M 10 50 A 40 40 0 0 1 90 50"\n fill="none" stroke="#E0E0E0" stroke-width="8" stroke-linecap="round"/>\n ${c>0?`<path d="M ${h} ${g} A 40 40 0 ${l>180?1:0} 1 ${p} ${m}"\n fill="none" stroke="${a}" stroke-width="8" stroke-linecap="round"/>`:""}\n <text x="50" y="45" text-anchor="middle" font-size="16" font-weight="bold" fill="${a}">\n ${c}\n </text>\n <text x="50" y="58" text-anchor="middle" font-size="7" fill="#666">\n ${s}\n </text>\n </svg>\n `,f=void 0!==n.rtt?n.rtt+" ms":"N/A",y=void 0!==n.jitter?n.jitter+" ms":"N/A";let b=`\n <div class="network-quality-dashboard">\n <div class="nq-hero">\n <div class="nq-gauge-container">\n ${v}\n <div class="nq-gauge-label">Link Quality</div>\n </div>\n <div class="nq-key-metrics">\n ${r("RTT",f,n.rtt>500?"error":n.rtt>200?"warning":"")}\n ${r("Jitter",y,n.jitter>100?"error":n.jitter>50?"warning":"")}\n </div>\n </div>\n\n <div class="nq-details">\n <h5>Reliability Statistics</h5>\n <div class="stats-grid">\n `;b+=i?`\n ${o("Retransmissions",(n.retransmissions||0).toLocaleString(),n.retransmissions>0)}\n ${o("Queue Depth",(n.queueDepth||0).toLocaleString(),n.queueDepth>100)}\n `:`\n ${o("ACKs Sent",(n.acksSent||0).toLocaleString())}\n ${o("NAKs Sent",(n.naksSent||0).toLocaleString(),n.naksSent>0)}\n `,b+="\n </div>\n </div>\n </div>\n ",t.innerHTML=b}updateBandwidthDisplay(e){const t=document.getElementById("bandwidth");if(!t||!e.bandwidth)return;const n=e.bandwidth,i="client"===e.mode,s=i?n.bytesOutRaw-n.bytesOut:n.bytesInRaw-n.bytesIn,a=this.formatBytes(s>0?s:0);let o;o=i?[l("Total Sent (Compressed)",n.bytesOutFormatted),l("Total Raw (Before Compression)",n.bytesOutRawFormatted),l("Bandwidth Saved",a,!0,!0),l("Packets Sent",n.packetsOut.toLocaleString())]:[l("Total Received (Compressed)",n.bytesInFormatted),l("Total Raw (After Decompression)",this.formatBytes(n.bytesInRaw||0)),l("Bandwidth Saved",a,!0,!0),l("Packets Received",n.packetsIn.toLocaleString())];const r=`\n <div class="bandwidth-dashboard">\n <div class="bandwidth-hero">\n <div class="hero-stat ${i?"primary":"secondary"}">\n <div class="hero-value">${i?n.rateOutFormatted:n.rateInFormatted}</div>\n <div class="hero-label">${i?"Upload Rate":"Download Rate"}</div>\n </div>\n <div class="hero-stat success">\n <div class="hero-value">${n.compressionRatio}%</div>\n <div class="hero-label">Compression Ratio</div>\n </div>\n <div class="hero-stat">\n <div class="hero-value">${n.avgPacketSizeFormatted}</div>\n <div class="hero-label">Avg Packet Size</div>\n </div>\n </div>\n\n <div class="bandwidth-details">\n <h5>Bandwidth Details</h5>\n <div class="bandwidth-grid">${o.join("")}</div>\n </div>\n\n ${this.renderBandwidthChart(n.history,i)}\n </div>\n `;t.innerHTML=r}renderBandwidthChart(e,t){if(!e||e.length<2)return`\n <div class="bandwidth-chart-placeholder">\n <p>Collecting data for chart... (${e?e.length:0}/2 points)</p>\n </div>\n `;const n=Math.max(...e.map(e=>t?e.rateOut:e.rateIn),1),i=e.map((i,s)=>`${s/(e.length-1)*100},${40-(t?i.rateOut:i.rateIn)/n*40}`).join(" "),s=this.formatBytes(n);return`\n <div class="bandwidth-chart">\n <h5>Rate History (Last ${15*e.length}s)</h5>\n <div class="chart-container">\n <svg viewBox="0 0 100 40" class="sparkline" preserveAspectRatio="none">\n <polyline\n fill="none"\n stroke="var(--primary-color)"\n stroke-width="1.5"\n points="${i}"\n />\n </svg>\n <div class="chart-labels">\n <span class="chart-max">${s}/s</span>\n <span class="chart-min">0</span>\n </div>\n </div>\n </div>\n `}updatePathAnalyticsDisplay(e){const t=document.getElementById("pathAnalytics");if(!t||!e.pathStats)return;const n=e.pathStats;if(0===n.length)return void(t.innerHTML='\n <div class="path-analytics-empty">\n <p>No path data collected yet. Data will appear once deltas are transmitted.</p>\n </div>\n ');const i=new Set(n.map(e=>e.path.split(".")[0])).size;let s=`\n <div class="path-analytics-dashboard">\n <div class="path-summary">\n <div class="summary-stat">\n <span class="summary-value">${n.length}</span>\n <span class="summary-label">Active Paths</span>\n </div>\n <div class="summary-stat">\n <span class="summary-value">${i}</span>\n <span class="summary-label">Categories</span>\n </div>\n </div>\n\n <div class="path-table-container">\n <table class="path-table">\n <thead>\n <tr>\n <th>Path</th>\n <th>Updates/min</th>\n <th>Data Volume</th>\n <th>% of Total</th>\n </tr>\n </thead>\n <tbody>\n `;n.slice(0,15).forEach(e=>{const t=Math.max(e.percentage,2);s+=`\n <tr>\n <td class="path-name" title="${this.escapeHtml(e.path)}">${this.escapeHtml(e.path)}</td>\n <td class="path-rate">${e.updatesPerMinute}</td>\n <td class="path-bytes">${e.bytesFormatted}</td>\n <td class="path-percentage">\n <div class="percentage-bar-container">\n <div class="percentage-bar" style="width: ${t}%"></div>\n <span class="percentage-text">${e.percentage}%</span>\n </div>\n </td>\n </tr>\n `}),s+="\n </tbody>\n </table>\n </div>\n ",n.length>15&&(s+=`\n <div class="path-more">\n <p>Showing top 15 of ${n.length} paths</p>\n </div>\n `),s+="</div>",t.innerHTML=s}updateCongestionDisplay(e){const t=document.getElementById("congestionSection"),n=document.getElementById("congestionControl");if(!t||!n)return;t.style.display="";const i=!!e.enabled,s=!!e.manualMode,a=i?s?"manual":"active":"disabled",l=i?s?"warning":"success":"error",d=s?"Manual Override":"Automatic",u=e.currentDeltaTimer||0,h=e.nominalDeltaTimer||0,g=`\n <div class="v2-dashboard">\n <div class="metrics-grid">\n ${c("State",`<span class="congestion-state ${l}">${a}</span>`)}\n ${r("Mode",d)}\n ${r("Current Timer",u+" ms")}\n ${r("Nominal Timer",h+" ms")}\n </div>\n <div class="metrics-stats">\n <h5>Congestion Details</h5>\n <div class="stats-grid">\n ${o("Min Delta Timer",(e.minDeltaTimer||0)+" ms")}\n ${o("Max Delta Timer",(e.maxDeltaTimer||0)+" ms")}\n ${o("Target RTT",(e.targetRTT||0)+" ms")}\n ${o("Avg RTT",(void 0!==e.avgRTT?Math.round(e.avgRTT):0)+" ms")}\n ${o("Avg Packet Loss",(void 0!==e.avgLoss?(100*e.avgLoss).toFixed(1):0)+"%",e.avgLoss>.05)}\n </div>\n </div>\n </div>\n `;n.innerHTML=g}updateBondingDisplay(e){const t=document.getElementById("bondingSection"),n=document.getElementById("bondingStatus");if(!t||!n)return;if(!e.enabled)return void(t.style.display="none");t.style.display="";const i=(e.mode||"main-backup").replace(/-/g," "),s=e.activeLink||"primary";let a="";e.links&&(a=Object.entries(e.links).map(([e,t])=>{const n=e===s,i=(t.status||"unknown").toLowerCase(),a="down"!==i?"success":"error";return`\n <div class="bonding-link ${n?"active":""}">\n <div class="link-header">\n <span class="link-name">${this.escapeHtml(e)}</span>\n ${n?'<span class="link-badge active-badge">ACTIVE</span>':""}\n <span class="link-badge ${a}">${this.escapeHtml(i.toUpperCase())}</span>\n </div>\n <div class="link-stats">\n ${o("RTT",(t.rtt||0)+" ms")}\n ${o("Packet Loss",(100*(t.loss||0)).toFixed(1)+"%")}\n </div>\n </div>\n `}).join(""));const c=`\n <div class="v2-dashboard">\n <div class="metrics-grid">\n ${r("Mode",i)}\n ${r("Active Link",s)}\n </div>\n <div class="bonding-links">${a}</div>\n <div style="margin-top: 1rem;">\n <button id="failoverBtn" class="btn btn-secondary">Force Failover</button>\n </div>\n </div>\n `;n.innerHTML=c;const l=document.getElementById("failoverBtn");l&&l.addEventListener("click",()=>this.triggerFailover())}async triggerFailover(){const e=this.activeConnectionId,t=document.getElementById("failoverBtn");t&&(t.disabled=!0);try{const t=await this.request(this.bondingFailoverPath(e),{method:"POST"});if(t.ok){const n=await t.json();this.showNotification(`Failover complete. Active link: ${n.activeLink}`,"success"),this.loadMetrics(e)}else{const e=await t.json();this.showNotification(401===t.status?this.authFailureMessage("triggering failover"):"Failover failed: "+(e.error||"Unknown error"),"error")}}catch(e){const t=e;this.showNotification(t.isUnauthorized?this.authFailureMessage("triggering failover"):"Failover failed: "+t.message,"error")}finally{t&&(t.disabled=!1)}}updateMonitoringDisplay(e){const t=document.getElementById("monitoringSection"),n=document.getElementById("monitoringAlerts");if(!t||!n)return;if(!(e.alerts||e.packetLoss||e.retransmissions))return void(t.style.display="none");t.style.display="";let i='<div class="v2-dashboard">';if(e.alerts){const t=e.alerts.activeAlerts||{},n=Object.entries(t).map(([e,t])=>{let n="warning";return"string"==typeof t?n=t.toLowerCase():t&&"object"==typeof t&&t.level&&(n=String(t.level).toLowerCase()),"warn"===n&&(n="warning"),"alert"===n&&(n="critical"),"warning"!==n&&"critical"!==n&&(n="warning"),{metric:e,level:n,value:t&&"object"==typeof t?t.value:void 0}}),a=n.length,o=n.map(e=>{const t=void 0!==e.value?` (${this.escapeHtml(String(e.value))})`:"";return((e,t,n=!1)=>`\n <div class="stat-item${n?" error":""}">\n <span class="stat-label">${s(e)}:</span>\n <span class="stat-value">${t}</span>\n </div>\n`)(e.metric,`<span class="alert-level alert-${e.level}">${this.escapeHtml(e.level.toUpperCase())}${t}</span>`,"critical"===e.level)}).join("");i+=`\n <div class="monitoring-subsection">\n <h5>Active Alerts</h5>\n ${0===a?'<div class="metrics-success"><div class="success-message">No active alerts</div></div>':`<div class="stats-grid">${o}</div>`}\n </div>\n `}if(e.packetLoss&&e.packetLoss.summary){const t=e.packetLoss.summary;i+=`\n <div class="monitoring-subsection">\n <h5>Packet Loss</h5>\n <div class="stats-grid">\n ${o("Overall Loss Rate",(100*t.overallLossRate).toFixed(2)+"%",t.overallLossRate>.05)}\n ${o("Max Loss Rate",(100*t.maxLossRate).toFixed(2)+"%",t.maxLossRate>.1)}\n ${o("Trend",t.trend||"stable")}\n </div>\n </div>\n `}if(e.retransmissions&&e.retransmissions.summary){const t=e.retransmissions.summary;i+=`\n <div class="monitoring-subsection">\n <h5>Retransmission Rates</h5>\n <div class="stats-grid">\n ${o("Current Rate",(100*t.currentRate).toFixed(2)+"%",t.currentRate>.05)}\n ${o("Average Rate",(100*t.avgRate).toFixed(2)+"%")}\n ${o("Max Rate",(100*t.maxRate).toFixed(2)+"%",t.maxRate>.1)}\n </div>\n </div>\n `}i+="</div>",n.innerHTML=i}updateStatus(){const e=document.getElementById("status");if(!e)return;let t="<h4>Configuration Status</h4>";if(this.deltaTimerConfig?t+=`\n <div class="status-item">\n <strong>Delta Timer:</strong> ${this.escapeHtml(String(this.deltaTimerConfig.deltaTimer))}ms\n <span class="status-indicator success">Configured</span>\n </div>\n `:t+='\n <div class="status-item">\n <strong>Delta Timer:</strong>\n <span class="status-indicator warning">Not configured</span>\n </div>\n ',this.subscriptionConfig&&this.subscriptionConfig.subscribe){const e=this.subscriptionConfig;t+=`\n <div class="status-item">\n <strong>Subscriptions:</strong> ${e.subscribe.length} path(s) configured\n <span class="status-indicator success">Configured</span>\n </div>\n <div class="status-details">\n <strong>Context:</strong> ${this.escapeHtml(e.context||"")}<br>\n <strong>Paths:</strong> ${e.subscribe.map(e=>this.escapeHtml(e.path)).join(", ")}\n </div>\n `}else t+='\n <div class="status-item">\n <strong>Subscriptions:</strong>\n <span class="status-indicator warning">Not configured</span>\n </div>\n ';this.sentenceFilterConfig&&this.sentenceFilterConfig.excludedSentences&&this.sentenceFilterConfig.excludedSentences.length>0&&(t+=`\n <div class="status-item">\n <strong>Sentence Filter:</strong> ${this.sentenceFilterConfig.excludedSentences.length} sentence(s) excluded\n <span class="status-indicator success">Configured</span>\n </div>\n <div class="status-details">\n <strong>Excluded:</strong> ${this.sentenceFilterConfig.excludedSentences.map(e=>this.escapeHtml(e)).join(", ")}\n </div>\n `),e.innerHTML=t}buildCompletePluginConfig(e){const t=this.extractSchemaDefaults(this.pluginSchema),n=this.deepMerge(t||{},e||{});if(Array.isArray(n.connections))return n;const i=this.normalizeServerType(n.serverType);return n.serverType=i||"client",n}normalizeServerType(e){return!0===e||"server"===e?"server":!1===e||"client"===e?"client":void 0}extractSchemaDefaults(e){if(!e||"object"!=typeof e)return;const t="object"===e.type||!!e.properties,n={};let i=!1;if(t&&e.default&&this.isPlainObject(e.default)&&(Object.assign(n,this.deepClone(e.default)),i=!0),e.properties&&this.isPlainObject(e.properties))for(const[t,s]of Object.entries(e.properties)){const e=this.extractSchemaDefaults(s);void 0!==e?(n[t]=e,i=!0):s&&"object"===s.type?(n[t]={},i=!0):s&&"string"===s.type&&(n[t]="",i=!0)}if(e.dependencies&&this.isPlainObject(e.dependencies))for(const t of Object.values(e.dependencies)){const e=this.extractSchemaDefaults(t);e&&this.isPlainObject(e)&&(Object.assign(n,this.deepMerge(n,e)),i=!0)}for(const t of["oneOf","anyOf","allOf"]){const s=e[t];Array.isArray(s)&&s.forEach(t=>{const s=this.extractSchemaDefaults(t);if(void 0!==s)return this.isPlainObject(s)?(Object.assign(n,this.deepMerge(n,s)),void(i=!0)):void((i||void 0!==e.default)&&(i=!0))})}return i?n:void 0!==e.default?this.deepClone(e.default):void 0}isPlainObject(e){return null!==e&&"object"==typeof e&&!Array.isArray(e)}deepClone(e){if(Array.isArray(e))return e.map(e=>this.deepClone(e));if(this.isPlainObject(e)){const t={};for(const[n,i]of Object.entries(e))t[n]=this.deepClone(i);return t}return e}deepMerge(e,t){if(void 0===t)return this.deepClone(e);if(Array.isArray(t))return this.deepClone(t);if(this.isPlainObject(e)&&this.isPlainObject(t)){const n=this.deepClone(e);for(const[i,s]of Object.entries(t))n[i]=this.deepMerge(e[i],s);return n}return this.deepClone(t)}formatBytes(e){if(!e||e<=0)return"0 B";const t=["B","KB","MB","GB"],n=Math.min(Math.floor(Math.log(e)/Math.log(1024)),t.length-1);return parseFloat((e/Math.pow(1024,n)).toFixed(2))+" "+t[n]}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}showNotification(e,t="success"){const n=document.getElementById("notification");n&&(this._notificationTimer&&clearTimeout(this._notificationTimer),n.textContent=e,n.className=`notification ${t} show`,this._notificationTimer=setTimeout(()=>{n.classList.remove("show"),this._notificationTimer=null},4e3))}}document.addEventListener("DOMContentLoaded",()=>{window.dataConnectorConfig=new u}),document.addEventListener("visibilitychange",()=>{window.dataConnectorConfig&&(document.hidden?window.dataConnectorConfig.metricsInterval&&(clearInterval(window.dataConnectorConfig.metricsInterval),window.dataConnectorConfig.metricsInterval=null):window.dataConnectorConfig.metricsInterval||(window.dataConnectorConfig.loadMetrics(),window.dataConnectorConfig.startMetricsRefresh()))}),window.addEventListener("beforeunload",()=>{window.dataConnectorConfig&&window.dataConnectorConfig.metricsInterval&&(clearInterval(window.dataConnectorConfig.metricsInterval),window.dataConnectorConfig.metricsInterval=null)})}},i={};function s(e){var t=i[e];if(void 0!==t)return t.exports;var a=i[e]={exports:{}};return n[e](a,a.exports,s),a.exports}s.m=n,s.c=i,s.f={},s.e=e=>Promise.all(Object.keys(s.f).reduce((t,n)=>(s.f[n](e,t),t),[])),s.u=e=>e+".70a0bc6aadb412703390.js",s.miniCssF=e=>{},s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),s.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),e={},t="signalk-edge-link:",s.l=(n,i,a,o)=>{if(e[n])e[n].push(i);else{var r,c;if(void 0!==a)for(var l=document.getElementsByTagName("script"),d=0;d<l.length;d++){var u=l[d];if(u.getAttribute("src")==n||u.getAttribute("data-webpack")==t+a){r=u;break}}r||(c=!0,(r=document.createElement("script")).charset="utf-8",s.nc&&r.setAttribute("nonce",s.nc),r.setAttribute("data-webpack",t+a),r.src=n),e[n]=[i];var h=(t,i)=>{r.onerror=r.onload=null,clearTimeout(g);var s=e[n];if(delete e[n],r.parentNode&&r.parentNode.removeChild(r),s&&s.forEach(e=>e(i)),t)return t(i)},g=setTimeout(h.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=h.bind(null,r.onerror),r.onload=h.bind(null,r.onload),c&&document.head.appendChild(r)}},(()=>{s.S={};var e={},t={};s.I=(n,i)=>{i||(i=[]);var a=t[n];if(a||(a=t[n]={}),!(i.indexOf(a)>=0)){if(i.push(a),e[n])return e[n];s.o(s.S,n)||(s.S[n]={});var o=s.S[n],r="signalk-edge-link",c=[];return"default"===n&&((e,t,n,i)=>{var a=o[e]=o[e]||{},c=a[t];(!c||!c.loaded&&(1!=!c.eager?i:r>c.from))&&(a[t]={get:()=>s.e(540).then(()=>()=>s(6540)),from:r,eager:!1})})("react","16.14.0"),e[n]=c.length?Promise.all(c).then(()=>e[n]=1):1}}})(),(()=>{var e;s.g.importScripts&&(e=s.g.location+"");var t=s.g.document;if(!e&&t&&(t.currentScript&&"SCRIPT"===t.currentScript.tagName.toUpperCase()&&(e=t.currentScript.src),!e)){var n=t.getElementsByTagName("script");if(n.length)for(var i=n.length-1;i>-1&&(!e||!/^http(s?):/.test(e));)e=n[i--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),s.p=e})(),(()=>{var e={792:0};s.f.j=(t,n)=>{var i=s.o(e,t)?e[t]:void 0;if(0!==i)if(i)n.push(i[2]);else{var a=new Promise((n,s)=>i=e[t]=[n,s]);n.push(i[2]=a);var o=s.p+s.u(t),r=new Error;s.l(o,n=>{if(s.o(e,t)&&(0!==(i=e[t])&&(e[t]=void 0),i)){var a=n&&("load"===n.type?"missing":n.type),o=n&&n.target&&n.target.src;r.message="Loading chunk "+t+" failed.\n("+a+": "+o+")",r.name="ChunkLoadError",r.type=a,r.request=o,i[1](r)}},"chunk-"+t,t)}};var t=(t,n)=>{var i,a,[o,r,c]=n,l=0;if(o.some(t=>0!==e[t])){for(i in r)s.o(r,i)&&(s.m[i]=r[i]);c&&c(s)}for(t&&t(n);l<o.length;l++)a=o[l],s.o(e,a)&&e[a]&&e[a][0](),e[a]=0},n=self.webpackChunksignalk_edge_link=self.webpackChunksignalk_edge_link||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})(),s(9217)})();
|
|
2
|
-
//# sourceMappingURL=main.f1780db6593b0c07a48c.js.map
|