matssocket
Version:
MatsSocket client library
3 lines (2 loc) • 37.8 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).matssocket={})}(this,function(e){"use strict";function t(e,t){this.type=e,this.currentExpirationTimestamp=t}const n={NOT_PRESENT:"notpresent",EXPIRED:"expired",REAUTHENTICATE:"reauthenticate"};Object.freeze(n);const o={NO_SESSION:"nosession",CONNECTING:"connecting",WAITING:"waiting",CONNECTED:"connected",SESSION_ESTABLISHED:"sessionestablished"};function i(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(o);const s={CONNECTING:o.CONNECTING,WAITING:o.WAITING,CONNECTED:o.CONNECTED,SESSION_ESTABLISHED:o.SESSION_ESTABLISHED,CONNECTION_ERROR:"connectionerror",LOST_CONNECTION:"lostconnection",COUNTDOWN:"countdown"};Object.freeze(s);const r={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 c(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(r);const a={ACK:"ack",NACK:"nack",TIMEOUT:"timeout",SESSION_CLOSED:"sessionclosed"};function d(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 l={RESOLVE:"resolve",REJECT:"reject",SEND:"send",REQUEST:"request",PUB:"pub",TIMEOUT:"timeout",SESSION_CLOSED:"sessionclosed"};function u(e,t){this.type=e,this.topicId=t}Object.freeze(l);const f={OK:"ok",NOT_AUTHORIZED:"notauthorized",LOST_MESSAGES:"lostmessages"};function g(e,t,n,o,i,s,r,c,a,d,l){this.type=a?h.REQUEST_REPLY_TO:c?h.REQUEST:h.SEND,this.endpointId=e,this.clientMessageId=t,this.sentTimestamp=n,this.sessionEstablishedOffsetMillis=o,this.traceId=i,this.initiationMessage=s,this.acknowledgeRoundTripMillis=r,this.replyMessageEventType=c,this.replyToTerminatorId=a,this.requestReplyRoundTripMillis=d,this.replyMessageEvent=l}Object.freeze(f);const h={SEND:"send",REQUEST:"request",REQUEST_REPLY_TO:"requestreplyto"};function p(e,t){this.pingId=e,this.sentTimestamp=t,this.roundTripMillis=void 0}Object.freeze(h);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 S=(()=>{const e=new Map(Object.entries(m).map(([e,t])=>[t,e]));return{nameFor:t=>e.get(t)??`UNKNOWN(${t})`}})();function E(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 w(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 T={TIMESTAMPS:1,NODES:2,CUSTOM_A:64,CUSTOM_B:128};Object.freeze(T),e.AuthorizationRequiredEvent=t,e.AuthorizationRequiredEventType=n,e.ConnectionEvent=i,e.ConnectionEventType=s,e.ConnectionState=o,e.DebugInformation=w,e.DebugOption=T,e.ErrorEvent=E,e.InitiationProcessedEvent=g,e.InitiationProcessedEventType=h,e.MatsSocket=function(e,h,T,b=null){let v="MatsSocket.js,1.0.0-2025-10-27";if("string"!=typeof e)throw new Error("appName must be a string, was: ["+e+"]");if("string"!=typeof h)throw new Error("appVersion must be a string, was: ["+h+"]");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 C,O,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+"].");O=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+"].");O=function(e,t){return new b.webSocket(e,t)}}if(!O)if("function"==typeof WebSocket)O=(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(()=>{O=(e,n)=>new t(e,n),R("Constructor: 'webSocketFactory' is now set."),I=!1,"function"==typeof C&&(R("Constructor: Invoking callback-method to restart WebSocket creation attempt."),C())},0)}).catch(e=>{I=!1,M("Import of WebSocket module failed","In Node.js environment, the import('ws') failed",e)})}let y="object"==typeof window&&window.performance||{now:function(){return Date.now()}};const N=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,N.flush()},this.setCurrentAuthorization=function(e,t=-1,o=3e4){this.logging&&R("Got Authorization which "+(-1!==t?"Expires in ["+(t-Date.now())+" ms]":"[Never expires]")+", roomForLatencyMillis: "+o),j=e,x=t,B=o,G===n.REAUTHENTICATE&&(R("Immediate send of new authentication due to REAUTHENTICATE"),ce=!0),G=void 0,N.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 pe}}),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 me},set:function(e){if(e<0)throw new Error("numberOfInitiationsKept must be >= 0");for(me=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?(Ce({t:r.SUB,eid:e},!0),n.subscriptionSentToServer=!0):(ce=!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&&(Ce({t:r.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,s){let c=Object.create(null);if(c.ack=i,c.nack=s,o){if("object"!=typeof o)throw new Error("The 'config' parameter wasn't an object.");o.suppressInitiationProcessedEvent&&(c.suppressInitiationProcessedEvent=!0)}let a=Object.create(null);a.t=r.SEND,a.eid=e,a.msg=n,ve(a,t,c,void 0)})},this.request=function(e,t,n,o=void 0){return new Promise(function(i,s){let c=N.requestTimeout,a=Object.create(null);if("function"==typeof o)a.ack=o,a.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.");a.ack=o.receivedCallback,a.nack=o.receivedCallback}else{if(o.ackCallback){if("function"!=typeof o.ackCallback)throw new Error("The 'configOrCallback.ackCallback' is not a function.");a.ack=o.ackCallback}if(o.nackCallback){if("function"!=typeof o.nackCallback)throw new Error("The 'configOrCallback.nackCallback' is not a function.");a.nack=o.nackCallback}}if(void 0!==o.timeout){if("number"!=typeof o.timeout)throw new Error("The 'configOrCallback.timeout' is not a number.");c=o.timeout}o.suppressInitiationProcessedEvent&&(a.suppressInitiationProcessedEvent=!0),void 0!==o.debug&&(a.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=s,d.timeout=c;let l=Object.create(null);l.t=r.REQUEST,l.eid=e,l.msg=n,l.to=c,ve(l,t,a,d)})},this.requestReplyTo=function(e,t,n,o,i,s=void 0){if(!Q[o])throw new Error("The Client Terminator ["+o+"] is not present, !");return new Promise(function(c,a){let d=Object.create(null);d.ack=c,d.nack=a;let l=N.requestTimeout;if(s){if("object"!=typeof s)throw new Error("The 'config' parameter wasn't an object.");if(void 0!==s.timeout){if("number"!=typeof s.timeout)throw new Error("The 'config.timeout' is not a number.");l=s.timeout}s.suppressInitiationProcessedEvent&&(d.suppressInitiationProcessedEvent=!0),void 0!==s.debug&&(d.debug=s.debug)}let u=Object.create(null);u.replyToTerminatorId=o,u.correlationInformation=i,u.timeout=l;let f=Object.create(null);f.t=r.REQUEST,f.eid=e,f.msg=n,f.to=l,ve(f,t,d,u)})},this.flush=function(){Oe&&(clearTimeout(Oe),Oe=void 0),ye()},this.close=function(e){let t=ke,n=N.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(N.logging&&R("reconnect(): Closing WebSocket with CloseCode '"+S.nameFor(n)+" ("+n+")', MatsSocketSessionId:["+N.sessionId+"] due to ["+e+"], currently connected: ["+(W?W.url:"not connected")+"]"),!W)throw new Error("There is no live WebSocket to close with "+S.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){N.logging&&(t?console.log(_+"/"+N.sessionId+"{"+(Date.now()-A)+"}: "+e,t):console.log(_+"/"+N.sessionId+"{"+(Date.now()-A)+"}: "+e))}function M(e,t,n){let o=new E(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)}N.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 _=N.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=o.NO_SESSION,re=!1,ce=!1,ae=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 pe=[];let me=10;const Se=[];function Ee(e){setTimeout(e,0)}function we(){N.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=N.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),N.sessionId=void 0,se=o.NO_SESSION,Te(),Y.length=0,J=!1;for(let e in ue){let t=ue[e];delete ue[e],N.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],N.logging&&R("Close Session: Clearing outstanding REQUEST to ["+t.envelope.eid+"], cmid:["+t.envelope.cmid+"], TraceId:["+t.envelope.tid+"].",t),nt(t,l.SESSION_CLOSED,{},Date.now())}}function ve(e,t,n,o){J=!0;let i=Date.now(),s=y.now();e.tid=t;let r=ae++;e.cmid=r,n.debug=void 0!==n.debug?n.debug:N.debug?N.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=y.now();N.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,l.TIMEOUT,{},Date.now())},50):nt(o,l.TIMEOUT,{},Date.now())},o.timeout),le[r]=o),Ce(e)}function Ce(e,t=!1){t?(N.logging&&R("ENQUEUE: Envelope of type ["+e.t+"] enqueued to PRE-pipeline: "+JSON.stringify(e)),V.push(e)):(N.logging&&R("ENQUEUE: Envelope of type ["+e.t+"] enqueued to pipeline: "+JSON.stringify(e)),Y.push(e)),Ie()}let Oe;function Ie(){Oe&&clearTimeout(Oe),Oe=setTimeout(function(){Oe=void 0,ye()},10)}function ye(){if(0!==Y.length||0!==V.length||ce)if(J)if(void 0!==j)if(void 0!==x&&-1!==x&&x-B<Date.now())Ne("Authorization is expired",new t(n.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 t={t:r.HELLO,clv:v+"; User-Agent: "+k,ts:Date.now(),an:e,av:h,auth:j,cid:N.randomId(10)};void 0!==N.sessionId?(R('HELLO not send, adding to pre-pipeline. HELLO ("Reconnect") to MatsSocketSessionId:['+N.sessionId+"]"),t.sid=N.sessionId):R('HELLO not sent, adding to pre-pipeline. HELLO ("New"), we will get assigned a MatsSocketSessionId upon WELCOME.'),V.unshift(t),re=!0,K=j;for(let e in Z){let t=Z[e];t.listeners.length>0&&!t.subscriptionSentToServer&&V.push({t:r.SUB,eid:e,smid:t.lastSmid}),0===t.listeners.length&&t.subscriptionSentToServer&&(V.push({t:r.UNSUB,eid:e}),delete Z[e])}}if(re&&K!==j){if(Y.length>0){let e=Y[Y.length-1];N.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 N.logging&&R("Authorization has changed, but there is no message in pipeline, so we add an AUTH message now."),Y.push({t:r.AUTH,auth:j});K=j}ce=!1,V.length>0&&(N.logging&&R("Flushing prePipeline of ["+V.length+"] messages: "+JSON.stringify(V)),W.send(JSON.stringify(V)),V.length=0),Y.length>0&&(N.logging&&R("Flushing pipeline of ["+Y.length+"] messages: "+JSON.stringify(Y)),W.send(JSON.stringify(Y)),Y.length=0)}else Ne("Authorization not present",new t(n.NOT_PRESENT,void 0));else R("evaluatePipelineSend(), but MatsSocket is not open - ignoring.")}function Ne(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(e){return new Promise(function(e,o){Ne("MatsSocket.renewAuth was invoked",new t(n.REAUTHENTICATE,void 0)),e({})})};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){!N.logging||e.type===s.COUNTDOWN&&e.countdownSeconds!==e.timeoutSeconds&&Math.round(e.countdownSeconds)!==e.countdownSeconds||R("Sending ConnectionEvent to listeners",e);let t=Object.keys(o).filter(function(t){return o[t]===e.type});1===t.length&&(se=o[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){N.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 Ne("Authorization is expired",new t(n.EXPIRED,x));if(!O){if(I)return R("InitiateWebSocketCreation: Missing matsSocketFactory, but import in progress! Wait for result of import attempt."),void(C=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 e,o,r,c=Me>10?Ue:Math.max(Pe,Math.min(Ue,Le*Math.pow(2,Me))),a=Date.now(),d=a+c,l=function(){return Math.round((d-Date.now())/100)/10};function u(){if(e){R(" \\- Within PreConnectionOperation phase - invoking preConnectOperationFunction's abort() function.");let t=e;e=void 0,t()}o&&(R(" \\- Within WebSocket connect phase - clearing handlers and invoking webSocket.close()."),o.onopen=void 0,o.onerror=function(e){N.logging&&R("!! websocketAttempt.onerror: Forced close by timeout, instanceId:["+e.target.webSocketInstanceId+"]",e)},o.onclose=function(e){N.logging&&R("!! websocketAttempt.onclose: Forced close by timeout, instanceId:["+e.target.webSocketInstanceId+"]",e)},o.close(m.CLOSE_SESSION,"WebSocket connect aborted"),o=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(e=void 0,o)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 t=ke+(N.preconnectoperation?"?preconnect=true":"");const n=N.randomId(6);N.logging&&R('INSTANTIATING new WebSocket("'+t+'", "matssocket") - InstanceId:['+n+"]"),o=O(t,"matssocket"),o.webSocketInstanceId=n,o.onerror=function(e){N.logging&&R("Create WebSocket: error. InstanceId:["+e.target.webSocketInstanceId+"]",e),o.onerror=void 0,o.onclose=void 0,o.onopen=void 0,je(new i(s.WAITING,ke,e,We(c),l(),Ae)),h()},o.onclose=function(e){N.logging&&R("Create WebSocket: close. InstanceId:["+e.target.webSocketInstanceId+"], Code:"+e.code+", Reason:"+e.reason,e),o.onerror=void 0,o.onclose=void 0,o.onopen=void 0,je(new i(s.WAITING,ke,e,We(c),l(),Ae)),h()},o.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=o,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 i(s.CONNECTED,ke,e,We(c),l(),Ae)),Ee(function(){R("WebSocket is open! Running evaluatePipelineSend() to start HELLO/WELCOME handshake."),ye()})}}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!==N.maxConnectionAttempts?N.maxConnectionAttempts:null!==N.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})}e=void 0,o=void 0,0===Me&&U.length>1&&(clearTimeout(r),Ee(function(){_e(),ze()}))}je(new i(s.CONNECTING,ke,void 0,We(c),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(;a<=Date.now();)a+=100;if(a>=d)!function(){if(R("Create WebSocket: Attempt timeout exceeded ["+c+" 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 i(s.COUNTDOWN,ke,void 0,We(c),l(),Ae));let t=Math.max(5,a-Date.now());r=setTimeout(function(){e()},t)}}(),N.preconnectoperation?function(){let t,n={webSocketUrl:ke,authorization:j};"function"==typeof N.preconnectoperation?t=N.preconnectoperation(n):"string"==typeof N.preconnectoperation?(n.directUrl=N.preconnectoperation,t=f(n)):t=f(n),e=t[0],t[1].then(function(t){e&&(R("PreConnectionOperation went OK ["+t+"], going on to create WebSocket."),g())}).catch(function(t){e&&(R("PreConnectionOperation failed ["+t+"] - retrying."),h())})}():g()}function xe(e){M("websocket.onerror","Got 'onerror' event from WebSocket, instanceId:["+e.target.webSocketInstanceId+"].",e),je(new i(s.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 ["+S.nameFor(e.code)+"] signifying that our MatsSocketSession is closed, reason:["+e.reason+"].",e);let t=Object.keys(ue).length;be(),e.codeName=S.nameFor(e.code),e.outstandingInitiations=t,Ke(e)}else e.code!==m.DISCONNECT?R("We were closed with a CloseCode ["+S.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(),ce=!0,je(new i(s.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(e){let o=Date.now(),c=e.data,g=JSON.parse(c),h=g.length;N.logging&&R("websocket.onmessage, instanceId:["+e.target.webSocketInstanceId+"]: Got "+h+" messages.");for(let e=0;e<h;e++){let c=g[e];try{if(N.logging&&R(" \\- onmessage: handling message "+e+": "+c.t+", envelope:"+JSON.stringify(c)),c.t===r.WELCOME){N.sessionId=c.sid,N.logging&&R("We're WELCOME! SessionId:"+N.sessionId+", there are ["+Object.keys(ue).length+"] outstanding sends-or-requests, and ["+Object.keys(ge).length+"] outstanding replies."),D||(D=y.now()),je(new i(s.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):(Ce(n),N.flush())):N.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):(Ce(n),N.flush())}}else if(c.t===r.REAUTH)Ne("Server demands new Authorization",new t(n.REAUTHENTICATE,void 0));else if(c.t===r.RETRY){let e=ue[c.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(){Ce(t)},n);continue}let t=ge[c.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(){Ce(n)},o)}}else if(c.t===r.ACK||c.t===r.NACK){if(void 0===c.cmid&&void 0===c.ids){M("ack missing ids","The ACK/NACK envelope is missing 'cmid' or 'ids'.",c);continue}let e=[];void 0!==c.cmid&&e.push(c.cmid),void 0!==c.ids&&(e=e.concat(c.ids)),Ze(e);for(let t=0;t<e.length;t++){let n=e[t],i=ue[n];if(void 0===i){delete ge[n];continue}i.messageAcked_PerformanceNow=y.now(),et(c.t===r.ACK?a.ACK:a.NACK,i,o,c.desc);let s=le[n];s&&c.t!==r.ACK&&nt(s,l.REJECT,{},o)}}else if(c.t===r.ACK2){if(void 0===c.smid&&void 0===c.ids){M("ack2 missing ids","The ACK2 envelope is missing 'smid' or 'ids'",c);continue}if(c.smid&&delete he[c.smid],c.ids)for(let e=0;e<c.ids.length;e++)delete he[c.ids[e]]}else if(c.t===r.SEND||c.t===r.REQUEST){let e=c.t===r.SEND?"Terminator":"Endpoint";if(void 0===c.smid){M(c.t.toLowerCase()+" missing smid","The "+c.t+" envelope is missing 'smid'",c);continue}let t=c.t===r.SEND?Q[c.eid]:X[c.eid];if(Je(t?r.ACK:r.NACK,c.smid,t?void 0:"The Client "+e+" ["+c.eid+"] does not exist!"),void 0===t){M("client "+e.toLowerCase()+" does not exist","The Client "+e+" ["+c.eid+"] does not exist!!",c);continue}if(he[c.smid]){N.logging&&R("Caught double delivery of "+c.t+" with smid:["+c.smid+"], sending ACK, but won't process again.",c);continue}if(he[c.smid]=c,c.t===r.SEND){let e=tt(c,o);t.resolve(e)}else{let e=function(e,t){F=Date.now();let n={t:e,smid:c.smid,tid:c.tid,msg:t};n.cmid=ae++,ge[n.cmid]={attempt:1,envelope:n},Ce(n)};t(tt(c,o)).then(function(t){e(r.RESOLVE,t)}).catch(function(t){e(r.REJECT,t)})}}else if(c.t===r.RESOLVE||c.t===r.REJECT){c.smid&&Je(r.ACK,c.smid);let e=ue[c.cmid];e&&(Ze(c.cmid),et(a.ACK,e,o));let t=le[c.cmid];if(!t){N.logging&&R("Double delivery: Evidently we've already completed the Request for cmid:["+c.cmid+"], traiceId: ["+c.tid+"], ignoring.");continue}clearTimeout(t.timeoutId);let n=c.t===r.RESOLVE?l.RESOLVE:l.REJECT;e&&t.replyToTerminatorId?setTimeout(function(){nt(t,n,c,o)},20):nt(t,n,c,o)}else if(c.t===r.PING)Ce({t:r.PONG,x:c.x}),N.flush();else if(c.t===r.SUB_OK||c.t===r.SUB_LOST||c.t===r.SUB_NO_AUTH){let e;e=c.t===r.SUB_OK?f.OK:c.t===r.SUB_LOST?f.LOST_MESSAGES:f.NOT_AUTHORIZED;let t=new u(e,c.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(c.t===r.PUB){let e=new d(l.PUB,c.msg,c.tid,c.smid,o),t=Z[c.eid];if(!t){M("message for unwanted topic","We got a PUB message for Topic ["+c.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 ["+c.eid+"].",e)}t.lastSmid=c.smid}else if(c.t===r.PONG){let e=de[c.x];delete de[c.x];let t=e[1],n=e[0];t.roundTripMillis=ot(y.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(c);M("envelope processing","Got unexpected error while handling incoming envelope of type '"+c.t+"': "+(t.length>1024?t.substring(0,1021)+"...":t),e)}}}De();let Ge,Fe=[],qe=[];function Je(e,t,n){n?Ce({t:e,smid:t,desc:n}):(e===r.ACK?Fe.push(t):qe.push(t),clearTimeout(Ge),Fe.length+qe.length>10?Ve():Ge=setTimeout(Ve,20))}function Ve(){Fe.length>1?(Ce({t:r.ACK,ids:Fe}),Fe=[]):1===Fe.length&&(Ce({t:r.ACK,smid:Fe[0]}),Fe.length=0),qe.length>1?(Ce({t:r.NACK,ids:qe}),qe=[]):1===qe.length&&(Ce({t:r.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?(Ce({t:r.ACK2,ids:Xe}),Xe=[]):1===Xe.length&&(Ce({t:r.ACK2,cmid:Xe[0]}),Xe.length=0)}function et(e,t,n,o=void 0){let i=y.now();t.messageAcked_PerformanceNow=i,delete ue[t.envelope.cmid];let s=new c(e,t.envelope.tid,t.sentTimestamp,n,ot(i-t.messageSent_PerformanceNow),o);if(e===a.ACK){if(t.ack)try{t.ack(s)}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(s)}catch(t){M("received nack","When trying to NACK the initiation with ReceivedEvent ["+e+"], we got error.",t)}t.envelope.t===r.SEND&&setTimeout(function(){it(t)},50)}function tt(e,t){let n=new d(e.t,e.msg,e.tid,e.smid,t);return e.debug&&(n.debug=new w(void 0,void 0,e,t)),n}function nt(e,t,n,o){clearTimeout(e.timeoutId);let i=y.now();delete le[e.envelope.cmid];let s=new d(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 w(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===l.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===l.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(y.now()-e.messageSent_PerformanceNow):void 0,r=n?n.type:void 0;if(me>0){let c=new g(e.envelope.eid,e.envelope.cmid,e.sentTimestamp,o,e.envelope.tid,e.envelope.msg,i,r,t,s,n);for(Se.push(c);Se.length>me;)Se.shift()}if(e.suppressInitiationProcessedEvent)R("InitiationProcessedEvent is suppressed, so NOT notifying listeners.");else for(let c=0;c<oe.length;c++)try{let a=oe[c],d=a.includeInitiationMessage?e.envelope.msg:void 0,l=a.includeReplyMessageEvent?n:void 0,u=new g(e.envelope.eid,e.envelope.cmid,e.sentTimestamp,o,e.envelope.tid,d,i,r,t,s,l);N.logging&&R("Sending InitiationProcessedEvent to listener ["+(c+1)+"/"+oe.length+"]",u),a.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!"),ct(N.initialPingDelay)}let rt=0;function ct(e){Qe=setTimeout(function(){const e=N.state;if(N.logging&&R("Ping-'thread': About to send ping. ConnectionState:["+e+"], matsSocketOpen:["+J+"]."),e===o.SESSION_ESTABLISHED&&J){let e=rt++,t=new p(e,Date.now());pe.push(t),pe.length>100&&pe.shift(),de[e]=[y.now(),t],W.send('[{"t":"'+r.PING+'","x":"'+e+'"}]'),ct(15e3)}else R("Ping-'thread': NOT sending Ping and NOT Rescheduling due to state!=SESSION_ESTABLISHED or !connected - exiting 'thread'.")},e)}},e.MatsSocketCloseCodes=m,e.MessageEvent=d,e.MessageEventType=l,e.MessageType=r,e.PingPong=p,e.ReceivedEvent=c,e.ReceivedEventType=a,e.SubscriptionEvent=u,e.SubscriptionEventType=f});
//# sourceMappingURL=MatsSocket.umd.min.js.map