UNPKG

matssocket

Version:
3 lines (2 loc) 37.6 kB
function e(e,t){this.type=e,this.currentExpirationTimestamp=t}const t={NOT_PRESENT:"notpresent",EXPIRED:"expired",REAUTHENTICATE:"reauthenticate"};Object.freeze(t);const n={NO_SESSION:"nosession",CONNECTING:"connecting",WAITING:"waiting",CONNECTED:"connected",SESSION_ESTABLISHED:"sessionestablished"};function o(e,t,n,o,i,s){this.type=e,this.webSocketUrl=t,this.webSocketEvent=n,this.timeoutSeconds=o,this.countdownSeconds=i,this.connectionAttempt=s}Object.freeze(n);const i={CONNECTING:n.CONNECTING,WAITING:n.WAITING,CONNECTED:n.CONNECTED,SESSION_ESTABLISHED:n.SESSION_ESTABLISHED,CONNECTION_ERROR:"connectionerror",LOST_CONNECTION:"lostconnection",COUNTDOWN:"countdown"};Object.freeze(i);const s={HELLO:"HELLO",WELCOME:"WELCOME",SEND:"SEND",REQUEST:"REQUEST",RETRY:"RETRY",ACK:"ACK",NACK:"NACK",ACK2:"ACK2",RESOLVE:"RESOLVE",REJECT:"REJECT",SUB:"SUB",UNSUB:"UNSUB",SUB_OK:"SUB_OK",SUB_LOST:"SUB_LOST",SUB_NO_AUTH:"SUB_NO_AUTH",PUB:"PUB",REAUTH:"REAUTH",AUTH:"AUTH",PING:"PING",PONG:"PONG"};function r(e,t,n,o,i,s){this.type=e,this.traceId=t,this.sentTimestamp=n,this.receivedTimestamp=o,this.roundTripMillis=i,this.description=s}Object.freeze(s);const a={ACK:"ack",NACK:"nack",TIMEOUT:"timeout",SESSION_CLOSED:"sessionclosed"};function c(e,t,n,o,i){this.type=e,this.data=t,this.correlationInformation=void 0,this.traceId=n,this.messageId=o,this.clientRequestTimestamp=void 0,this.receivedTimestamp=i,this.roundTripMillis=void 0,this.debug=void 0}Object.freeze(a);const d={RESOLVE:"resolve",REJECT:"reject",SEND:"send",REQUEST:"request",PUB:"pub",TIMEOUT:"timeout",SESSION_CLOSED:"sessionclosed"};function l(e,t){this.type=e,this.topicId=t}Object.freeze(d);const u={OK:"ok",NOT_AUTHORIZED:"notauthorized",LOST_MESSAGES:"lostmessages"};function f(e,t,n,o,i,s,r,a,c,d,l){this.type=c?g.REQUEST_REPLY_TO:a?g.REQUEST:g.SEND,this.endpointId=e,this.clientMessageId=t,this.sentTimestamp=n,this.sessionEstablishedOffsetMillis=o,this.traceId=i,this.initiationMessage=s,this.acknowledgeRoundTripMillis=r,this.replyMessageEventType=a,this.replyToTerminatorId=c,this.requestReplyRoundTripMillis=d,this.replyMessageEvent=l}Object.freeze(u);const g={SEND:"send",REQUEST:"request",REQUEST_REPLY_TO:"requestreplyto"};function h(e,t){this.pingId=e,this.sentTimestamp=t,this.roundTripMillis=void 0}Object.freeze(g);const m={VIOLATED_POLICY:1008,UNEXPECTED_CONDITION:1011,SERVICE_RESTART:1012,GOING_AWAY:1001,CLOSE_SESSION:4e3,SESSION_LOST:4001,RECONNECT:4002,DISCONNECT:4003,MATS_SOCKET_PROTOCOL_ERROR:4004};Object.freeze(m);const p=(()=>{const e=new Map(Object.entries(m).map(([e,t])=>[t,e]));return{nameFor:t=>e.get(t)??`UNKNOWN(${t})`}})();function S(e,t,n){this.type=e,this.message=t,this.reference=n,this.referenceAsString=function(e=1024){let t;try{t=JSON.stringify(this.reference)}catch(e){}return"string"!=typeof t&&(t=""+this.reference),t.length>e?t.substring(0,e-3)+"...":t}}function E(e,t,n,o){this.clientMessageSent=e,this.requestedDebugOptions=t,this.description=n.desc,this.messageReceived=o,this.resolvedDebugOptions=0,this.clientMessageReceived=void 0,this.clientMessageReceivedNodename=void 0,this.matsMessageSent=void 0,this.matsMessageReplyReceived=void 0,this.matsMessageReplyReceivedNodename=void 0,this.serverMessageCreated=void 0,this.serverMessageCreatedNodename=void 0,this.messageSentToClient=void 0,this.messageSentToClientNodename=void 0,n.debug&&(this.resolvedDebugOptions=n.debug.resd,this.clientMessageReceived=n.debug.cmrts,this.clientMessageReceivedNodename=n.debug.cmrnn,this.matsMessageSent=n.debug.mmsts,this.matsMessageReplyReceived=n.debug.mmrrts,this.matsMessageReplyReceivedNodename=n.debug.mmrrnn,this.serverMessageCreated=n.debug.smcts,this.serverMessageCreatedNodename=n.debug.smcnn,this.messageSentToClient=n.debug.mscts,this.messageSentToClientNodename=n.debug.mscnn)}const w={TIMESTAMPS:1,NODES:2,CUSTOM_A:64,CUSTOM_B:128};function T(g,w,T,b=null){let v="MatsSocket.js,1.0.0-2025-10-27";if("string"!=typeof g)throw new Error("appName must be a string, was: ["+g+"]");if("string"!=typeof w)throw new Error("appVersion must be a string, was: ["+w+"]");if(!("string"==typeof T||T instanceof String||Array.isArray(T)&&T.length>0))throw new Error("urls must have at least 1 url set, got: ["+T+"]");let O,C,I=!1;if(b)if(b.webSocketFactory){if("function"!=typeof b.webSocketFactory)throw new Error("config.webSocketFactory should be a function, instead got ["+typeof b.webSocketFactory+"].");C=b.webSocketFactory}else if(b.webSocket){if("function"!=typeof b.webSocket)throw new Error("config.webSocket should be a function (constructor), instead got ["+typeof b.webSocket+"].");C=function(e,t){return new b.webSocket(e,t)}}if(!C)if("function"==typeof WebSocket)C=(e,t)=>new WebSocket(e,t);else{if(!function(){const e=process;return e&&e.versions&&void 0!==e.versions.node}())throw new Error("Missing config.webSocket, config.webSocketFactory, global WebSocket (window.WebSocket), and seemingly not Node.js so cannot dynamically import 'ws' module: Cannot create MatsSocket.");I=!0,import("ws").then(e=>{R("Constructor: NodeJs import('ws') went OK: Got WebSocket module");const{default:t}=e;setTimeout(()=>{C=(e,n)=>new t(e,n),R("Constructor: 'webSocketFactory' is now set."),I=!1,"function"==typeof O&&(R("Constructor: Invoking callback-method to restart WebSocket creation attempt."),O())},0)}).catch(e=>{I=!1,M("Import of WebSocket module failed","In Node.js environment, the import('ws') failed",e)})}let N="object"==typeof window&&window.performance||{now:function(){return Date.now()}};const y=this,k="object"==typeof self&&"object"==typeof self.navigator?self.navigator.userAgent:"Unknown";T=[].concat(T),this.sessionId=void 0,this.logging=!1,this.errorLogging=!0,this.outofbandclose=!0,this.preconnectoperation=!1,this.debug=0,this.requestTimeout=45e3,this.maxConnectionAttempts=void 0,this.initialPingDelay=3e3+4e3*Math.random(),this.addSessionClosedEventListener=function(e){if("function"!=typeof e)throw Error("SessionClosedEvent listener must be a function");$.push(e)},this.addConnectionEventListener=function(e){if("function"!=typeof e)throw Error("SessionClosedEvent listener must be a function");ee.push(e)},this.addSubscriptionEventListener=function(e){if("function"!=typeof e)throw Error("SubscriptionEvent listener must be a function");te.push(e)},this.addErrorEventListener=function(e){if("function"!=typeof e)throw Error("ErrorEvent listener must be a function");ie.push(e)},this.setAuthorizationExpiredCallback=function(e){if("function"!=typeof e)throw Error("AuthorizationExpiredCallback must be a function");H=e,y.flush()},this.setCurrentAuthorization=function(e,n=-1,o=3e4){this.logging&&R("Got Authorization which "+(-1!==n?"Expires in ["+(n-Date.now())+" ms]":"[Never expires]")+", roomForLatencyMillis: "+o),j=e,x=n,B=o,G===t.REAUTHENTICATE&&(R("Immediate send of new authentication due to REAUTHENTICATE"),ae=!0),G=void 0,y.flush()},Object.defineProperty(this,"lastMessageEnqueuedTimestamp",{get:function(){return F}}),Object.defineProperty(this,"connected",{get:function(){return null!=W}}),Object.defineProperty(this,"state",{get:function(){return se}}),Object.defineProperty(this,"pings",{get:function(){return me}}),this.addPingPongListener=function(e){if("function"!=typeof e)throw Error("PingPong listener must be a function");ne.push(e)},Object.defineProperty(this,"initiations",{get:function(){return Se}}),Object.defineProperty(this,"numberOfInitiationsKept",{get:function(){return pe},set:function(e){if(e<0)throw new Error("numberOfInitiationsKept must be >= 0");for(pe=e;Se.length>e;)Se.shift()}}),this.addInitiationProcessedEventListener=function(e,t,n){if("function"!=typeof e)throw Error("InitiationProcessedEvent listener must be a function");oe.push({listener:e,includeInitiationMessage:t,includeReplyMessageEvent:n})},this.terminator=function(e,t,n){if(void 0!==Q[e])throw new Error("Cannot register more than one Terminator to same terminatorId ["+e+"], existing: "+Q[e]);if(void 0!==X[e])throw new Error("Cannot register a Terminator to same terminatorId ["+e+"] as an Endpoint's endpointId, existing: "+X[e]);if(e.startsWith("MatsSocket"))throw new Error('The namespace "MatsSocket" is reserved, terminatorId ['+e+"] is illegal.");if("function"!=typeof t)throw new Error("The 'messageCallback' must be a function.");if(void 0!==n&&"function"!=typeof n)throw new Error("The 'rejectCallback' must either be undefined or a function.");R("Registering Terminator on id ["+e+"]:\n #messageCallback: "+t+"\n #rejectCallback: "+n),Q[e]={resolve:t,reject:n}},this.endpoint=function(e,t){if(void 0!==X[e])throw new Error("Cannot register more than one Endpoint to same endpointId ["+e+"], existing: "+X[e]);if(void 0!==Q[e])throw new Error("Cannot register an Endpoint to same endpointId ["+e+"] as a Terminator, existing: "+Q[e]);if(e.startsWith("MatsSocket"))throw new Error('The namespace "MatsSocket" is reserved, EndpointId ['+e+"] is illegal.");if("function"!=typeof t)throw new Error("The 'promiseProducer' must be a function.");R("Registering Endpoint on id ["+e+"]:\n #promiseProducer: "+t),X[e]=t},this.subscribe=function(e,t){if(e.startsWith("MatsSocket"))throw new Error('The namespace "MatsSocket" is reserved, Topic ['+e+"] is illegal.");if(e.startsWith("!"))throw new Error('Topic cannot start with "!" (and why would you use chars like that anyway?!), Topic ['+e+"] is illegal.");if("function"!=typeof t)throw new Error("The 'messageCallback' must be a function.");R("Registering Subscription on Topic ["+e+"]:\n #messageCallback: "+t);let n=Z[e];n||(n={listeners:[],lastSmid:void 0,subscriptionSentToServer:!1},Z[e]=n);for(let o=0;o<n.listeners.length;o++)if(n.listeners[o]===t)return void M("subscription_already_exists","The specified messageCallback ["+t+"] was already subscribed to Topic ["+e+"].");n.listeners.push(t),n.subscriptionSentToServer||(re?(Oe({t:s.SUB,eid:e},!0),n.subscriptionSentToServer=!0):(ae=!0,J=!0,Ie()))},this.deleteSubscription=function(e,t){let n=Z[e];if(!n)throw new Error("The topicId ["+e+"] had no subscriptions! (thus this message callback is not subscribed! ["+t+"].");let o=!1;for(let e=0;e<n.listeners.length;e++)if(n.listeners[e]===t){o=!0,n.listeners=n.listeners.splice(e,1);break}o?0===n.listeners.length&&n.subscriptionSentToServer&&(Oe({t:s.UNSUB,eid:e},!0),delete Z[e]):M("subscription_not_found","The specified messageCallback ["+t+"] was not subscribed with Topic ["+e+"].")},this.send=function(e,t,n,o=void 0){return new Promise(function(i,r){let a=Object.create(null);if(a.ack=i,a.nack=r,o){if("object"!=typeof o)throw new Error("The 'config' parameter wasn't an object.");o.suppressInitiationProcessedEvent&&(a.suppressInitiationProcessedEvent=!0)}let c=Object.create(null);c.t=s.SEND,c.eid=e,c.msg=n,ve(c,t,a,void 0)})},this.request=function(e,t,n,o=void 0){return new Promise(function(i,r){let a=y.requestTimeout,c=Object.create(null);if("function"==typeof o)c.ack=o,c.nack=o;else if("object"==typeof o){if(o.receivedCallback){if("function"!=typeof o.receivedCallback)throw new Error("The 'configOrCallback.receivedCallback' is not a function.");c.ack=o.receivedCallback,c.nack=o.receivedCallback}else{if(o.ackCallback){if("function"!=typeof o.ackCallback)throw new Error("The 'configOrCallback.ackCallback' is not a function.");c.ack=o.ackCallback}if(o.nackCallback){if("function"!=typeof o.nackCallback)throw new Error("The 'configOrCallback.nackCallback' is not a function.");c.nack=o.nackCallback}}if(void 0!==o.timeout){if("number"!=typeof o.timeout)throw new Error("The 'configOrCallback.timeout' is not a number.");a=o.timeout}o.suppressInitiationProcessedEvent&&(c.suppressInitiationProcessedEvent=!0),void 0!==o.debug&&(c.debug=o.debug)}else if(void 0!==o)throw new Error("The 'configOrCallback' parameter was neither a function or an object.");let d=Object.create(null);d.resolve=i,d.reject=r,d.timeout=a;let l=Object.create(null);l.t=s.REQUEST,l.eid=e,l.msg=n,l.to=a,ve(l,t,c,d)})},this.requestReplyTo=function(e,t,n,o,i,r=void 0){if(!Q[o])throw new Error("The Client Terminator ["+o+"] is not present, !");return new Promise(function(a,c){let d=Object.create(null);d.ack=a,d.nack=c;let l=y.requestTimeout;if(r){if("object"!=typeof r)throw new Error("The 'config' parameter wasn't an object.");if(void 0!==r.timeout){if("number"!=typeof r.timeout)throw new Error("The 'config.timeout' is not a number.");l=r.timeout}r.suppressInitiationProcessedEvent&&(d.suppressInitiationProcessedEvent=!0),void 0!==r.debug&&(d.debug=r.debug)}let u=Object.create(null);u.replyToTerminatorId=o,u.correlationInformation=i,u.timeout=l;let f=Object.create(null);f.t=s.REQUEST,f.eid=e,f.msg=n,f.to=l,ve(f,t,d,u)})},this.flush=function(){Ce&&(clearTimeout(Ce),Ce=void 0),Ne()},this.close=function(e){let t=ke,n=y.sessionId;if(R("close(): Closing MatsSocketSession, id:["+n+"] due to ["+e+"], currently connected: ["+(W?W.url:"not connected")+"]"),W&&(R(" \\-> WebSocket is open, so we perform in-band Session Close by closing the WebSocket with MatsSocketCloseCode.CLOSE_SESSION (4000)."),W.close(m.CLOSE_SESSION,"From client: "+e)),be(),n)if("function"==typeof this.outofbandclose)this.outofbandclose({webSocketUrl:t,sessionId:n});else if(this.outofbandclose&&"undefined"!=typeof window&&void 0!==window.navigator){let e=t.replace("ws","http")+"/close_session?session_id="+n;R(" \\- Send an out-of-band (i.e. HTTP) close_session, using navigator.sendBeacon('"+e+"')."),R(" \\- Result: "+(window.navigator.sendBeacon(e)?"Enqueued POST, but do not know whether anyone received it - check Network tab of Dev Tools.":"Did NOT manage to enqueue a POST."))}},this.reconnect=function(e,t=!1){let n=t?m.DISCONNECT:m.RECONNECT;if(y.logging&&R("reconnect(): Closing WebSocket with CloseCode '"+p.nameFor(n)+" ("+n+")', MatsSocketSessionId:["+y.sessionId+"] due to ["+e+"], currently connected: ["+(W?W.url:"not connected")+"]"),!W)throw new Error("There is no live WebSocket to close with "+p.nameFor(n)+" closeCode!");W.onmessage=void 0,W.close(n,e)},this.randomId=function(e=6){let t="";for(let n=0;n<e;n++)t+=L[Math.floor(Math.random()*L.length)];return t},this.randomCId=function(e=10){let t="";for(let n=0;n<e;n++)t+=P[Math.floor(Math.random()*P.length)];return t};const A=Date.now();function R(e,t){y.logging&&(t?console.log(_+"/"+y.sessionId+"{"+(Date.now()-A)+"}: "+e,t):console.log(_+"/"+y.sessionId+"{"+(Date.now()-A)+"}: "+e))}function M(e,t,n){let o=new S(e,t,n);for(let e=0;e<ie.length;e++)try{ie[e](o)}catch(n){console.error("Caught error when notifying one of the ["+ie.length+"] ErrorEvent listeners - NOT notifying using ErrorEvent in fear of creating infinite recursion.",n)}y.errorLogging&&(n?console.error(e+": "+t,n):console.error(e+": "+t))}const L="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",P="!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~";let U=[].concat(T);!function(e){for(let t=e.length-1;t>0;t--){let n=Math.floor(Math.random()*(t+1)),o=e[t];e[t]=e[n],e[n]=o}}(U);const _=y.randomId(3);let D,W,j,K,z,x,B,H,G,F=Date.now(),q=!1,J=!1,V=[],Y=[],Q=Object.create(null),X=Object.create(null),Z=Object.create(null),$=[],ee=[],te=[],ne=[],oe=[],ie=[],se=n.NO_SESSION,re=!1,ae=!1,ce=0;const de=Object.create(null),le=Object.create(null),ue=Object.create(null);let fe=this.randomCId(5);const ge=Object.create(null);let he=Object.create(null);const me=[];let pe=10;const Se=[];function Ee(e){setTimeout(e,0)}function we(){y.close(v+" window.onbeforeunload close")}function Te(){R("clearWebSocketStateAndInfrastructure(). Current WebSocket:"+W),R("Cancelling PINGer"),Qe&&(clearTimeout(Qe),Qe=void 0),"object"==typeof self&&"function"==typeof self.addEventListener&&self.removeEventListener("beforeunload",we),De(),fe=y.randomCId(5),W&&(W.onclose=void 0,W.onmessage=void 0,W.onerror=void 0),W=void 0}function be(){R("closeSessionAndClearStateAndPipelineAndFuturesAndOutstandingMessages(). Current WebSocket:"+W),y.sessionId=void 0,se=n.NO_SESSION,Te(),Y.length=0,J=!1;for(let e in ue){let t=ue[e];delete ue[e],y.logging&&R("Close Session: Clearing outstanding Initiation ["+t.envelope.t+"] to ["+t.envelope.eid+"], cmid:["+t.envelope.cmid+"], TraceId:["+t.envelope.tid+"]."),et(a.SESSION_CLOSED,t,Date.now())}for(let e in le){let t=le[e];delete le[e],y.logging&&R("Close Session: Clearing outstanding REQUEST to ["+t.envelope.eid+"], cmid:["+t.envelope.cmid+"], TraceId:["+t.envelope.tid+"].",t),nt(t,d.SESSION_CLOSED,{},Date.now())}}function ve(e,t,n,o){J=!0;let i=Date.now(),s=N.now();e.tid=t;let r=ce++;e.cmid=r,n.debug=void 0!==n.debug?n.debug:y.debug?y.debug:0,0!==n.debug&&(e.rd=n.debug),0===n.debug&&0!==z&&(e.rd=0),z=n.debug,F=i,n.envelope=e,n.retransmitGuard=fe,n.attempt=1,n.sentTimestamp=i,n.messageSent_PerformanceNow=s,n.messageAcked_PerformanceNow=void 0,ue[r]=n,o&&(o.initiation=n,o.envelope=e,o.timeoutId=setTimeout(function(){let e=N.now();y.logging&&R("TIMEOUT! Request with TraceId:["+o.envelope.tid+"], cmid:["+o.envelope.cmid+"] overshot timeout ["+(e-o.initiation.messageSent_PerformanceNow)+" ms of "+o.timeout+"]");let t=ue[r];t&&(delete ue[r],et(a.TIMEOUT,t,Date.now())),t&&o.replyToTerminatorId?setTimeout(function(){nt(o,d.TIMEOUT,{},Date.now())},50):nt(o,d.TIMEOUT,{},Date.now())},o.timeout),le[r]=o),Oe(e)}function Oe(e,t=!1){t?(y.logging&&R("ENQUEUE: Envelope of type ["+e.t+"] enqueued to PRE-pipeline: "+JSON.stringify(e)),V.push(e)):(y.logging&&R("ENQUEUE: Envelope of type ["+e.t+"] enqueued to pipeline: "+JSON.stringify(e)),Y.push(e)),Ie()}let Ce;function Ie(){Ce&&clearTimeout(Ce),Ce=setTimeout(function(){Ce=void 0,Ne()},10)}function Ne(){if(0!==Y.length||0!==V.length||ae)if(J)if(void 0!==j)if(void 0!==x&&-1!==x&&x-B<Date.now())ye("Authorization is expired",new e(t.EXPIRED,x));else if(G)R("We have asked app for new authorization, and still waiting for it.");else if(q)R("evaluatePipelineSend(): WebSocket is currently connecting. Cannot send yet.");else{if(void 0===W)return R("evaluatePipelineSend(): WebSocket is not present, so initiate creation. Cannot send yet."),void ze();if(!re){let e={t:s.HELLO,clv:v+"; User-Agent: "+k,ts:Date.now(),an:g,av:w,auth:j,cid:y.randomId(10)};void 0!==y.sessionId?(R('HELLO not send, adding to pre-pipeline. HELLO ("Reconnect") to MatsSocketSessionId:['+y.sessionId+"]"),e.sid=y.sessionId):R('HELLO not sent, adding to pre-pipeline. HELLO ("New"), we will get assigned a MatsSocketSessionId upon WELCOME.'),V.unshift(e),re=!0,K=j;for(let e in Z){let t=Z[e];t.listeners.length>0&&!t.subscriptionSentToServer&&V.push({t:s.SUB,eid:e,smid:t.lastSmid}),0===t.listeners.length&&t.subscriptionSentToServer&&(V.push({t:s.UNSUB,eid:e}),delete Z[e])}}if(re&&K!==j){if(Y.length>0){let e=Y[Y.length-1];y.logging&&R("Authorization has changed, and there is a message in pipeline of type ["+e.t+"], so so we add 'auth' to it."),e.auth=j}else y.logging&&R("Authorization has changed, but there is no message in pipeline, so we add an AUTH message now."),Y.push({t:s.AUTH,auth:j});K=j}ae=!1,V.length>0&&(y.logging&&R("Flushing prePipeline of ["+V.length+"] messages: "+JSON.stringify(V)),W.send(JSON.stringify(V)),V.length=0),Y.length>0&&(y.logging&&R("Flushing pipeline of ["+Y.length+"] messages: "+JSON.stringify(Y)),W.send(JSON.stringify(Y)),Y.length=0)}else ye("Authorization not present",new e(t.NOT_PRESENT,void 0));else R("evaluatePipelineSend(), but MatsSocket is not open - ignoring.")}function ye(e,t){if(G)R(e+", but we've already asked app for it due to: ["+G+"].");else{if(R(e+". Will not send pipeline until gotten. Invoking 'authorizationExpiredCallback', type:["+t.type+"]."),G=t.type,!H){let e="From Client: Need new authorization, but missing 'authorizationExpiredCallback'. This is fatal, cannot continue.";M("missingauthcallback",e),W&&(R(" \\-> WebSocket is open, so we perform in-band Session Close by closing the WebSocket with MatsSocketCloseCode.CLOSE_SESSION (4000)."),W.close(m.CLOSE_SESSION,e));let t=Object.keys(ue).length;return be(),void Ke({type:"close",code:m.VIOLATED_POLICY,codeName:"VIOLATED_POLICY",reason:e,outstandingInitiations:t})}H(t)}}X["MatsSocket.renewAuth"]=function(n){return new Promise(function(n,o){ye("MatsSocket.renewAuth was invoked",new e(t.REAUTHENTICATE,void 0)),n({})})};let ke,Ae=0,Re=0,Me=0,Le=500,Pe=U.length>1?Le:5e3,Ue=15e3;function _e(){Ae++,Re++,Re>=U.length&&(Re=0,Me++),ke=U[Re],R("## _increaseReconnectStateVars(): round:["+Me+"], urlIndex:["+Re+"] = "+ke)}function De(){Ae=0,Re=0,Me=0,ke=U[Re],R("## _resetReconnectStateVars(): round:["+Me+"], urlIndex:["+Re+"] = "+ke)}function We(e){return Math.round(e/100)/10}function je(e){!y.logging||e.type===i.COUNTDOWN&&e.countdownSeconds!==e.timeoutSeconds&&Math.round(e.countdownSeconds)!==e.countdownSeconds||R("Sending ConnectionEvent to listeners",e);let t=Object.keys(n).filter(function(t){return n[t]===e.type});1===t.length&&(se=n[t[0]],R("The ConnectionEventType ["+t[0]+"] is also a ConnectionState - setting MatsSocket state ["+se+"]."));for(let t=0;t<ee.length;t++)try{ee[t](e)}catch(t){M("notify ConnectionEvent listeners","Caught error when notifying one of the ["+ee.length+"] ConnectionEvent listeners about ["+e.type+"].",t)}}function Ke(e){y.logging&&R("Sending SessionClosedEvent to listeners",e);for(let t=0;t<$.length;t++)try{$[t](e)}catch(e){M("notify SessionClosedEvent listeners","Caught error when notifying one of the ["+$.length+"] SessionClosedEvent listeners.",e)}}function ze(){if(void 0!==W)throw new Error("Should not be here, as WebSocket is already in place!");if(!J)throw new Error("The MatsSocket instance is closed, so we should not open WebSocket");if(void 0!==x&&-1!==x&&x-B<Date.now())return R("InitiateWebSocketCreation: Authorization is expired, we need new to continue."),q=!1,void ye("Authorization is expired",new e(t.EXPIRED,x));if(!C){if(I)return R("InitiateWebSocketCreation: Missing matsSocketFactory, but import in progress! Wait for result of import attempt."),void(O=function(){R("InitiateWebSocketCreation: Was missing matsSocketFactory, but matsSocketFactory should now be in place. Attempting again."),ze()});throw M("Missing WebSocket implementation","InitiateWebSocketCreation: Missing matsSocketFactory, and there is no attempt in progress to get it. Fatal."),new Error("Missing matsSocketFactory!")}q=!0;let n,s,r,a=Me>10?Ue:Math.max(Pe,Math.min(Ue,Le*Math.pow(2,Me))),c=Date.now(),d=c+a,l=function(){return Math.round((d-Date.now())/100)/10};function u(){if(n){R(" \\- Within PreConnectionOperation phase - invoking preConnectOperationFunction's abort() function.");let e=n;n=void 0,e()}s&&(R(" \\- Within WebSocket connect phase - clearing handlers and invoking webSocket.close()."),s.onopen=void 0,s.onerror=function(e){y.logging&&R("!! websocketAttempt.onerror: Forced close by timeout, instanceId:["+e.target.webSocketInstanceId+"]",e)},s.onclose=function(e){y.logging&&R("!! websocketAttempt.onclose: Forced close by timeout, instanceId:["+e.target.webSocketInstanceId+"]",e)},s.close(m.CLOSE_SESSION,"WebSocket connect aborted"),s=void 0)}function f(e){let t=new XMLHttpRequest;return[function(){t.abort()},new Promise(function(n,o){t.addEventListener("loadend",function(e){let i=t.status;200===i||202===i||204===i?n(i):o(i)}),t.withCredentials=!0,t.open("GET",e.directUrl?e.directUrl:e.webSocketUrl.replace("ws","http")),t.setRequestHeader("Authorization",e.authorization),t.send()})]}function g(){if(n=void 0,s)throw Error("When going for attempt on creating WebSocket, there was already an attempt in place.");if(!J)return R("Upon WebSocket.open, we realize that this MatsSocket instance is closed! - stopping right here."),void u();let e=ke+(y.preconnectoperation?"?preconnect=true":"");const t=y.randomId(6);y.logging&&R('INSTANTIATING new WebSocket("'+e+'", "matssocket") - InstanceId:['+t+"]"),s=C(e,"matssocket"),s.webSocketInstanceId=t,s.onerror=function(e){y.logging&&R("Create WebSocket: error. InstanceId:["+e.target.webSocketInstanceId+"]",e),s.onerror=void 0,s.onclose=void 0,s.onopen=void 0,je(new o(i.WAITING,ke,e,We(a),l(),Ae)),h()},s.onclose=function(e){y.logging&&R("Create WebSocket: close. InstanceId:["+e.target.webSocketInstanceId+"], Code:"+e.code+", Reason:"+e.reason,e),s.onerror=void 0,s.onclose=void 0,s.onopen=void 0,je(new o(i.WAITING,ke,e,We(a),l(),Ae)),h()},s.onopen=function(e){if(clearTimeout(r),!J)return R("Upon WebSocket.open, we realize that this MatsSocket instance is closed! - stopping right here."),void u();R("Create WebSocket: opened! InstanceId:["+e.target.webSocketInstanceId+"].",e),W=s,q=!1,re=!1,W.onopen=void 0,W.onerror=xe,W.onclose=Be,W.onmessage=He,"object"==typeof self&&"function"==typeof self.addEventListener&&self.addEventListener("beforeunload",we),je(new o(i.CONNECTED,ke,e,We(a),l(),Ae)),Ee(function(){R("WebSocket is open! Running evaluatePipelineSend() to start HELLO/WELCOME handshake."),Ne()})}}function h(){if(R("Create WebSocket: Attempt failed, URL ["+ke+"] didn't work out."),!J)return R("After failed attempt, we realize that this MatsSocket instance is closed! - stopping right here."),u(),void clearTimeout(r);if(Ae>=(void 0!==y.maxConnectionAttempts?y.maxConnectionAttempts:null!==y.sessionId?5760:60)){let e="Trying to create WebSocket: Too many consecutive connection attempts ["+Ae+"]";M("too many connection attempts",e);let t=Object.keys(ue).length;return u(),clearTimeout(r),be(),void Ke({type:"close",code:m.VIOLATED_POLICY,codeName:"VIOLATED_POLICY",reason:e,outstandingInitiations:t})}n=void 0,s=void 0,0===Me&&U.length>1&&(clearTimeout(r),Ee(function(){_e(),ze()}))}je(new o(i.CONNECTING,ke,void 0,We(a),l(),Ae)),function e(){if(!J)return R("When doing countdown rounds, we realize that this MatsSocket instance is closed! - stopping right here."),void u();for(;c<=Date.now();)c+=100;if(c>=d)!function(){if(R("Create WebSocket: Attempt timeout exceeded ["+a+" ms], URL ["+ke+"] didn't work out."),u(),!J)return void R("After timed out attempt, we realize that this MatsSocket instance is closed! - stopping right here.");setTimeout(function(){_e(),ze()},Math.round(200*Math.random()))}();else{je(new o(i.COUNTDOWN,ke,void 0,We(a),l(),Ae));let t=Math.max(5,c-Date.now());r=setTimeout(function(){e()},t)}}(),y.preconnectoperation?function(){let e,t={webSocketUrl:ke,authorization:j};"function"==typeof y.preconnectoperation?e=y.preconnectoperation(t):"string"==typeof y.preconnectoperation?(t.directUrl=y.preconnectoperation,e=f(t)):e=f(t),n=e[0],e[1].then(function(e){n&&(R("PreConnectionOperation went OK ["+e+"], going on to create WebSocket."),g())}).catch(function(e){n&&(R("PreConnectionOperation failed ["+e+"] - retrying."),h())})}():g()}function xe(e){M("websocket.onerror","Got 'onerror' event from WebSocket, instanceId:["+e.target.webSocketInstanceId+"].",e),je(new o(i.CONNECTION_ERROR,ke,e,void 0,void 0,Ae))}function Be(e){if(R("websocket.onclose, instanceId:["+e.target.webSocketInstanceId+"]",e),e.code===m.UNEXPECTED_CONDITION||e.code===m.MATS_SOCKET_PROTOCOL_ERROR||e.code===m.VIOLATED_POLICY||e.code===m.CLOSE_SESSION||e.code===m.SESSION_LOST){M("session closed from server","The WebSocket was closed with a CloseCode ["+p.nameFor(e.code)+"] signifying that our MatsSocketSession is closed, reason:["+e.reason+"].",e);let t=Object.keys(ue).length;be(),e.codeName=p.nameFor(e.code),e.outstandingInitiations=t,Ke(e)}else e.code!==m.DISCONNECT?R("We were closed with a CloseCode ["+p.nameFor(e.code)+"] that does NOT denote that we should close the session. Initiate reconnect and reissue all outstanding."):R("We were closed with the special DISCONNECT close code - act as we lost connection, but do NOT start to reconnect."),Te(),ae=!0,je(new o(i.LOST_CONNECTION,ke,e,void 0,void 0,Ae)),e.code!==m.DISCONNECT&&setTimeout(function(){void 0!==W||q?R("Start reconnect after LOST_CONNECTION: Already gotten WebSocket, or started creation process. Bail out."):J?ze():R("Start reconnect after LOST_CONNECTION: MatsSocket is closed. Bail out.")},250+750*Math.random())}function He(n){let r=Date.now(),f=n.data,g=JSON.parse(f),h=g.length;y.logging&&R("websocket.onmessage, instanceId:["+n.target.webSocketInstanceId+"]: Got "+h+" messages.");for(let n=0;n<h;n++){let f=g[n];try{if(y.logging&&R(" \\- onmessage: handling message "+n+": "+f.t+", envelope:"+JSON.stringify(f)),f.t===s.WELCOME){y.sessionId=f.sid,y.logging&&R("We're WELCOME! SessionId:"+y.sessionId+", there are ["+Object.keys(ue).length+"] outstanding sends-or-requests, and ["+Object.keys(ge).length+"] outstanding replies."),D||(D=N.now()),je(new o(i.SESSION_ESTABLISHED,ke,void 0,void 0,void 0,Ae)),st();for(let e in ue){let t=ue[e],n=t.envelope;t.retransmitGuard!==fe?(t.attempt++,t.attempt>10?M("toomanyretries","Upon reconnect: Too many attempts at sending Initiation ["+n.t+"] with cmid:["+n.cmid+"], TraceId["+n.tid+"], size:["+JSON.stringify(n).length+"].",n):(Oe(n),y.flush())):y.logging&&R("RetransmitGuard: The outstanding Initiation ["+n.t+"] with cmid:["+n.cmid+"] and TraceId:["+n.tid+"] was created with the same RetransmitGuard as we currently have ["+fe+"] - they were sent directly trailing HELLO, before WELCOME came back in. No use in sending again.")}for(let e in ge){let t=ge[e],n=t.envelope;t.attempt++,t.attempt>10?M("toomanyretries","Upon reconnect: Too many attempts at sending Reply ["+n.t+"] with smid:["+n.smid+"], TraceId["+n.tid+"], size:["+JSON.stringify(n).length+"].",n):(Oe(n),y.flush())}}else if(f.t===s.REAUTH)ye("Server demands new Authorization",new e(t.REAUTHENTICATE,void 0));else if(f.t===s.RETRY){let e=ue[f.cmid];if(e){let t=e.envelope;if(e.attempt++,e.attempt>10){M("toomanyretries","Upon RETRY-request: Too many attempts at sending ["+t.t+"] with cmid:["+t.cmid+"], TraceId["+t.tid+"], size:["+JSON.stringify(t).length+"].",t);continue}let n=500*Math.pow(2,e.attempt-2)+Math.round(1e3*Math.random());setTimeout(function(){Oe(t)},n);continue}let t=ge[f.cmid];if(t){let n=t.envelope;if(t.attempt++,t.attempt>10){M("toomanyretries","Upon RETRY-request: Too many attempts at sending ["+n.t+"] with smid:["+n.smid+"], TraceId["+n.tid+"], size:["+JSON.stringify(n).length+"].",n);continue}let o=500*Math.pow(2,e.attempt-2)+Math.round(1e3*Math.random());setTimeout(function(){Oe(n)},o)}}else if(f.t===s.ACK||f.t===s.NACK){if(void 0===f.cmid&&void 0===f.ids){M("ack missing ids","The ACK/NACK envelope is missing 'cmid' or 'ids'.",f);continue}let e=[];void 0!==f.cmid&&e.push(f.cmid),void 0!==f.ids&&(e=e.concat(f.ids)),Ze(e);for(let t=0;t<e.length;t++){let n=e[t],o=ue[n];if(void 0===o){delete ge[n];continue}o.messageAcked_PerformanceNow=N.now(),et(f.t===s.ACK?a.ACK:a.NACK,o,r,f.desc);let i=le[n];i&&f.t!==s.ACK&&nt(i,d.REJECT,{},r)}}else if(f.t===s.ACK2){if(void 0===f.smid&&void 0===f.ids){M("ack2 missing ids","The ACK2 envelope is missing 'smid' or 'ids'",f);continue}if(f.smid&&delete he[f.smid],f.ids)for(let e=0;e<f.ids.length;e++)delete he[f.ids[e]]}else if(f.t===s.SEND||f.t===s.REQUEST){let e=f.t===s.SEND?"Terminator":"Endpoint";if(void 0===f.smid){M(f.t.toLowerCase()+" missing smid","The "+f.t+" envelope is missing 'smid'",f);continue}let t=f.t===s.SEND?Q[f.eid]:X[f.eid];if(Je(t?s.ACK:s.NACK,f.smid,t?void 0:"The Client "+e+" ["+f.eid+"] does not exist!"),void 0===t){M("client "+e.toLowerCase()+" does not exist","The Client "+e+" ["+f.eid+"] does not exist!!",f);continue}if(he[f.smid]){y.logging&&R("Caught double delivery of "+f.t+" with smid:["+f.smid+"], sending ACK, but won't process again.",f);continue}if(he[f.smid]=f,f.t===s.SEND){let e=tt(f,r);t.resolve(e)}else{let e=function(e,t){F=Date.now();let n={t:e,smid:f.smid,tid:f.tid,msg:t};n.cmid=ce++,ge[n.cmid]={attempt:1,envelope:n},Oe(n)};t(tt(f,r)).then(function(t){e(s.RESOLVE,t)}).catch(function(t){e(s.REJECT,t)})}}else if(f.t===s.RESOLVE||f.t===s.REJECT){f.smid&&Je(s.ACK,f.smid);let e=ue[f.cmid];e&&(Ze(f.cmid),et(a.ACK,e,r));let t=le[f.cmid];if(!t){y.logging&&R("Double delivery: Evidently we've already completed the Request for cmid:["+f.cmid+"], traiceId: ["+f.tid+"], ignoring.");continue}clearTimeout(t.timeoutId);let n=f.t===s.RESOLVE?d.RESOLVE:d.REJECT;e&&t.replyToTerminatorId?setTimeout(function(){nt(t,n,f,r)},20):nt(t,n,f,r)}else if(f.t===s.PING)Oe({t:s.PONG,x:f.x}),y.flush();else if(f.t===s.SUB_OK||f.t===s.SUB_LOST||f.t===s.SUB_NO_AUTH){let e;e=f.t===s.SUB_OK?u.OK:f.t===s.SUB_LOST?u.LOST_MESSAGES:u.NOT_AUTHORIZED;let t=new l(e,f.eid);for(let e=0;e<te.length;e++)try{te[e](t)}catch(e){M("notify SubscriptionEvent listeners","Caught error when notifying one of the ["+te.length+"] SubscriptionEvent listeners.",e)}}else if(f.t===s.PUB){let e=new c(d.PUB,f.msg,f.tid,f.smid,r),t=Z[f.eid];if(!t){M("message for unwanted topic","We got a PUB message for Topic ["+f.eid+"], but we have no subscribers for it.");continue}for(let n=0;n<t.listeners.length;n++)try{t.listeners[n](e)}catch(e){M("dispatch topic message","Caught error when notifying one of the ["+t.listeners.length+"] subscription listeners for Topic ["+f.eid+"].",e)}t.lastSmid=f.smid}else if(f.t===s.PONG){let e=de[f.x];delete de[f.x];let t=e[1],n=e[0];t.roundTripMillis=ot(N.now()-n);for(let e=0;e<ne.length;e++)try{ne[e](t)}catch(e){M("notify pingpongevent listeners","Caught error when notifying one of the ["+ne.length+"] PingPongEvent listeners.",e)}}}catch(e){let t=JSON.stringify(f);M("envelope processing","Got unexpected error while handling incoming envelope of type '"+f.t+"': "+(t.length>1024?t.substring(0,1021)+"...":t),e)}}}De();let Ge,Fe=[],qe=[];function Je(e,t,n){n?Oe({t:e,smid:t,desc:n}):(e===s.ACK?Fe.push(t):qe.push(t),clearTimeout(Ge),Fe.length+qe.length>10?Ve():Ge=setTimeout(Ve,20))}function Ve(){Fe.length>1?(Oe({t:s.ACK,ids:Fe}),Fe=[]):1===Fe.length&&(Oe({t:s.ACK,smid:Fe[0]}),Fe.length=0),qe.length>1?(Oe({t:s.NACK,ids:qe}),qe=[]):1===qe.length&&(Oe({t:s.NACK,smid:qe[0]}),qe.length=0)}let Ye,Qe,Xe=[];function Ze(e){Xe=Xe.concat(e),clearTimeout(Ye),Xe.length>10?$e():Ye=setTimeout($e,50)}function $e(){Xe.length>1?(Oe({t:s.ACK2,ids:Xe}),Xe=[]):1===Xe.length&&(Oe({t:s.ACK2,cmid:Xe[0]}),Xe.length=0)}function et(e,t,n,o=void 0){let i=N.now();t.messageAcked_PerformanceNow=i,delete ue[t.envelope.cmid];let c=new r(e,t.envelope.tid,t.sentTimestamp,n,ot(i-t.messageSent_PerformanceNow),o);if(e===a.ACK){if(t.ack)try{t.ack(c)}catch(t){M("received ack","When trying to ACK the initiation with ReceivedEvent ["+e+"], we got error.",t)}}else if(t.nack)try{t.nack(c)}catch(t){M("received nack","When trying to NACK the initiation with ReceivedEvent ["+e+"], we got error.",t)}t.envelope.t===s.SEND&&setTimeout(function(){it(t)},50)}function tt(e,t){let n=new c(e.t,e.msg,e.tid,e.smid,t);return e.debug&&(n.debug=new E(void 0,void 0,e,t)),n}function nt(e,t,n,o){clearTimeout(e.timeoutId);let i=N.now();delete le[e.envelope.cmid];let s=new c(t,n.msg,e.envelope.tid,e.envelope.cmid,o);if(s.clientRequestTimestamp=e.initiation.sentTimestamp,s.roundTripMillis=i-e.initiation.messageSent_PerformanceNow,s.correlationInformation=e.correlationInformation,0!==e.initiation.debug&&(s.debug=new E(e.initiation.sentTimestamp,e.initiation.debug,n,o)),it(e.initiation,e.replyToTerminatorId,s),e.replyToTerminatorId){let n=Q[e.replyToTerminatorId];setTimeout(function(){if(t===d.RESOLVE)try{n.resolve(s)}catch(t){M("replytoterminator resolve","When trying to pass a RESOLVE to Terminator ["+e.replyToTerminatorId+"], an exception was raised.",t)}else if(n.reject)try{n.reject(s)}catch(n){M("replytoterminator reject","When trying to pass a ["+t+"] to Terminator ["+e.replyToTerminatorId+"], an exception was raised.",n)}},0)}else delete le[e.envelope.cmid],t===d.RESOLVE?e.resolve(s):e.reject(s)}function ot(e){return Math.round(100*e)/100}function it(e,t=void 0,n=void 0){let o=D?ot(e.messageSent_PerformanceNow-D):0,i=ot(e.messageAcked_PerformanceNow-e.messageSent_PerformanceNow),s=n?ot(N.now()-e.messageSent_PerformanceNow):void 0,r=n?n.type:void 0;if(pe>0){let a=new f(e.envelope.eid,e.envelope.cmid,e.sentTimestamp,o,e.envelope.tid,e.envelope.msg,i,r,t,s,n);for(Se.push(a);Se.length>pe;)Se.shift()}if(e.suppressInitiationProcessedEvent)R("InitiationProcessedEvent is suppressed, so NOT notifying listeners.");else for(let a=0;a<oe.length;a++)try{let c=oe[a],d=c.includeInitiationMessage?e.envelope.msg:void 0,l=c.includeReplyMessageEvent?n:void 0,u=new f(e.envelope.eid,e.envelope.cmid,e.sentTimestamp,o,e.envelope.tid,d,i,r,t,s,l);y.logging&&R("Sending InitiationProcessedEvent to listener ["+(a+1)+"/"+oe.length+"]",u),c.listener(u)}catch(e){M("notify InitiationProcessedEvent listeners","Caught error when notifying one of the ["+oe.length+"] InitiationProcessedEvent listeners.",e)}}function st(){R("Starting PING'er!"),at(y.initialPingDelay)}let rt=0;function at(e){Qe=setTimeout(function(){const e=y.state;if(y.logging&&R("Ping-'thread': About to send ping. ConnectionState:["+e+"], matsSocketOpen:["+J+"]."),e===n.SESSION_ESTABLISHED&&J){let e=rt++,t=new h(e,Date.now());me.push(t),me.length>100&&me.shift(),de[e]=[N.now(),t],W.send('[{"t":"'+s.PING+'","x":"'+e+'"}]'),at(15e3)}else R("Ping-'thread': NOT sending Ping and NOT Rescheduling due to state!=SESSION_ESTABLISHED or !connected - exiting 'thread'.")},e)}}Object.freeze(w);export{e as AuthorizationRequiredEvent,t as AuthorizationRequiredEventType,o as ConnectionEvent,i as ConnectionEventType,n as ConnectionState,E as DebugInformation,w as DebugOption,S as ErrorEvent,f as InitiationProcessedEvent,g as InitiationProcessedEventType,T as MatsSocket,m as MatsSocketCloseCodes,c as MessageEvent,d as MessageEventType,s as MessageType,h as PingPong,r as ReceivedEvent,a as ReceivedEventType,l as SubscriptionEvent,u as SubscriptionEventType}; //# sourceMappingURL=MatsSocket.esm.min.js.map