UNPKG

@interopio/core

Version:

IOConnect core library

1 lines 190 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):((e="undefined"!=typeof globalThis?globalThis:e||self).core=e.core||{},e.core.min=t())}(this,function(){"use strict";var e=1,t=2,n=3,r=4;function i(i){return i.type===n?"timestamp":i.type===t?"number":i.type===e?"string":i.type===r?"object":"unknown"}function s(e){return e.constructor===Date?"timestamp":"number"==typeof e?"number":"string"==typeof e?"string":"object"==typeof e?"object":"string"}function o(e){const t={},n=i(e);if("object"===n){const n=Object.keys(e.value).reduce((t,n)=>{const r=s(e.value[n]);if("object"===r){const r=a(e.value[n]);t[n]={type:"object",description:"",context:{},composite:r}}else t[n]={type:r,description:"",context:{}};return t},{});t.composite=n}return t.name=c(e.path.join("/")+"/"+e.name),t.type=n,t.description=e.description,t.context={},t}function a(e){return Object.keys(e).reduce((t,n)=>{const r=s(e[n]);return t[n]="object"===r?{type:"object",description:"",context:{},composite:a(e[n])}:{type:r,description:"",context:{}},t},{})}function c(e){return void 0!==e&&e.length>0&&"/"!==e[0]?"/"+e:e}function d(e){return"timestamp"===i(e)?Date.now():u(e.value)}function u(e){return"object"!=typeof e?e:Object.keys(e).reduce((t,n)=>{const r=e[n];return"object"==typeof r&&r.constructor!==Date?t[n]=u(r):r.constructor===Date?t[n]=new Date(r).getTime():r.constructor===Boolean?t[n]=r.toString():t[n]=r,t},{})}function l(e){return e.reduce((e,t)=>e.concat(Array.isArray(t)?l(t):t),[])}function h(e){const t=l(e.root.getAggregateState()),n=t.sort((e,t)=>e.state?t.state?t.state-e.state:-1:1)[0];const r=function(e){let t="";return e.forEach((e,n,r)=>{const i=e.path.join(".");n===r.length-1?t+=i+"."+e.name+": "+e.description:t+=i+"."+e.name+": "+e.description+","}),t.length>100?t.slice(0,100)+"...":t}(t);return{description:r,value:n.state}}var p=(e,t,n)=>{if(null===e||"object"!=typeof e)throw new Error("Missing definition");if(null===t||"object"!=typeof t)throw new Error("Missing parent");if(null===n||"object"!=typeof n)throw new Error("Missing transport")};class g{definition;system;transport;value;type;path=[];name;description;get repo(){return this.system?.repo}get id(){return`${this.system.path}/${name}`}constructor(e,t,n,r,i){this.definition=e,this.system=t,this.transport=n,this.value=r,this.type=i,p(e,t,n),this.path=t.path.slice(0),this.path.push(t.name),this.name=e.name,this.description=e.description,n.createMetric(this)}update(e){return this.value=e,this.transport.updateMetric(this)}}class f extends g{constructor(e,n,r,i){super(e,n,r,i,t)}incrementBy(e){this.update(this.value+e)}increment(){this.incrementBy(1)}decrement(){this.incrementBy(-1)}decrementBy(e){this.incrementBy(-1*e)}}class m extends g{constructor(e,t,n,i){super(e,t,n,i,r)}update(e){return this.mergeValues(e),this.transport.updateMetric(this)}mergeValues(e){return Object.keys(this.value).forEach(t=>{void 0!==e[t]&&(this.value[t]=e[t])})}}class b extends g{constructor(t,n,r,i){super(t,n,r,i,e)}}class v extends g{constructor(e,t,r,i){super(e,t,r,i,n)}now(){this.update(new Date)}}function y(i,s,o,a,c){if(!s)throw new Error("Repository is required");if(!o)throw new Error("Transport is required");const d=o,u=i,l=c||"",h=s,p=a,g=function e(t){if(!t||!t.parent)return[];const n=e(t.parent);return n.push(t.name),n}(a);let w={};const S=(I="/",((_=g)&&_.length>0?_.join(I):"")+i);var _,I;const T=s.root,x=[],P=[];function M(e,t,n,r){let i={name:""};i="string"==typeof e?{name:e}:e;const s=P.filter(e=>e.name===i.name);if(s.length>0){const e=s[0];if(e.type!==t)throw new Error(`A metric named ${i.name} is already defined with different type.`);return void 0!==n&&e.update(n).catch(()=>{}),e}const o=r(i);return P.push(o),o}const C={get name(){return u},get description(){return l},get repo(){return h},get parent(){return p},path:g,id:S,root:T,get subSystems(){return x},get metrics(){return P},subSystem:function(e,t){if(!e||0===e.length)throw new Error("name is required");const n=x.filter(t=>t.name===e);if(n.length>0)return n[0];const r=y(e,h,d,C,t);return x.push(r),r},getState:()=>w,setState:function(e,t){w={state:e,description:t},d.updateSystem(C,w)},stringMetric:function(t,n){return M(t,e,n,e=>new b(e,C,d,n))},timestampMetric:function(e,t){return M(e,n,t,e=>new v(e,C,d,t))},objectMetric:function(e,t){return M(e,r,t,e=>new m(e,C,d,t))},numberMetric:function(e,n){return M(e,t,n,e=>new f(e,C,d,n))},getAggregateState:function(){const e=[];return Object.keys(w).length>0&&e.push({name:u,path:g,state:w.state,description:w.description}),x.forEach(t=>{const n=t.getAggregateState();n.length>0&&e.push(...n)}),e}};return d.createSystem(C),C}class w{root;constructor(e,t){t.init(this),this.root=y("",this,t),this.addSystemMetrics(this.root,e.clickStream||void 0===e.clickStream)}addSystemMetrics(e,t){if("undefined"!=typeof navigator&&e.stringMetric("UserAgent",navigator.userAgent),t&&"undefined"!=typeof document){const t=e.subSystem("ClickStream"),n=e=>{if(!e.target)return;const n=e.target,r=n?n.getAttribute("class")??"":"";t.objectMetric("LastBrowserEvent",{type:"click",timestamp:new Date,target:{className:r,id:n.id,type:"<"+n.tagName.toLowerCase()+">",href:n.href||""}})};t.objectMetric("Page",{title:document.title,page:window.location.href}),document.addEventListener?document.addEventListener("click",n):document.attachEvent("onclick",n)}e.stringMetric("StartTime",(new Date).toString());const n=e.stringMetric("StartURL",""),r=e.stringMetric("AppName","");if("undefined"!=typeof window){if(void 0!==window.location){const e=window.location.href;n.update(e)}void 0!==window.glue42gd&&r.update(window.glue42gd.appName)}}}class S{init(e){}createSystem(e){return Promise.resolve()}updateSystem(e,t){return Promise.resolve()}createMetric(e){return Promise.resolve()}updateMetric(e){return Promise.resolve()}}class _{api;lastCount=0;initialPublishTimeout=1e4;publishInterval=6e4;system;constructor(e,t,n){this.api=e,this.initialPublishTimeout=t??this.initialPublishTimeout,this.publishInterval=n??this.publishInterval,this.scheduleCollection(),this.system=this.api.subSystem("performance","Performance data published by the web application")}scheduleCollection(){setTimeout(()=>{this.collect(),setInterval(()=>{this.collect()},this.publishInterval)},this.initialPublishTimeout)}collect(){try{this.collectMemory(),this.collectEntries()}catch{}}collectMemory(){const e=window.performance;if(!e||!e.memory)return;const t=e.memory;this.system.stringMetric("memory",JSON.stringify({totalJSHeapSize:t.totalJSHeapSize,usedJSHeapSize:t.usedJSHeapSize}))}collectEntries(){const e=window.performance.getEntries();if(e.length<=this.lastCount)return;this.lastCount=e.length;const t=e.map(e=>e.toJSON());this.system.stringMetric("entries",JSON.stringify(t))}}var I=e=>{let t;t=e.connection&&"object"==typeof e.connection?function(e,t){if(!e||"object"!=typeof e)throw new Error("Connection is required parameter");let n,r;const i=e=>{s(e.root)},s=e=>{a(e),e.metrics.forEach(e=>{u(e)}),e.subSystems.forEach(e=>{s(e)})},a=async e=>{if(void 0===e.parent)return;await n;const i={type:"define",metrics:[{name:c(e.path.join("/")+"/"+e.name+"/State"),type:"object",composite:{Description:{type:"string",description:""},Value:{type:"number",description:""}},description:"System state",context:{}}]};r.sendFireAndForget(i).catch(n=>{t.logger.warn(`Failed to send define for system state metric of ${e.name}: ${JSON.stringify(n)}`)})},u=async e=>{const i=p(e);await n;const s={type:"define",metrics:[o(i)]};r.sendFireAndForget(s).catch(n=>{t.logger.warn(`Failed to send define for metric ${e.name}: ${JSON.stringify(n)}`)}),void 0!==i.value&&l(i)},l=e=>{if(g()){const n=d(e),i={type:"publish",values:[{name:c(e.path.join("/")+"/"+e.name),value:n,timestamp:Date.now()}]};return r.sendFireAndForget(i).catch(n=>{t.logger.warn(`Failed to publish metric ${e.name}: ${JSON.stringify(n)}`)})}return Promise.resolve()},p=e=>{const t={...e};return"object"==typeof e.value&&null!==e.value&&(t.value={...e.value}),t},g=()=>{try{return(t.canUpdateMetric??(()=>!0))()}catch{return!0}};return{init:s=>{let o;n=new Promise(e=>{o=e}),r=e.domain("metrics"),r.onJoined(e=>{!e&&o&&(o(),o=void 0);const n={type:"define",metrics:[{name:"/State",type:"object",composite:{Description:{type:"string",description:""},Value:{type:"number",description:""}},description:"System state",context:{}}]};r.sendFireAndForget(n).catch(e=>{t.logger.warn(`Failed to send define for root state metric: ${JSON.stringify(e)}`)}),e&&i(s)}),r.join({system:t.system,service:t.service,instance:t.instance})},createSystem:a,updateSystem:async(i,s)=>{await n;const o={type:"publish",values:[{name:c(i.path.join("/")+"/"+i.name+"/State"),value:{Description:s.description,Value:s.state},timestamp:Date.now()}]};r.sendFireAndForget(o).catch(e=>{t.logger.warn(`Failed to send update for system state metric of ${i.name}: ${JSON.stringify(e)}`)});const a=h(i),d={type:"publish",peer_id:e.peerId,values:[{name:"/State",value:{Description:a.description,Value:a.value},timestamp:Date.now()}]};r.sendFireAndForget(d).catch(e=>{t.logger.warn(`Failed to send update for root state metric of ${i.name}: ${JSON.stringify(e)}`)})},createMetric:u,updateMetric:async e=>{const t=p(e);await n,l(t)}}}(e.connection,e):new S;let n=new w(e,t).root;e.disableAutoAppSystem||(n=n.subSystem("App"));const r=function(e){const t=e.subSystem("reporting"),n={name:"features"};let r;const i=(e,i,s)=>{if(void 0===e||""===e)throw new Error("name is mandatory");if(void 0===i||""===i)throw new Error("action is mandatory");if(void 0===s||""===s)throw new Error("payload is mandatory");r?r.update({name:e,action:i,payload:s}):r=t.objectMetric(n,{name:e,action:i,payload:s})};return e.featureMetric=i,e}(n);return function(e,t){if("undefined"==typeof window)return;const n=window?.glue42gd?.metrics?.pagePerformanceMetrics;n&&(t=n);t?.enabled&&new _(e,t.initialPublishTimeout,t.publishInterval)}(r,e.pagePerformanceMetrics),r};var T,x,P="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function M(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var C=function(){if(x)return T;function e(e){if(e&&e.errorHandling&&"function"!=typeof e.errorHandling&&"log"!==e.errorHandling&&"silent"!==e.errorHandling&&"throw"!==e.errorHandling)throw new Error('Invalid options passed to createRegistry. Prop errorHandling should be ["log" | "silent" | "throw" | (err) => void], but '+typeof e.errorHandling+" was passed");var t=e&&"function"==typeof e.errorHandling&&e.errorHandling,n={};function r(n,r){var i=n instanceof Error?n:new Error(n);if(t)t(i);else{var s='[ERROR] callback-registry: User callback for key "'+r+'" failed: '+i.stack;if(e)switch(e.errorHandling){case"log":return console.error(s);case"silent":return;case"throw":throw new Error(s)}console.error(s)}}return{add:function(e,t,i){var s=n[e];return s||(s=[],n[e]=s),s.push(t),i&&setTimeout(function(){i.forEach(function(i){var s;if(null===(s=n[e])||void 0===s?void 0:s.includes(t))try{Array.isArray(i)?t.apply(void 0,i):t.apply(void 0,[i])}catch(t){r(t,e)}})},0),function(){var r=n[e];r&&(0===(r=r.reduce(function(e,n,r){return n===t&&e.length===r||e.push(n),e},[])).length?delete n[e]:n[e]=r)}},execute:function(e){for(var t=[],i=1;i<arguments.length;i++)t[i-1]=arguments[i];var s=n[e];if(!s||0===s.length)return[];var o=[];return s.forEach(function(n){try{var i=n.apply(void 0,t);o.push(i)}catch(t){o.push(void 0),r(t,e)}}),o},clear:function(){n={}},clearKey:function(e){n[e]&&delete n[e]}}}return x=1,e.default=e,T=e}(),O=M(C);class k{gw;registry=O();client;constructor(e,t){this.gw=e.facade,this.gw.connect((e,t)=>{this.messageHandler(t)}).then(e=>{this.client=e})}get isObjectBasedTransport(){return!0}sendObject(e){return this.client?(this.client.send(e),Promise.resolve(void 0)):Promise.reject("not connected")}send(e){return Promise.reject("not supported")}onMessage(e){return this.registry.add("onMessage",e)}onConnectedChanged(e){return e(!0),()=>{}}close(){return Promise.resolve()}open(){return Promise.resolve()}name(){return"in-memory"}reconnect(){return Promise.resolve()}messageHandler(e){this.registry.execute("onMessage",e)}}class j{logger;worker;registry=O();constructor(e,t){this.logger=t,this.worker=new SharedWorker(e),this.worker.port.onmessage=e=>{this.messageHandler(e.data)}}get isObjectBasedTransport(){return!0}sendObject(e){return this.worker.port.postMessage(e),Promise.resolve()}send(e){return Promise.reject("not supported")}onMessage(e){return this.registry.add("onMessage",e)}onConnectedChanged(e){return e(!0),()=>{}}close(){return Promise.resolve()}open(){return Promise.resolve()}name(){return"shared-worker"}reconnect(){return Promise.resolve()}messageHandler(e){this.registry.execute("onMessage",e)}}class A{static isNode(){if(void 0!==A._isNode)return A._isNode;if("undefined"!=typeof window)return A._isNode=!1,!1;try{A._isNode="[object process]"===Object.prototype.toString.call(global.process)}catch(e){A._isNode=!1}return A._isNode}static _isNode;static getMethodName(e){return"string"==typeof e?e:e?.name}}class E{static delay(e){return new Promise(t=>setTimeout(t,e))}resolve;reject;promise;rejected=!1;resolved=!1;get ended(){return this.rejected||this.resolved}constructor(){this.promise=new Promise((e,t)=>{this.resolve=t=>{this.resolved=!0,e(t)},this.reject=e=>{this.rejected=!0,t(e)}})}}const R={};function N(e){const t=R[e];if(t)return t;const n=[];function r(){return(new Date).getTime()}const i=r();let s,o;function a(e,t){const i=t??r();let s=0;n.length>0&&(s=i-n[n.length-1].time),n.push({name:e,time:i,diff:s})}a("start",i);const c={get startTime(){return i},get endTime(){return s},get period(){return o},stop:function(){return s=r(),a("end",s),o=s-i,o},mark:a,marks:n};return R[e]=c,c}const L=A.isNode()?require("ws"):window.WebSocket;function D(e,t,n,r){const i=!1!==r?.includeStack,s=e instanceof Error?e:e?.error;return s instanceof Error?JSON.stringify({name:s.name,message:s.message,code:s.code,stack:i?s.stack:void 0}):JSON.stringify({type:e?.type,readyState:t?.readyState,url:n,message:"string"==typeof e?.message?e.message:void 0})}class F{ws;logger;settings;startupTimer=N("connection");_running=!0;_registry=O();wsRequests=[];constructor(e,t){if(this.settings=e,this.logger=t,!this.settings.ws)throw new Error("ws is missing")}onMessage(e){return this._registry.add("onMessage",e)}send(e,t){return new Promise((t,n)=>{this.waitForSocketConnection(()=>{try{this.ws?.send(e),t()}catch(e){n(e)}},n)})}open(){return this.logger.info("opening ws..."),this._running=!0,new Promise((e,t)=>{this.waitForSocketConnection(e,t)})}close(){return this._running=!1,this.ws&&this.ws.close(),Promise.resolve()}onConnectedChanged(e){return this._registry.add("onConnectedChanged",e)}name(){return this.settings.ws}reconnect(){this.ws?.close();const e=new E;return this.waitForSocketConnection(()=>{e.resolve()}),e.promise}waitForSocketConnection(e,t){t=t??(()=>{}),this._running?1!==this.ws?.readyState?(this.wsRequests.push({callback:e,failed:t}),this.wsRequests.length>1||this.openSocket()):e():t(`wait for socket on ${this.settings.ws} failed - socket closed by user`)}async openSocket(e,t){this.logger.info(`opening ws to ${this.settings.ws}, retryInterval: ${e}, retriesLeft: ${t}...`),this.startupTimer.mark("opening-socket"),void 0===e&&(e=this.settings.reconnectInterval),void 0===t&&(t=this.settings.reconnectAttempts);try{await this.initiateSocket(),this.startupTimer.mark("socket-initiated"),this.notifyForSocketState()}catch{if(void 0!==t&&t<=0)return void this.notifyForSocketState(`wait for socket on ${this.settings.ws} failed - no more retries left`);void 0!==t&&this.logger.debug(`will retry ${t-1} more times (every ${e} ms)`),setTimeout(()=>{const n=void 0===t?void 0:t-1;this.openSocket(e,n)},e)}}initiateSocket(){const e=new E;this.logger.debug(`initiating ws to ${this.settings.ws}...`),this.ws=new L(this.settings.ws??"");let t=!1;return this.ws.onerror=n=>{const r=D(n,this.ws,this.settings.ws);this.logger.info(`ws error - ${r}`),e.reject("error"),t&&(t=!1,this.notifyForSocketState("error"));const i=D(n,this.ws,this.settings.ws,{includeStack:!1});this.notifyStatusChanged(!1,i)},this.ws.onclose=n=>{var r;this.logger.info("ws closed - "+(r=n,`code: ${r?.code} reason: ${r?.reason||"(none)"} wasClean: ${r?.wasClean}`)),e.reject("closed"),t&&(t=!1,this.notifyForSocketState("closed")),this.notifyStatusChanged(!1)},this.ws.onopen=()=>{this.startupTimer.mark("ws-opened"),this.logger.info(`ws opened ${this.settings.identity?.application}`),e.resolve(),t=!0,this.notifyStatusChanged(!0)},this.ws.onmessage=e=>{this._registry.execute("onMessage",e.data)},e.promise}notifyForSocketState(e){this.wsRequests.forEach(t=>{e?t.failed&&t.failed(e):t.callback()}),this.wsRequests=[]}notifyStatusChanged(e,t){this._registry.execute("onConnectedChanged",e,t)}}class ${specs;specsNames=[];messages={};isDone;subs={};subsRefCount={};connection;constructor(e){this.specs={};for(const t of e)this.specs[t.name]=t,this.specsNames.push(t.name)}init(e){this.connection=e;for(const t of this.specsNames)for(const n of this.specs[t].types){let t=this.subsRefCount[n];if(t||(t=0),t+=1,this.subsRefCount[n]=t,t>1)continue;const r=e.on(n,e=>this.processMessage(n,e));this.subs[n]=r}}processMessage(e,t){if(!this.isDone&&t)for(const n of this.specsNames)if(-1!==this.specs[n].types.indexOf(e)){const e=this.messages[n]||[];this.messages[n]=e,e.push(t)}}drain(e,t){t&&(this.messages[e]||[]).forEach(t),delete this.messages[e];for(const t of this.specs[e].types)this.subsRefCount[t]-=1,this.subsRefCount[t]<=0&&(this.connection?.off(this.subs[t]),delete this.subs[t],delete this.subsRefCount[t]);delete this.specs[e],this.specs.length||(this.isDone=!0)}}let H=(e=21)=>{let t="",n=0|e;for(;n--;)t+="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"[64*Math.random()|0];return t};const q=(e,t,n)=>new Promise((r,i)=>{const s=setTimeout(()=>{i(n||`Promise timeout hit: ${t}`)},t);new Promise(e).then(e=>{clearTimeout(s),r(e)}).catch(e=>{clearTimeout(s),i(e)})});class B{settings;logger;identity;isPreferredActivated;_connectionProtocolVersion;_communicationId;publicWindowId;selfAssignedWindowId;iAmConnected=!1;parentReady=!1;rejected=!1;parentPingResolve;parentPingInterval;connectionResolve;extConnectionResolve;extConnectionReject;connectionReject;port;myClientId;extContentAvailable=!1;extContentConnecting=!1;extContentConnected=!1;parentWindowId;parentInExtMode=!1;webNamespace="g42_core_web";parent;parentType;parentPingTimeout=5e3;connectionRequestTimeout=7e3;defaultTargetString="*";registry=O();messages={connectionAccepted:{name:"connectionAccepted",handle:this.handleConnectionAccepted.bind(this)},connectionRejected:{name:"connectionRejected",handle:this.handleConnectionRejected.bind(this)},connectionRequest:{name:"connectionRequest",handle:this.handleConnectionRequest.bind(this)},parentReady:{name:"parentReady",handle:()=>{}},parentPing:{name:"parentPing",handle:this.handleParentPing.bind(this)},platformPing:{name:"platformPing",handle:this.handlePlatformPing.bind(this)},platformReady:{name:"platformReady",handle:this.handlePlatformReady.bind(this)},clientUnload:{name:"clientUnload",handle:()=>{}},manualUnload:{name:"manualUnload",handle:this.handleManualUnload.bind(this)},extConnectionResponse:{name:"extConnectionResponse",handle:this.handleExtConnectionResponse.bind(this)},extSetupRequest:{name:"extSetupRequest",handle:this.handleExtSetupRequest.bind(this)},gatewayDisconnect:{name:"gatewayDisconnect",handle:this.handleGatewayDisconnect.bind(this)},gatewayInternalConnect:{name:"gatewayInternalConnect",handle:this.handleGatewayInternalConnect.bind(this)}};constructor(e,t,n){this.settings=e,this.logger=t,this.identity=n,this.extContentAvailable=!!window.glue42ext,this.setUpMessageListener(),this.setUpUnload(),this.setupPlatformUnloadListener(),this.parentType=window.name.includes("#wsp")?"workspace":void 0}manualSetReadyState(){this.iAmConnected=!0,this.parentReady=!0}get transportWindowId(){return this.publicWindowId}get communicationId(){return this._communicationId}async sendObject(e){if(this.extContentConnected)return window.postMessage({glue42ExtOut:e},window.origin);if(!this.port)throw new Error("Cannot send message, because the port was not opened yet");this.port.postMessage(e)}get isObjectBasedTransport(){return!0}onMessage(e){return this.registry.add("onMessage",e)}send(){return Promise.reject("not supported")}onConnectedChanged(e){return this.registry.add("onConnectedChanged",e)}async open(){this.logger.debug("opening a connection to the web platform gateway."),await this.connect(),this.notifyStatusChanged(!0)}close(){this.logger.debug(`closing connection - clientId: ${this.myClientId}, windowId: ${this.identity?.windowId||"unknown"}, client connected: ${this.iAmConnected}`);const e={glue42core:{type:this.messages.gatewayDisconnect.name,data:{clientId:this.myClientId,ownWindowId:this.identity?.windowId}}};return this.port?.postMessage(e),this.parentReady=!1,this.notifyStatusChanged(!1,"manual reconnection"),Promise.resolve()}name(){return"web-platform"}async reconnect(){return await this.close(),Promise.resolve()}initiateInternalConnection(){return new Promise((e,t)=>{this.logger.debug("opening an internal web platform connection"),this.port=this.settings.port,this.iAmConnected?this.logger.warn("cannot open a new connection, because this client is currently connected"):(this.port.onmessage=n=>{if(this.iAmConnected&&!n.data?.glue42core)return void this.registry.execute("onMessage",n.data);const r=n.data?.glue42core;r&&(r.type===this.messages.gatewayInternalConnect.name&&r.success&&(this.publicWindowId=this.settings.windowId,this.identity&&this.publicWindowId&&(this.identity.windowId=this.publicWindowId,this.identity.instance=this.publicWindowId),e()),r.type===this.messages.gatewayInternalConnect.name&&r.error&&t(r.error))},this.port.postMessage({glue42core:{type:this.messages.gatewayInternalConnect.name}}))})}initiateRemoteConnection(e){return q((t,n)=>{this.connectionResolve=t,this.connectionReject=n,this.myClientId=this.myClientId??H(10);const r=this.getMyWindowId()||H(10),i={glue42core:{type:this.messages.connectionRequest.name,clientId:this.myClientId,clientType:"child",bridgeInstanceId:r,selfAssignedWindowId:this.selfAssignedWindowId}};if(this.logger.debug(`sending connection request - clientId: ${this.myClientId}`),this.extContentConnecting)return i.glue42core.clientType="child",i.glue42core.bridgeInstanceId=this.myClientId,i.glue42core.parentWindowId=this.parentWindowId,window.postMessage(i,window.origin);if(!e)throw new Error("Cannot send a connection request, because no glue target was specified!");e.postMessage(i,this.defaultTargetString)},this.connectionRequestTimeout,"The connection to the target glue window timed out")}async isParentCheckSuccess(e){try{return await e,{success:!0}}catch(e){return{success:!1}}}setUpMessageListener(){this.settings.port?this.logger.debug("skipping generic message listener, because this is an internal client"):(this.logger.debug("setting up window message listener"),window.addEventListener("message",e=>{const t=e.data?.glue42core;if(!t||this.rejected)return;const n=this.settings.allowedOrigins||[];if(n.length&&!n.includes(e.origin))return void this.logger.warn(`received a message from an origin which is not in the allowed list: ${e.origin}`);if(!this.checkMessageTypeValid(t.type))return void this.logger.error(`cannot handle the incoming glue42 core message, because the type is invalid: ${t.type}`);const r=t.type;this.logger.debug(`received valid glue42core message of type: ${r}`),this.messages[r].handle(e)}))}setUpUnload(){this.settings.port?this.logger.debug("skipping unload event listener, because this is an internal client"):(this.logger.debug("setting up unload event listeners"),window.addEventListener("beforeunload",()=>{this._connectionProtocolVersion||this.signalClientDisappearing()}),window.addEventListener("pagehide",()=>{this._connectionProtocolVersion&&this.signalClientDisappearing()}))}signalClientDisappearing(){if(this.extContentConnected)return;this.logger.debug(`signaling client disappearing for clientId: ${this.myClientId}`);const e={glue42core:{type:this.messages.clientUnload.name,data:{clientId:this.myClientId,ownWindowId:this.identity?.windowId}}};this.parent?.postMessage(e,this.defaultTargetString),this.port?.postMessage(e)}handlePlatformReady(e){this.logger.debug("the web platform gave the ready signal"),this.parentReady=!0,this.parentPingResolve&&(this.parentPingResolve(),delete this.parentPingResolve),this.parentPingInterval&&(clearInterval(this.parentPingInterval),delete this.parentPingInterval),this.parent=e.source,this.parentType=window.name.includes("#wsp")?"workspace":"window"}handleConnectionAccepted(e){const t=e.data?.glue42core;return this.myClientId!==t.clientId?this.logger?.debug(`ignoring a connection accepted signal, because it is not targeted at me. My id: ${this.myClientId}, the id in the message: ${t.clientId}`):this.handleAcceptanceOfMyRequest(t)}handleAcceptanceOfMyRequest(e){if(this.logger.debug("handling a connection accepted signal targeted at me."),this.isPreferredActivated=e.isPreferredActivated,this.extContentConnecting)return this.processExtContentConnection(e);if(e.port){if(this._connectionProtocolVersion=e.connectionProtocolVersion,this.publicWindowId=this.getMyWindowId(),this.identity&&(this.identity.windowId=this.publicWindowId,this.identity.instance=this.identity.instance?this.identity.instance:this.publicWindowId||H(10)),this.identity&&e.appName&&(this.identity.application=e.appName,this.identity.applicationName=e.appName),this._communicationId=e.communicationId,this.port=e.port,this.port.onmessage=e=>this.registry.execute("onMessage",e.data),this.connectionResolve)return this.logger.debug("my connection is set up, calling the connection resolve."),this.connectionResolve(),void delete this.connectionResolve;this.logger.error("unable to call the connection resolve, because no connection promise was found")}else this.logger.error("cannot set up my connection, because I was not provided with a port")}processExtContentConnection(e){if(this.logger.debug("handling a connection accepted signal targeted at me for extension content connection."),this.extContentConnecting=!1,this.extContentConnected=!0,this.publicWindowId=this.parentWindowId||this.myClientId,this.extContentConnecting&&this.identity&&(this.identity.windowId=this.publicWindowId),this.identity&&e.appName&&(this.identity.application=e.appName,this.identity.applicationName=e.appName),window.addEventListener("message",e=>{const t=e.data?.glue42ExtInc;if(!t)return;const n=this.settings.allowedOrigins||[];!n.length||n.includes(e.origin)?this.registry.execute("onMessage",t):this.logger.warn(`received a message from an origin which is not in the allowed list: ${e.origin}`)}),this.connectionResolve)return this.logger.debug("my connection is set up, calling the connection resolve."),this.connectionResolve(),void delete this.connectionResolve}handleConnectionRejected(e){if(this.logger.debug("handling a connection rejection. Most likely the reason is that this window was not created by a glue API call"),!this.connectionReject)return;const t="string"==typeof e.data.glue42core?.error?`Connection was rejected. ${e.data.glue42core?.error}`:"The platform connection was rejected. Most likely because this window was not created by a glue API call";this.connectionReject(t),delete this.connectionReject}handleConnectionRequest(){this.extContentConnecting&&this.logger.debug("This connection request event is targeted at the extension content")}handleParentPing(e){if(!this.parentReady)return void this.logger.debug("my parent is not ready, I am ignoring the parent ping");if(!this.iAmConnected)return void this.logger.debug("i am not fully connected yet, I am ignoring the parent ping");const t={glue42core:{type:this.messages.parentReady.name}};this.extContentConnected&&(t.glue42core.extMode={windowId:this.myClientId});const n=e.source;this.logger.debug("responding to a parent ping with a ready message"),n.postMessage(t,e.origin)}setupPlatformUnloadListener(){this.logger.debug("setting up platform unload listener"),this.onMessage(e=>{"platformUnload"===e.type&&(this.logger.debug("detected a web platform unload"),this.parentReady=!1,this.notifyStatusChanged(!1,"Gateway unloaded"))})}handleManualUnload(){this.logger.debug("handling manual unload");const e={glue42core:{type:this.messages.clientUnload.name,data:{clientId:this.myClientId,ownWindowId:this.identity?.windowId}}};if(this.extContentConnected)return window.postMessage({glue42ExtOut:e},window.origin);this.port?.postMessage(e)}handlePlatformPing(){}notifyStatusChanged(e,t){this.logger.debug(`status changed - connected: ${e}, reason: ${t||"none"}`),this.iAmConnected=e,this.registry.execute("onConnectedChanged",e,t)}checkMessageTypeValid(e){return"string"==typeof e&&!!this.messages[e]}requestConnectionPermissionFromExt(){return this.waitForContentScript().then(()=>q((e,t)=>{this.extConnectionResolve=e,this.extConnectionReject=t;this.logger.debug("permission request to the extension content script was sent"),window.postMessage({glue42core:{type:"extSetupRequest"}},window.origin)},this.parentPingTimeout,"Cannot initialize glue, because this app was not opened or created by a Glue Client and the request for extension connection timed out"))}handleExtConnectionResponse(e){const t=e.data?.glue42core;if(!t.approved)return this.extConnectionReject?this.extConnectionReject("Cannot initialize glue, because this app was not opened or created by a Glue Client and the request for extension connection was rejected"):void 0;this.extConnectionResolve&&(this.extConnectionResolve(),delete this.extConnectionResolve),this.extContentConnecting=!0,this.parentType="extension",this.logger.debug("The extension connection was approved, proceeding.")}handleExtSetupRequest(){}handleGatewayDisconnect(){}handleGatewayInternalConnect(){}waitForContentScript(){return!!window.glue42ext?.content?Promise.resolve():q(e=>{window.addEventListener("Glue42EXTReady",()=>{e()})},this.connectionRequestTimeout,"The content script was available, but was never heard to be ready")}async connect(){if(this.settings.port)return await this.initiateInternalConnection(),void this.logger.debug("internal web platform connection completed");this.logger.debug("opening a client web platform connection"),await this.findParent(),await this.initiateRemoteConnection(this.parent),this.logger.debug("the client is connected")}async findParent(){const e="Cannot initiate glue, because this window was not opened or created by a glue client",t=this.getPossibleParentsInWindow(window),n=this.getPossibleParentsOutsideWindow(window.top?.opener,window.top),r=new Set([...t,...n]);if(!r.size&&!this.extContentAvailable)throw new Error(e);if(!r.size&&this.extContentAvailable)return void await this.requestConnectionPermissionFromExt();if((await this.isParentCheckSuccess(this.confirmParent(Array.from(r)))).success)this.logger.debug("The default parent was found!");else{if(!this.extContentAvailable)throw new Error(e);await this.requestConnectionPermissionFromExt()}}getPossibleParentsInWindow(e){return e?.parent&&e!==e.parent?[e.parent,...this.getPossibleParentsInWindow(e.parent)]:[]}getPossibleParentsOutsideWindow(e,t){return e&&t&&e!==t?[e,...this.getPossibleParentsInWindow(e),...this.getPossibleParentsOutsideWindow(e.opener,e)]:[]}confirmParent(e){const t=q(t=>{this.parentPingResolve=t;const n={glue42core:{type:this.messages.platformPing.name}};this.parentPingInterval=setInterval(()=>{e.forEach(e=>{e.postMessage(n,this.defaultTargetString)})},1e3)},this.parentPingTimeout,"Cannot initiate glue, because this window was not opened or created by a glue client");return t.catch(()=>{this.parentPingInterval&&(clearInterval(this.parentPingInterval),delete this.parentPingInterval)}),t}getMyWindowId(){return"workspace"===this.parentType?window.name.substring(0,window.name.indexOf("#wsp")):window===window.top?window.name?.includes("g42")?window.name:(this.selfAssignedWindowId=this.selfAssignedWindowId||`g42-${H(10)}`,this.selfAssignedWindowId):void 0}}class U{minSequenceInterval;queue=[];isExecutingQueue=!1;constructor(e=0){this.minSequenceInterval=e}enqueue(e){return new Promise((t,n)=>{this.queue.push({action:e,resolve:t,reject:n}),this.executeQueue()})}async executeQueue(){if(!this.isExecutingQueue){for(this.isExecutingQueue=!0;this.queue.length;){const e=this.queue.shift();if(!e)return void(this.isExecutingQueue=!1);try{const t=await e.action();e.resolve(t)}catch(t){e.reject(t)}await this.intervalBreak()}this.isExecutingQueue=!1}}intervalBreak(){return new Promise(e=>setTimeout(e,this.minSequenceInterval))}}function W(e,t,n,r,i){null==e&&(e="global"),r=r??["success"],i=i??["error"];let s,o="global"===e,a=!1,c=!1;const d=O();t.disconnected(function(){n.debug("connection is down"),c=!1,o=!1,a=!0,Object.keys(u).forEach(e=>{const t=u[e];t&&(n.trace(`failing pending request ${e} due to connection lost`),t.error({err:"Connection lost - gateway connection was disconnected"}))}),d.execute("onLeft",{disconnected:!0})}),t.loggedIn(async function(){if(c=!0,a){n.debug("connection is now up - trying to reconnect...");try{await l(s)}catch{n.trace("failed to reconnect")}}}),t.on("success",e=>g(e)),t.on("error",e=>p(e)),t.on("result",e=>g(e)),r&&r.forEach(e=>{t.on(e,e=>g(e))}),i&&i.forEach(e=>{t.on(e,e=>p(e))});const u={};function l(t){return s=t,new Promise((r,i)=>{if(o)return void r({});let s;if("global"===e)s=c?Promise.resolve({}):Promise.reject("not connected to gateway");else{n.debug(`joining domain ${e}`);s=b({type:"join",destination:e,domain:"global",options:t})}s.then(()=>{!function(){n.debug("did join "+e),o=!0;const t=a;a=!1,d.execute("onJoined",t)}(),r({})}).catch(t=>{n.debug("error joining "+e+" domain: "+JSON.stringify(t)),i(t)})})}function h(e){return o&&e(!1),d.add("onJoined",e)}function p(t){if(e!==t.domain)return;const n=t.request_id;if(!n)return;const r=u[n];r&&r.error(t)}function g(t){if(t.domain!==e)return;const n=t.request_id;if(!n)return;const r=u[n];r&&r.success(t)}function f(){return H(10)}let m=[];function b(r,i,s){if(r.type&&-1===["hello","join"].indexOf(r.type)&&!o){console.warn(`trying to send a message (${r.domain} ${r.type}) but not connected, will queue`);const e=new E;if(m.push({msg:r,tag:i,options:s,pw:e}),1===m.length){const e=h(()=>{n.info(`joined - will now send queued messages (${m.length} -> [${m.map(e=>e.msg.type)}])`),m.forEach(e=>{b(e.msg,e.tag,e.options).then(t=>e.pw.resolve(t)).catch(t=>e.pw.reject(t))}),m=[],e()})}return e.promise}s=s??{},r.request_id=r.request_id??f(),r.domain=r.domain??e,s.skipPeerId||(r.peer_id=t.peerId);const a=r.request_id;return new Promise((e,n)=>{u[a]={success:t=>{delete u[a],t._tag=i,e(t)},error:e=>{console.warn(`Gateway error - ${JSON.stringify(e)}`),delete u[a],e._tag=i,n(e)}},t.send(r,s).catch(e=>{u[a]?.error({err:e})})})}return{join:l,leave:function(){return"global"===e?Promise.resolve():o?(n.debug("stopping session "+e+"..."),a=!1,b({type:"leave",destination:e,domain:"global"}).then(()=>{o=!1,d.execute("onLeft")}).catch(()=>{o=!1,d.execute("onLeft")})):(a=!1,Promise.resolve())},onJoined:h,onLeft:function(e){return o||e(),d.add("onLeft",e)},send:b,sendFireAndForget:function(n){return n.request_id=n.request_id?n.request_id:f(),n.domain=n.domain??e,n.peer_id=t.peerId,t.send(n)},on:(r,i)=>{t.on(r,t=>{if(t.domain===e)try{i(t)}catch(e){n.error(`Callback failed: ${e} \n ${e.stack} \n msg was: ${JSON.stringify(t)}`,e)}})},loggedIn:e=>t.loggedIn(e),connected:e=>t.connected(e),disconnected:e=>t.disconnected(e),get peerId(){return t.peerId},get domain(){return e}}}function J(e){if(e instanceof Error)return e;if("string"==typeof e)return new Error(e);const t=e,n="string"==typeof t?.message?t.message:void 0,r="string"==typeof t?.reason?t.reason:void 0;return void 0!==n&&n.length>0?new Error(n):void 0!==r&&r.length>0?new Error(r):""===n||""===r?new Error(""):new Error(function(e){try{const t=new WeakSet,n=JSON.stringify(e,(e,n)=>{if("bigint"==typeof n)return`${n.toString()}n`;if("function"==typeof n)return"[Function]";if("symbol"==typeof n)return n.toString();if("object"==typeof n&&null!==n){if(t.has(n))return"[Circular]";t.add(n)}return n});if(void 0!==n)return n}catch{}if(null!==e&&"object"==typeof e){const t=e.constructor?.name??"Object";let n=[];try{n=Object.keys(e)}catch{}return n.length>0?`[${t} keys=${n.join(",")}]`:`[${t}]`}return String(e)}(e))}class V{settings;logger;protocolVersion=3;peerId;token;info;resolvedIdentity;availableDomains;gatewayToken;replayer;messageHandlers={};ids=1;registry=O();_connected=!1;isTrace=!1;transport;_defaultTransport;_defaultAuth;_targetTransport;_targetAuth;_swapTransport=!1;_switchInProgress=!1;_transportSubscriptions=[];datePrefix="#T42_DATE#";datePrefixLen=this.datePrefix.length;dateMinLen=this.datePrefixLen+1;datePrefixFirstChar=this.datePrefix[0];_sequelizer=new U;_isLoggedIn=!1;shouldTryLogin=!0;pingTimer;reconnectTimeout;sessions=[];globalDomain;initialLogin=!0;initialLoginAttempts=3;remainingReconnectAttempts;loginConfig;loginRetryInProgress=!1;reconnectInProgress=!1;constructor(e,t){if(this.settings=e,this.logger=t,(e=e||{}).reconnectAttempts=e.reconnectAttempts??10,e.reconnectInterval=e.reconnectInterval??1e3,e.inproc)this.transport=new k(e.inproc,t.subLogger("inMemory"));else if(e.sharedWorker)this.transport=new j(e.sharedWorker,t.subLogger("shared-worker"));else if(e.webPlatform)this.transport=new B(e.webPlatform,t.subLogger("web-platform"),e.identity);else{if(void 0===e.ws)throw new Error("No connection information specified");this.transport=new F(e,t.subLogger("ws"))}this.isTrace=t.canPublish("trace"),t.debug(`starting with ${this.transport.name()} transport`);const n=this.transport.onConnectedChanged(this.handleConnectionChanged.bind(this)),r=this.transport.onMessage(this.handleTransportMessage.bind(this));this._transportSubscriptions.push(n),this._transportSubscriptions.push(r),this._defaultTransport=this.transport,this.ping()}async switchTransport(e){return this._sequelizer.enqueue(async()=>{if(!e||"object"!=typeof e)throw new Error("Cannot switch transports, because the settings are missing or invalid.");if(void 0===e.type)throw new Error("Cannot switch the transport, because the type is not defined");this.logger.trace(`Starting transport switch with settings: ${JSON.stringify(e)}`);const t="secondary"===e.type?this.getNewSecondaryTransport(e):this._defaultTransport;this._targetTransport=t,this._targetAuth="secondary"===e.type?this.getNewSecondaryAuth(e):this._defaultAuth;const n=this.verifyConnection();this._swapTransport=!0,this._switchInProgress=!0,this.logger.trace("The new transport has been set, closing the current transport"),await this.transport.close();try{await n;const e=this.transport===t;return this.logger.info(`The reconnection after the switch was completed. Was the switch a success: ${e}`),this._switchInProgress=!1,{success:e}}catch(e){return this.logger.info("The reconnection after the switch timed out, reverting back to the default transport."),this.switchTransport({type:"default"}),this._switchInProgress=!1,{success:!1}}})}onLibReAnnounced(e){return this.registry.add("libReAnnounced",e)}setLibReAnnounced(e){this.registry.execute("libReAnnounced",e)}send(e,t){if(this.transport.sendObject&&this.transport.isObjectBasedTransport){const n=this.createObjectMessage(e);return this.isTrace&&this.logger.trace(`>> ${JSON.stringify(n)}`),this.transport.sendObject(n,t)}{const n=this.createStringMessage(e);return this.isTrace&&this.logger.trace(`>> ${n}`),this.transport.send(n,t)}}on(e,t){e=e.toLowerCase(),void 0===this.messageHandlers[e]&&(this.messageHandlers[e]={});const n=this.ids++;return this.messageHandlers[e][n]=t,{type:e,id:n}}off(e){delete this.messageHandlers[e.type.toLowerCase()][e.id]}get isConnected(){return this._isLoggedIn}connected(e){return this.loggedIn(()=>{const t=this.transport.name();e(t)})}disconnected(e){return this.registry.add("disconnected",e)}async login(e,t){if(this.logger.debug(`Login initiated - reconnect: ${t}, transport: ${this.transport.name()}`),this._defaultAuth||(this._defaultAuth=e),this._swapTransport){this.logger.trace("Detected a transport swap, swapping transports");e=this.transportSwap()??e}try{await this.transport.open(),this.logger.debug(`Transport: ${this.transport.name()} opened, logging in`),N("connection").mark("transport-opened");const n=await this.loginCore(e,t);return this.logger.debug(`Logged in with identity: ${JSON.stringify(n)}`),N("connection").mark("protocol-logged-in"),n}catch(e){throw this._switchInProgress&&(this.logger.debug("An error while logging in after a transport swap, preparing a default swap."),this.prepareDefaultSwap()),J(e)}}async logout(){await this.logoutCore(),await this.transport.close()}loggedIn(e){return this._isLoggedIn&&e(),this.registry.add("onLoggedIn",e)}domain(e,t,n){let r=this.sessions.find(t=>t.domain===e);return r||(r=W(e,this,this.logger.subLogger(`domain=${e}`),t,n),this.sessions.push(r)),r}authToken(){return this.globalDomain?this.globalDomain.send({domain:"global",type:"create-token"}).then(e=>e.token):Promise.reject(new Error("no global domain session"))}async reconnect(){if(!this.loginConfig)throw new Error("Cannot reconnect - no previous login configuration");if(this.reconnectInProgress)this.logger.debug("reconnect() already in progress, ignoring");else{this.reconnectInProgress=!0;try{for(this.shouldTryLogin=!1,this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=void 0);this.loginRetryInProgress;)await new Promise(e=>setTimeout(e,50));this._isLoggedIn&&(this.setLoggedIn(!1),this.registry.execute("disconnected")),this.shouldTryLogin=!0,await this.login(this.loginConfig,!0)}finally{this.reconnectInProgress=!1}}}setLoggedIn(e){this._isLoggedIn=e,this._isLoggedIn&&(this.initialLogin=!1,this.registry.execute("onLoggedIn"))}distributeMessage(e,t){const n=this.messageHandlers[t.toLowerCase()];void 0!==n&&Object.keys(n).forEach(t=>{const r=n[t];if(void 0!==r)try{r(e)}catch(e){try{this.logger.error(`Message handler failed with ${e.stack}`,e)}catch(t){console.log("Message handler failed",e)}}})}handleConnectionChanged(e){this._connected!==e?(this.logger.info("connection state changed to "+(e?"connected":"disconnected")),this._connected=e,e?(this.settings?.replaySpecs?.length&&(this.replayer=new $(this.settings.replaySpecs),this.replayer.init(this)),this.registry.execute("connected")):(this.setLoggedIn(!1),this.shouldTryLogin&&(this.remainingReconnectAttempts=this.settings.reconnectAttempts,this.attemptLoginWithRetry()),this.registry.execute("disconnected"))):this.logger.trace("connection state unchanged, skipping")}async attemptLoginWithRetry(){if(!this.loginConfig)throw new Error("no login info");if(this.shouldTryLogin)if(this.loginRetryInProgress)this.logger.debug("login attempt already in progress, ignoring request...");else if(this._isLoggedIn)this.logger.debug("already logged in, ignoring request...");else{if(this.initialLogin){if(this.logger.debug(`initial login attempt failed, ${this.initialLoginAttempts} attempts remaining...`),this.initialLoginAttempts<=0)return void this.logger.info("maximum initial login attempts reached, will not try to login again");this.initialLoginAttempts--}else if(void 0!==this.remainingReconnectAttempts){if(this.remainingReconnectAttempts<=0)return void this.logger.info("maximum reconnect attempts reached, will not try to login again");this.logger.debug(`reconnect attempt, ${this.remainingReconnectAttempts} attempts remaining...`),this.remainingReconnectAttempts--}try{this.logger.debug(`will try a new login... ${this.loginRetryInProgress}`),this.loginRetryInProgress=!0,await this.login(this.loginConfig,!0)}catch(e){this.logger.error(`error trying to login: ${e?.message}`,e),this.shouldTryLogin&&(this.reconnectTimeout=setTimeout(this.attemptLoginWithRetry.bind(this),this.settings.reconnectInterval??1e3))}finally{this.loginRetryInProgress=!1}}else this.logger.debug("should not try to login, ignoring reconnect attempt...")}handleTransportMessage(e){let t;t="string"==typeof e?this.processStringMessage(e):this.processObjectMessage(e),this.isTrace&&this.logger.trace(`<< ${JSON.stringify(t)}`),this.distributeMessage(t.msg,t.msgType)}verifyConnection(){return q(e=>{let t;const n=((e,t)=>{let n=e;return()=>{n--,0===n&&t()}})(2,()=>{t&&t(),e()});t=this.onLibReAnnounced(e=>"interop"===e.name||"contexts"===e.name?n():void 0)},1e4,"Transport switch timed out waiting for all libraries to be re-announced")}getNewSecondaryTransport(e){if(!e.transportConfig?.url)throw new Error("Missing secondary transport URL.");return new F(Object.assign({},this.settings,{ws:e.transportConfig.url,reconnectAttempts:1}),this.logger.subLogger("ws-secondary"))}getNewSecondaryAuth(e){if(!e.transportConfig?.auth)throw new Error("Missing secondary transport auth information.");return e.transportConfig.auth}transportSwap(){if(this._swapTransport=!1,!this._targetTransport||!this._targetAuth)return void this.logger.warn(`Error while switching transports - either the target transport or auth is not defined: transport defined -> ${!!this._defaultTransport}, auth defined -> ${!!this._targetAuth}. Staying on the current one.`);this._transportSubscriptions.forEach(e=>e()),this._transportSubscriptions=[],this.transport=this._targetTransport;const e=this.transport.onConnectedChanged(this.handleConnectionChanged.bind(this)),t=this.transport.onMessage(this.handleTransportMessage.bind(this));return this._transportSubscriptions.push(e),this._transportSubscriptions.push(t),this._targetAuth}prepareDefaultSwap(){this._transportSubscriptions.forEach(e=>e()),this._transportSubscriptions=[],this.transport.close().catch(e=>this.logger.warn(`Error closing the ${this.transport.name()} transport after a failed connection attempt: ${JSON.stringify(e)}`)),this._targetTransport=this._defaultTransport,this._targetAuth=this._defaultAuth,this._swapTransport=!0}processStringMessage(e){const t=JSON.parse(e,(e,t)=>{if("string"!=typeof t)return t;if(t.length<this.dateMinLen)return t;if(!t.startsWith(this.datePrefixFirstChar))return t;if(t.substring(0,this.datePrefixLen)!==this.datePrefix)return t;try{const e=parseInt(t.substring(this.datePrefixLen,t.length),10);return isNaN(e)?t:new Date(e)}catch(e){return t}});return{msg:t,msgType:t.type}}createStringMessage(e){const t=Date.prototype.toJSON;try{const t=this.datePrefix;Date.prototype.toJSON=function(){return t+this.getTime()};return JSON.stringify(e)}finally{Date.prototype.toJSON=t}}processObjectMessage(e){if(!e.type)throw new Error("Object should have type property");return{msg:e,msgType:e.type}}createObjectMessage(e){return e}async loginCore(e,t){this.loginConfig=e,this.loginConfig||(this.loginConfig={username:"",password:""});const n=await this.setupAuthConfig(e,t),r={type:"hello",identity:this.settings.identity,authentication:n};e.sessionId&&(r.request_id=e.sessionId),this.globalDomain||(this.globalDomain=W("global",this,this.logger.subLogger("global-domain"),["welcome","token","authentication-request"]));const i={skipPeerId:!0};this.initialLogin&&(i.retryInterval=this.settings.reconnectInterval,i.maxRetries=this.settings.reconnectAttempts);try{const t=await this.tryAuthenticate(this.globalDomain,r,i,e);return this.logger.info("login successful with peerId "+t.peer_id),this.peerId=t.peer_id,this.resolvedIdentity=t.resolved_identity,this.availableDomains=t.available_domains,t.options&&(this.token=t.options.access_token,this.info=t.options.info),this.setLoggedIn(!0),t.resolved_identity}catch(e){throw this.logger.error("error sending hello message - "+(e.message||e.msg||e.reason||e),e),e}finally{e?.flowCallback&&e.sessionId&&e.flowCallback(e.sessionId,null)}}async tryAuthenticate(e,t,n,r){let i;for(;;){const s=await e.send(t,void 0,n);if("authentication-request"!==s.type){if("welcome"===s.type){i=s;break}throw"error"===s.type?new Error("Authentication failed: "+s.reason):new Error("Unexpected message type during authentication: "+s.type)}{const e=Buffer.from(s.authentication.token,"base64");r.flowCallback&&r.sessionId&&(t.authentication.token=(await r.flowCallback(r.sessionId,e)).data.toString("base64")),t.request_id=r.sessionId}}return i}async setupAuthConfig(e,t){const n={};if(this.gatewayToken=e.gatewayToken,e.gatewayToken){if(t)try{e.gatewayToken=await this.getNewGWToken()}catch(e){this.logger.warn(`failed to get GW token when reconnecting ${e?.message||e}`)}n.method="gateway-token",n.token=e.gatewayToken,this.gatewayToken=e.gatewayToken}else if("sspi"===e.flowName){if(n.provider="win",n.method="access-token",!e.flowCallback||!e.sessionId)throw new Error("Invalid SSPI config");n.token=(await e.flowCallback(e.sessionId,null)).data.toString("base64")}else if(e.token)n.method="access-token",n.token=e.token;else if(e.username)n.method="secret",n.login=e.username,n.secret=e.password;else{if(!e.provider)throw new Error("invalid auth message"+JSON.stringify(e));n.provider=e.provider,n.providerContext=e.providerContext}return n}async logoutCore(){this.logger.debug("core logging out..."),this.shouldTryLogin=!1,this.setLoggedIn(!1),this.pingTimer&&clearTimeout(this.pingTimer),this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=void 0);const e=this.sessions.map(e=>e.leave());await Promise.all(e)}getNewGWToken(){if("undefined"!=typeof window){const e=window.glue42gd;if(e)return e.getGWToken()}return Promise.reject(new Error("not running in GD"))}ping(){this.shouldTryLogin&&(this._isLoggedIn&&this.send({type:"ping"}),this.pingTimer=setTimeout(()=>{this.ping()},3e4))}}const K=["trace","debug","info","warn","error","off"];class G{name;parent;static Interop;static InteropMethodName="T42.AppLogger.Log";sta