matssocket
Version:
MatsSocket client library
1 lines • 327 kB
Source Map (JSON)
{"version":3,"file":"MatsSocket.umd.cjs","sources":["../lib/AuthorizationRequiredEvent.js","../lib/ConnectionState.js","../lib/ConnectionEvent.js","../lib/MessageType.js","../lib/ReceivedEvent.js","../lib/MessageEvent.js","../lib/SubscriptionEvent.js","../lib/InitiationProcessedEvent.js","../lib/PingPong.js","../lib/MatsSocketCloseCodes.js","../lib/ErrorEvent.js","../lib/DebugInformation.js","../lib/MatsSocket.js"],"sourcesContent":["import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nexport { AuthorizationRequiredEvent, AuthorizationRequiredEventType }\n\n/**\n * Sent by the MatsSocket, via the {@link MatsSocket#setAuthorizationExpiredCallback}, when it requires new or\n * revalidated authentication by the client.\n *\n * @param {AuthorizationRequiredEventType} type - {@link AuthorizationRequiredEvent#type}\n * @param {Timestamp} currentExpirationTimestamp - {@link AuthorizationRequiredEvent#currentExpirationTimestamp}\n * @class\n */\nfunction AuthorizationRequiredEvent(type, currentExpirationTimestamp) {\n /**\n * Type of the event, one of {@link AuthorizationRequiredEventType}.\n *\n * @type {AuthorizationRequiredEventType}\n */\n this.type = type;\n\n /**\n * Millis-since-epoch when the current Authorization expires - note that this might well still be in the future,\n * but the \"slack\" left before expiration is used up.\n *\n * @type {Timestamp}\n */\n this.currentExpirationTimestamp = currentExpirationTimestamp;\n}\n\n/**\n * Type of {@link AuthorizationRequiredEvent}.\n *\n * @enum {string}\n * @readonly\n */\nconst AuthorizationRequiredEventType = {\n /**\n * Initial state, if auth not already set by app.\n */\n NOT_PRESENT: \"notpresent\",\n\n /**\n * The authentication is expired - note that this might well still be in the future,\n * but the \"slack\" left before expiration is not long enough.\n */\n EXPIRED: \"expired\",\n\n /**\n * The server has requested that the app provides fresh auth to proceed - this needs to be fully fresh, even\n * though there might still be \"slack\" enough left on the current authorization to proceed. (The server side\n * might want the full expiry to proceed, or wants to ensure that the app can still produce new auth - i.e.\n * it might suspect that the current authentication session has been invalidated, and need proof that the app\n * can still produce new authorizations/tokens).\n */\n REAUTHENTICATE: \"reauthenticate\"\n};\nObject.freeze(AuthorizationRequiredEventType);","export { ConnectionState }\n\n/**\n * States for MatsSocket's {@link MatsSocket#state state}.\n *\n * @enum {string}\n * @readonly\n */\nconst ConnectionState = {\n /**\n * This is the initial State of a MatsSocket. Also, the MatsSocket is re-set back to this State in a\n * Session-Closed-from-Server situation (which is communicated via listeners registered with\n * {@link MatsSocket#addSessionClosedEventListener}), OR if you have explicitly performed a\n * {@link MatsSocket#close}.\n * <p/>\n * Only transition out of this state is into {@link ConnectionState.CONNECTING}.\n */\n NO_SESSION: \"nosession\",\n\n /**\n * Read doc at {@link ConnectionEventType.CONNECTING}.\n */\n CONNECTING: \"connecting\",\n\n /**\n * Read doc at {@link ConnectionEventType.WAITING}.\n */\n WAITING: \"waiting\",\n\n /**\n * Read doc at {@link ConnectionEventType.CONNECTED}.\n */\n CONNECTED: \"connected\",\n\n /**\n * Read doc at {@link ConnectionEventType.SESSION_ESTABLISHED}.\n */\n SESSION_ESTABLISHED: \"sessionestablished\"\n};\nObject.freeze(ConnectionState);\n","import { ConnectionState } from \"./ConnectionState.js\";\n\nexport { ConnectionEvent, ConnectionEventType }\n\n/**\n * Event object for {@link MatsSocket#addConnectionEventListener}.\n * <p />\n * <b>Note on event ordering</b>: {@link ConnectionEvent}s are delivered ASAP. This means that for events that the\n * client controls, they are issued <i/>before</i> the operation they describe commences:\n * {@link ConnectionEventType#CONNECTING CONNECTING} and\n * {@link ConnectionEventType#SESSION_ESTABLISHED SESSION_ESTABLISHED}. However, for events where the client is\n * \"reacting\", e.g. when the WebSocket connects, or abruptly closes, they are issued ASAP when the Client gets to know about it:\n * {@link ConnectionEventType#CONNECTED CONNECTED}, {@link ConnectionEventType#LOST_CONNECTION LOST_CONNECTION},\n * {@link ConnectionEventType#CONNECTION_ERROR CONNECTION_ERROR} and {@link ConnectionEventType#WAITING WAITING}.\n * For {@link ConnectionEventType#COUNTDOWN COUNTDOWN}, there is not much to say wrt. timing, other than you won't typically\n * get a 'countdown'-event with 0 seconds left, as that is when we transition into 'connecting' again. For events\n * that also describe {@link ConnectionState}s, the {@link MatsSocket.state} is updated before the event is fired.\n *\n * @param {ConnectionEventType} type - {@link ConnectionEvent#type}\n * @param {string} webSocketUrl - {@link ConnectionEvent#webSocketUrl}\n * @param {Event} webSocketEvent - {@link ConnectionEvent#webSocketEvent}\n * @param {number} timeoutSeconds - {@link ConnectionEvent#timeoutSeconds}\n * @param {number} countdownSeconds - {@link ConnectionEvent#countdownSeconds}\n * @param {number} connectionAttempt - {@link ConnectionEvent#connectionAttempt}\n * @class\n */\nfunction ConnectionEvent(type, webSocketUrl, webSocketEvent, timeoutSeconds, countdownSeconds, connectionAttempt) {\n /**\n * The type of the <code>ConnectionEvent</code>, returns an enum value of {@link ConnectionEventType}.\n *\n * @type {ConnectionEventType}\n */\n this.type = type;\n\n /**\n * Holds the current URL we're either connected to, was connected to, or trying to connect to.\n *\n * @type {string}\n */\n this.webSocketUrl = webSocketUrl;\n\n /**\n * For several of the events (enumerated in {@link ConnectionEventType}), there is an underlying WebSocket event\n * that caused it. This field holds that.\n * <ul>\n * <li>{@link ConnectionEventType#WAITING}: WebSocket {@link CloseEvent} that caused this transition.</li>\n * <li>{@link ConnectionEventType#CONNECTED}: WebSocket {@link Event} that caused this transition.</li>\n * <li>{@link ConnectionEventType#CONNECTION_ERROR}: WebSocket {@link Event} that caused this transition.</li>\n * <li>{@link ConnectionEventType#LOST_CONNECTION}: WebSocket {@link CloseEvent} that caused it.</li>\n * </ul>\n *\n * @type {Event}\n */\n this.webSocketEvent = webSocketEvent;\n\n /**\n * For {@link ConnectionEventType#CONNECTING}, {@link ConnectionEventType#WAITING} and {@link ConnectionEventType#COUNTDOWN},\n * tells how long the timeout for this attempt is, i.e. what the COUNTDOWN events start out with. Together with\n * {@link #countdownSeconds} of the COUNTDOWN events, this can be used to calculate a fraction if you want to\n * make a \"progress bar\" of sorts.\n * <p/>\n * The timeouts starts at 500 ms (unless there is only 1 URL configured, in which case 5 seconds), and then\n * increases exponentially, but maxes out at 15 seconds.\n *\n * @type {number}\n */\n this.timeoutSeconds = timeoutSeconds;\n\n /**\n * For {@link ConnectionEventType#CONNECTING}, {@link ConnectionEventType#WAITING} and {@link ConnectionEventType#COUNTDOWN},\n * tells how many seconds there are left for this attempt (of the {@link #timeoutSeconds} it started with),\n * with a tenth of a second as precision. With the COUNTDOWN events, these come in each 100 ms (1/10 second),\n * and show how long time there is left before trying again (if MatsSocket is configured with multiple URLs,\n * the next attempt will be a different URL).\n * <p/>\n * The countdown is started when the state transitions to {@link ConnectionEventType#CONNECTING}, and\n * stops either when {@link ConnectionEventType#CONNECTED} or the timeout reaches zero. If the\n * state is still CONNECTING when the countdown reaches zero, implying that the \"new WebSocket(..)\" call still\n * has not either opened or closed, the connection attempt is aborted by calling webSocket.close(). It then\n * tries again, possibly with a different URL - and the countdown starts over.\n * <p/>\n * Notice that the countdown is not affected by any state transition into {@link ConnectionEventType#WAITING} -\n * such transition only means that the \"new WebSocket(..)\" call failed and emitted a close-event, but we will\n * still wait out the countdown before trying again.\n * <p/>\n * Notice that you will most probably not get an event with 0 seconds, as that is when we transition into\n * {@link ConnectionEventType#CONNECTING} and the countdown starts over (possibly with a larger timeout).\n * <p/>\n * Truncated exponential backoff: The timeouts starts at 500 ms (unless there is only 1 URL configured, in which\n * case 5 seconds), and then increases exponentially, but maxes out at 15 seconds.\n *\n * @type {number}\n */\n this.countdownSeconds = countdownSeconds;\n\n /**\n * The connection attempt count, starts at 0th attempt and increases for each time the connection attempt fails.\n *\n * @type {number}\n */\n this.connectionAttempt = connectionAttempt;\n}\n\n\n/**\n * The event types of {@link ConnectionEvent} - four of the event types are state-transitions into different states\n * of {@link ConnectionState}.\n *\n * @enum {string}\n * @readonly\n */\nconst ConnectionEventType = {\n /**\n * State, and fires as ConnectionEvent when we transition into this state, which is when the WebSocket is literally trying to connect.\n * This is between <code>new WebSocket(url)</code> (or the {@link MatsSocket#preconnectoperation \"PreConnectOperation\"} if configured),\n * and either webSocket.onopen or webSocket.onclose is fired, or countdown reaches 0. If webSocket.onopen,\n * we transition into {@link ConnectionEventType.CONNECTED}, if webSocket.onclose, we transition into\n * {@link ConnectionEventType.WAITING}. If we reach countdown 0 while in CONNECTING, we will \"re-transition\" to the same state, and\n * thus get one more event of CONNECTING.\n * <p/>\n * User Info Tip: Show a info-box, stating \"Connecting! <4.0 seconds..>\", countdown in \"grayed out\" style, box is\n * some neutral information color, e.g. yellow (fading over to this color if already red or orange due to\n * {@link ConnectionEventType.CONNECTION_ERROR} or {@link ConnectionEventType.LOST_CONNECTION}).\n * Each time it transitions into CONNECTING, it will start a new countdown. Let's say it starts from say 4\n * seconds: If this connection attempt fails after 1 second, it will transition into WAITING and continue the\n * countdown with 3 seconds remaining.\n */\n CONNECTING: ConnectionState.CONNECTING,\n\n /**\n * State, and fires as ConnectionEvent when we transition into this state, which is when {@link ConnectionEventType.CONNECTING} fails.\n * The only transition out of this state is {@link ConnectionEventType.CONNECTING}, when the {@link ConnectionEventType.COUNTDOWN} reaches 0.\n * <p/>\n * Notice that the {@link ConnectionEvent} contains the {@link Event} that came with webSocket.close (while CONNECTING).\n * <p/>\n * User Info Tip: Show a info-box, stating \"Waiting! <2.9 seconds..>\", countdown in normal visibility, box is\n * some neutral information color, e.g. yellow (keeping the box color fading if in progress).\n * It will come into this state from {@link ConnectionEventType.CONNECTING}, and have the time remaining from the initial countdown.\n * So if the attempt countdown started from 4 seconds, and it took 1 second before the connection attempt failed,\n * then there will be 3 seconds left in WAITING state.\n */\n WAITING: ConnectionState.WAITING,\n\n /**\n * State, and fires as ConnectionEvent when we transition into this state, which is when WebSocket.onopen is fired.\n * Notice that the MatsSocket is still not fully established, as we have not yet exchanged HELLO and WELCOME -\n * the MatsSocket is fully established at {@link ConnectionEventType.SESSION_ESTABLISHED}.\n * <p/>\n * Notice that the {@link ConnectionEvent} contains the WebSocket 'onopen' {@link Event} that was issued when\n * the WebSocket opened.\n * <p/>\n * User Info Tip: Show a info-box, stating \"Connected!\", happy-color, e.g. green, with no countdown.\n */\n CONNECTED: ConnectionState.CONNECTED,\n\n /**\n * State, and fires as ConnectionEvent when we transition into this state, which is when when the WELCOME MatsSocket message comes\n * from the Server, also implying that it has been authenticated: The MatsSocket is now fully established, and\n * actual messages can be exchanged.\n * <p/>\n * User Info Tip: Show a info-box, stating \"Session OK!\", happy-color, e.g. green, with no countdown - and the\n * entire info-box fades away fast, e.g. after 1 second.\n */\n SESSION_ESTABLISHED: ConnectionState.SESSION_ESTABLISHED,\n\n /**\n * This is a pretty worthless event. It comes from WebSocket.onerror. It will <i>always</i> be trailed by a\n * WebSocket.onclose, which gives the event {@link ConnectionEventType.LOST_CONNECTION}.\n * <p/>\n * Notice that the {@link ConnectionEvent} contains the {@link Event} that caused the error.\n * <p/>\n * User Info Tip: Show a info-box, which is some reddish color (no need for text since next event {@link ConnectionEventType.LOST_CONNECTION}) comes immediately).\n */\n CONNECTION_ERROR: \"connectionerror\",\n\n /**\n * This comes when WebSocket.onclose is fired \"unexpectedly\", <b>and the reason for this close is NOT a SessionClosed Event</b> (The latter will\n * instead invoke the listeners registered with {@link MatsSocket#addSessionClosedEventListener}).\n * A LOST_CONNECTION will start a reconnection attempt after a very brief delay (couple of hundred milliseconds),\n * and the next state transition and thus event is {@link ConnectionEventType.CONNECTING}.\n * <p/>\n * Notice that the {@link ConnectionEvent} contains the {@link CloseEvent} that caused the lost connection.\n * <p/>\n * User Info Tip: Show a info-box, stating \"Connection broken!\", which is some orange color (unless it already\n * is red due to {@link ConnectionEventType.CONNECTION_ERROR}), fading over to the next color when next event ({@link ConnectionEventType.CONNECTING}\n * comes in.\n */\n LOST_CONNECTION: \"lostconnection\",\n\n /**\n * Events fired every 100ms while in state {@link ConnectionEventType.CONNECTING}, possibly continuing over to {@link ConnectionEventType.WAITING}.\n * Notice that you will most probably not get an event with 0 seconds left, as that is when we (re-)transition to\n * {@link ConnectionEventType.CONNECTING} and the countdown starts over (possibly with a larger timeout). Read more at\n * {@link ConnectionEvent#countdownSeconds}.\n * <p/>\n * User Info Tip: Read more at {@link ConnectionEventType.CONNECTING} and {@link ConnectionEventType.WAITING}.\n */\n COUNTDOWN: \"countdown\"\n\n};\nObject.freeze(ConnectionEventType);\n","export { MessageType }\n\n/**\n * <b>Copied directly from MatsSocketServer.java</b>:\n * All Message Types (aka MatsSocket Envelope Types) used in the wire-protocol of MatsSocket.\n *\n * @enum {string}\n * @readonly\n */\nconst MessageType = {\n /**\n * A HELLO message must be part of the first Pipeline of messages, preferably alone. One of the messages in the\n * first Pipeline must have the \"auth\" field set, and it might as well be the HELLO.\n */\n HELLO: \"HELLO\",\n\n /**\n * The reply to a {@link #HELLO}, where the MatsSocketSession is established, and the MatsSocketSessionId is\n * returned. If you included a MatsSocketSessionId in the HELLO, signifying that you want to reconnect to an\n * existing session, and you actually get a WELCOME back, it will be the same as what you provided - otherwise\n * the connection is closed with {@link MatsSocketCloseCodes#SESSION_LOST}.\n */\n WELCOME: \"WELCOME\",\n\n /**\n * The sender sends a \"fire and forget\" style message.\n */\n SEND: \"SEND\",\n\n /**\n * The sender initiates a request, to which a {@link #RESOLVE} or {@link #REJECT} message is expected.\n */\n REQUEST: \"REQUEST\",\n\n /**\n * The sender should retry the message (the receiver could not handle it right now, but a Retry might fix it).\n */\n RETRY: \"RETRY\",\n\n /**\n * The specified message was Received, and acknowledged positively - i.e. the other party has decided to process\n * it.\n * <p/>\n * The sender of the ACK has now taken over responsibility of the specified message, put it (at least the\n * reference ClientMessageId) in its <i>Inbox</i>, and possibly started processing it. The reason for the Inbox\n * is so that if it Receives the message again, it may just insta-ACK/NACK it and toss this copy out the window\n * (since it has already handled it).\n * <p/>\n * When an ACK is received, the receiver may safely delete the acknowledged message from its <i>Outbox</i>.\n */\n ACK: \"ACK\",\n\n /**\n * The specified message was Received, but it did not acknowledge it - i.e. the other party has decided to NOT\n * process it.\n * <p/>\n * The sender of the NACK has now taken over responsibility of the specified message, put it (at least the\n * reference Client/Server MessageId) in its <i>Inbox</i> - but has evidently decided not to process it. The\n * reason for the Inbox is so that if it Receives the message again, it may just insta-ACK/NACK it and toss this\n * copy out the window (since it has already handled it).\n * <p/>\n * When an NACK is received, the receiver may safely delete the acknowledged message from its <i>Outbox</i>.\n */\n NACK: \"NACK\",\n\n /**\n * An \"Acknowledge ^ 2\", i.e. an acknowledge of the {@link #ACK} or {@link #NACK}. When the receiver gets this,\n * it may safely delete the entry it has for the specified message from its <i>Inbox</i>.\n * <p/>\n * The message is now fully transferred from one side to the other, and both parties again has no reference to\n * this message in their Inbox and Outbox.\n */\n ACK2: \"ACK2\",\n\n /**\n * A RESOLVE-reply to a previous {@link #REQUEST} - if the Client did the {@code REQUEST}, the Server will\n * answer with either a RESOLVE or {@link #REJECT}.\n */\n RESOLVE: \"RESOLVE\",\n\n /**\n * A REJECT-reply to a previous {@link #REQUEST} - if the Client did the {@code REQUEST}, the Server will answer\n * with either a REJECT or {@link #RESOLVE}.\n */\n REJECT: \"REJECT\",\n\n /**\n * Request from Client: The Client want to subscribe to a Topic, the TopicId is specified in 'eid'.\n */\n SUB: \"SUB\",\n\n /**\n * Request from Client: The Client want to unsubscribe to a Topic, the TopicId is specified in 'eid'.\n */\n UNSUB: \"UNSUB\",\n\n /**\n * Reply from Server: Subscription was OK. If this is a reconnect, this indicates that any messages that was\n * lost \"while offline\" will now be delivered/\"replayed\".\n */\n SUB_OK: \"SUB_OK\",\n\n /**\n * Reply from Server: Subscription went OK, but you've lost messages: The messageId that was referenced in the\n * {@link #SUB} was not known to the server, implying that there are at least one message that has expired, and\n * as such it can be many - so you won't get any \"replayed\".\n */\n SUB_LOST: \"SUB_LOST\",\n\n /**\n * Reply from Server: Subscription was not authorized - no messages for this Topic will be delivered.\n */\n SUB_NO_AUTH: \"SUB_NO_AUTH\",\n\n /**\n * Topic message from Server: A message is issued on Topic, the TopicId is specified in 'eid', while the message\n * is in 'msg'.\n */\n PUB: \"PUB\",\n\n /**\n * The server requests that the Client re-authenticates, where the Client should immediately get a fresh\n * authentication and send it back using either any message it has pending, or in a separate {@link #AUTH}\n * message. Message processing - both processing of received messages, and sending of outgoing messages (i.e.\n * Replies to REQUESTs, or Server-initiated SENDs and REQUESTs) will be stalled until such auth is gotten.\n */\n REAUTH: \"REAUTH\",\n\n /**\n * From Client: The client can use a separate AUTH message to send over the requested {@link #REAUTH} (it could\n * just as well put the 'auth' in a PING or any other message it had pending).\n */\n AUTH: \"AUTH\",\n\n /**\n * A PING, to which a {@link #PONG} is expected.\n */\n PING: \"PING\",\n\n /**\n * A Reply to a {@link #PING}.\n */\n PONG: \"PONG\"\n};\nObject.freeze(MessageType);\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nexport { ReceivedEvent, ReceivedEventType }\n\n/**\n * Message Received on Server event: \"acknowledge\" or \"negative acknowledge\" - these are the events which the\n * returned Promise of a send(..) is settled with (i.e. then() and catch()), and which\n * {@link MatsSocket#request request}'s receivedCallback function are invoked with.\n *\n * @param {ReceivedEventType} type - {@link ReceivedEvent#type}\n * @param {string} traceId - {@link ReceivedEvent#traceId}\n * @param {Timestamp} sentTimestamp - {@link ReceivedEvent#sentTimestamp}\n * @param {Timestamp} receivedTimestamp - {@link ReceivedEvent#receivedTimestamp}\n * @param {Timestamp} roundTripMillis - {@link ReceivedEvent#roundTripMillis}\n * @param {string} description - {@link ReceivedEvent#description}\n * @class\n */\nfunction ReceivedEvent(type, traceId, sentTimestamp, receivedTimestamp, roundTripMillis, description) {\n /**\n * Values are from {@link ReceivedEventType}: Type of received event, either {@link ReceivedEventType#ACK \"ack\"},\n * {@link ReceivedEventType#NACK \"nack\"} - <b>or {@link ReceivedEventType#SESSION_CLOSED \"sessionclosed\"} if the\n * session was closed with outstanding initiations and MatsSocket therefore \"clears out\" these initiations.</b>\n *s\n * @type {ReceivedEventType}\n */\n this.type = type;\n\n /**\n * TraceId for this call / message.\n *\n * @type {string}\n */\n this.traceId = traceId;\n\n /**\n * Millis-since-epoch when the message was sent from the Client.\n *\n * @type {Timestamp}\n */\n this.sentTimestamp = sentTimestamp;\n\n /**\n * Millis-since-epoch when the ACK or NACK was received on the Client, millis-since-epoch.\n *\n * @type {Timestamp}\n */\n this.receivedTimestamp = receivedTimestamp;\n\n /**\n * Round-trip time in milliseconds from Initiation of flow (send, request, requestReplyTo) to Received\n * acknowledgement (ACK/NACK) was received, basically <code>{@link #receivedTimestamp}\n * - {@link #sentTimestamp}</code>, but depending on the browser/runtime, you might get higher resolution\n * than integer milliseconds (i.e. fractions of milliseconds, a floating point number) - it depends on\n * the resolution of <code>performance.now()</code>.\n * <p/>\n * Notice that Received-events might be de-prioritized on the Server side (batched up, with micro-delays\n * to get multiple into the same batch), so this number should not be taken as the \"ping time\".\n *\n * @type {FractionalMillis}\n */\n this.roundTripMillis = roundTripMillis;\n\n /**\n * Sometimes, typically on Server NACKs (e.g. targetting non-existing Endpoint), the Server supplies a\n * description to why this was no good.\n *\n * @type {string}\n */\n this.description = description;\n}\n\n/**\n * Types of {@link ReceivedEvent}.\n *\n * @enum {string}\n * @readonly\n */\nconst ReceivedEventType = {\n /**\n * If the Server-side MatsSocketEndpoint/Terminator accepted the message for handling (and if relevant,\n * forwarded it to the Mats fabric). The returned Promise of send() is <i>resolved</i> with this type of event.\n * The 'receivedCallback' of a request() will get both \"ack\" and {@link #NACK \"nack\"}, thus must check on\n * the type if it makes a difference.\n */\n ACK: \"ack\",\n\n /**\n * If the Server-side MatsSocketEndpoint/Terminator dit NOT accept the message, either explicitly with\n * context.deny(), or by failing with Exception. The returned Promise of send() is <i>rejected</i> with this\n * type of event. The 'receivedCallback' of a request() will get both \"nack\" and {@link #ACK \"ack\"}, thus must\n * check on the type if it makes a difference.\n * <p/>\n * Notice that a for a Client-initiated Request which is insta-rejected in the incomingHandler by invocation of\n * context.reject(..), this implies <i>acknowledge</i> of the <i>reception</i> of the message, but <i>reject</i>\n * as with regard to the </i>reply</i> (the Promise returned from request(..)).\n */\n NACK: \"nack\",\n\n /**\n * \"Synthetic\" event in that it is not a message from Server: A Client-to-Server\n * {@link MatsSocket#request() Request} was not ACKed or NACKed by the server within the\n * {@link MatsSocket#requestTimeoutMillis default request timeout} - or a specific timeout specified in the request\n * invocation. In these situations, any nack- or receivedCallback will be invoked with a {@link ReceivedEvent}\n * of this type.\n */\n TIMEOUT: \"timeout\",\n\n /**\n * \"Synthetic\" event in that it is not a message from Server: This only happens if the MatsSocketSession is\n * closed with outstanding Initiations not yet Received on Server. In these situations, any nack- or\n * receivedCallback will be invoked with a {@link ReceivedEvent} of this type.\n */\n SESSION_CLOSED: \"sessionclosed\"\n};\nObject.freeze(ReceivedEventType);\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nexport { MessageEvent, MessageEventType }\n\n/**\n * Message Event - the event emitted for a {@link MatsSocket#request() Requests}'s Promise resolve() and reject()\n * (i.e. then() and catch()), and to a {@link MatsSocket#terminator() Terminator}'s resolveCallback and\n * rejectCallback functions for replies due to {@link MatsSocket#requestReplyTo() requestReplyTo}, and for Server\n * initiated Sends (to Terminators), and for the event to a {@link MatsSocket#endpoint() Endpoint} upon a Server\n * initiated Request, and for the event sent to a {@link MatsSocket#subscribe() Subscription}.\n *\n * @param {MessageEventType} type - {@link MessageEvent#type}\n * @param {object} data - {@link MessageEvent#data}\n * @param {string} traceId - {@link MessageEvent#traceId}\n * @param {string} messageId - {@link MessageEvent#messageId}\n * @param {Timestamp} receivedTimestamp - {@link MessageEvent#receivedTimestamp}\n * @class\n */\nfunction MessageEvent(type, data, traceId, messageId, receivedTimestamp) {\n /**\n * Values are from {@link MessageEventType}: Either {@link MessageEventType#SEND \"send\"} (for a Client\n * Terminator when targeted for a Server initiated Send); {@link MessageEventType#REQUEST \"request\"} (for a\n * Client Endpoint when targeted for a Server initiated Request); or {@link MessageEventType#RESOLVE \"resolve\"}\n * or {@link MessageEventType#REJECT \"reject\"} (for settling of Promise from a Client-initiated Request, and\n * for a Client Terminator when targeted as the reply-endpoint for a Client initiated Request) - <b>or\n * {@link MessageEventType#SESSION_CLOSED \"sessionclosed\"} if the session was closed with outstanding Requests\n * and MatsSocket therefore \"clears out\" these Requests.</b>\n * <p/>\n * Notice: In the face of {@link MessageType#SESSION_CLOSED \"sessionclosed\"} or {@link MessageType#TIMEOUT \"timeout\"},\n * the {@link #data} property (i.e. the actual message from the server) will be <code>undefined</code>.\n * Wrt. \"sessionclosed\", this is <i>by definition</i>: The Request was outstanding, meaning that an answer from the\n * Server had yet to come. This is opposed to a normal REJECT settling from the Server-side MatsSocketEndpoint,\n * which may choose to include data with a rejection. The same basically goes wrt. \"timeout\", as the Server\n * has not replied yet.\n *\n * @type {MessageEventType}\n */\n this.type = type;\n\n /**\n * The actual data from the other peer.\n * <p/>\n * Notice: In the face of {@link MessageType#SESSION_CLOSED \"sessionclosed\"} or {@link MessageType#TIMEOUT \"timeout\"},\n * this value will be <code>undefined</code>.\n * Wrt. \"sessionclosed\", this is <i>by definition</i>: The Request was outstanding, meaning that an answer from the\n * Server had yet to come. This is opposed to a normal REJECT settling from the Server-side MatsSocketEndpoint,\n * which may choose to include data with a rejection. The same basically goes wrt. \"timeout\", as the Server\n * has not replied yet.\n *\n * @type {object}\n */\n this.data = data;\n\n /**\n * When a Terminator gets invoked to handle a Reply due to a Client initiated {@link MatsSocket#requestReplyTo},\n * this holds the 'correlationInformation' object that was supplied in the requestReplyTo(..) invocation.\n *\n * @type {object}\n */\n this.correlationInformation = undefined;\n\n /**\n * The TraceId for this call / message.\n *\n * @type {string}\n */\n this.traceId = traceId;\n\n /**\n * Either the ClientMessageId if this message is a Reply to a Client-initiated Request (i.e. this message is a\n * RESOLVE or REJECT), or ServerMessageId if this originated from the Server (i.e. SEND or REQUEST);\n *\n * @type {string}\n */\n this.messageId = messageId;\n\n /**\n * millis-since-epoch when the Request, for which this message is a Reply, was sent from the\n * Client. If this message is not a Reply to a Client-initiated Request, it is undefined.\n *\n * @type {Timestamp}\n */\n this.clientRequestTimestamp = undefined;\n\n /**\n * When the message was received on the Client, millis-since-epoch.\n *\n * @type {Timestamp}\n */\n this.receivedTimestamp = receivedTimestamp;\n\n /**\n * For {@link MatsSocket#request()} and {@link MatsSocket#requestReplyTo()} Requests: Round-trip time in\n * milliseconds from Request was performed to Reply was received, basically <code>{@link #receivedTimestamp} -\n * {@link #clientRequestTimestamp}</code>, but depending on the browser/runtime, you might get higher resolution\n * than integer milliseconds (i.e. fractions of milliseconds, a floating point number) - it depends on the\n * resolution of <code>performance.now()</code>.\n\n * @type {FractionalMillis}\n */\n this.roundTripMillis = undefined;\n\n /**\n * If debugging is requested, by means of {@link MatsSocket#debug} or the config object in the send, request and\n * requestReplyTo, this will contain a {@link DebugInformation} instance. However, the contents of that object\n * is decided by what you request, and what the authorized user is allowed to get as decided by the\n * AuthenticationPlugin when authenticating the user.\n */\n this.debug = undefined;\n}\n\n/**\n * Types of {@link MessageEvent}.\n *\n * @enum {string}\n * @readonly\n */\nconst MessageEventType = {\n /** Message sent from Server to Client as a resolve for a previous request. */\n RESOLVE: \"resolve\",\n\n /** Message sent from Server to Client as a reject for a previous request. */\n REJECT: \"reject\",\n\n /** Message sent from Server to a Client Terminator. */\n SEND: \"send\",\n\n /** Message sent from Server to a Client Endpoint (expecting a reply). */\n REQUEST: \"request\",\n\n /** Message sent from Server to a Client Topic. */\n PUB: \"pub\",\n\n /**\n * \"Synthetic\" event in that it is not a message from Server: A Client-to-Server\n * {@link MatsSocket#request() Request} was not replied to by the server within the\n * {@link MatsSocket#requestTimeout default request timeout} - or a specific timeout specified in the request\n * invocation. In these situations, the Request Promise is rejected with a {@link MessageEvent} of this type,\n * and the {@link MessageEvent#data} value is undefined.\n */\n TIMEOUT: \"timeout\",\n\n /**\n * \"Synthetic\" event in that it is not a message from Server: This only happens if the MatsSocketSession is\n * closed with outstanding Client-to-Server {@link MatsSocket#request() Requests} not yet replied to by the\n * server. In these situations, the Request Promise is rejected with a {@link MessageEvent} of this type, and\n * the {@link MessageEvent#data} value is undefined.\n */\n SESSION_CLOSED: \"sessionclosed\"\n};\nObject.freeze(MessageEventType);\n","export { SubscriptionEvent, SubscriptionEventType }\n\n/**\n * Information about how a subscription went on the server side. If you do two subscriptions to the same Topic,\n * you will still only get one such message - thus if you want one for each, you'd better add two listeners too,\n * <i>before</i> doing any of the subscribes.\n * <p />\n * Note: this also fires upon every reconnect. <b>Make note of the {@link SubscriptionEventType#LOST_MESSAGES}!</b>\n *\n * @param type {SubscriptionEventType} - {@link SubscriptionEvent#type}\n * @param topicId {string} - {@link SubscriptionEvent#topicId}\n * @class\n */\nfunction SubscriptionEvent(type, topicId) {\n /**\n * How the subscription fared.\n *\n * @type {SubscriptionEventType}\n */\n this.type = type;\n\n /**\n * What TopicIc this relates to.\n *\n * @type {string}\n */\n this.topicId = topicId;\n\n}\n\n/**\n * Type of {@link SubscriptionEvent}.\n *\n * @enum {string}\n * @readonly\n */\nconst SubscriptionEventType = {\n /**\n * The subscription on the server side went ok. If reconnect, any missing messages are now being sent.\n */\n OK: \"ok\",\n\n /**\n * You were not authorized to subscribe to this Topic.\n */\n NOT_AUTHORIZED: \"notauthorized\",\n\n /**\n * Upon reconnect, the \"last message Id\" was not known to the server, implying that there are lost messages.\n * Since you will now have to handle this situation by other means anyway (e.g. do a request for all stock ticks\n * between the last know timestamp and now), you will thus not get any of the lost messages even if the server\n * has some.\n */\n LOST_MESSAGES: \"lostmessages\"\n};\nObject.freeze(SubscriptionEventType);\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nimport { MessageEvent, MessageEventType } from './MessageEvent.js';\n\nexport { InitiationProcessedEvent, InitiationProcessedEventType }\n\n\n/**\n * (Metrics) Information about Client-to-Server SENDs and REQUESTs (aka <i>Client Initiations</i>), including\n * experienced round-trip times for both Received acknowledgement, and for Requests, the Request-to-Reply time.\n * <p />\n * For each message that, for sends, has been acknowledged received, and for requests, has been replied to, gives\n * this information:\n * <ul>\n * <li>Client MessageId (envelope's 'cmid').</li>\n * <li>Timestamp of when message was sent.</li>\n * <li>Target MatsSocket Endpoint or Terminator Id (envelope's 'eid').</li>\n * <li>TraceId for the SEND or REQUEST (envelope's 'tid').</li>\n * <li>The outgoing message, i.e. the SEND or the REQUEST message (envelope's 'msg').</li>\n * <li>Experienced Received Acknowledge round-trip time.</li>\n * <li>For {@link MatsSocket#request() Requests}, the Reply's {@link MessageEventType}</li>\n * <li>For {@link MatsSocket#requestReplyTo() requestReplyTo} Requests, the replyToTerminatorId.</li>\n * <li>For Requests, the total experienced Request-to-Reply time.</li>\n * <li>For Requests, the Reply {@link MessageEvent} object.</li>\n * </ul>\n * You may \"subscribe\" to <code>InitiationProcessedEvents</code> using\n * {@link MatsSocket#addInitiationProcessedEventListener()}, and you may get the latest such events from the\n * property {@link MatsSocket#initiations}.\n * <p />\n * <b>Note on event ordering</b>:\n * <ul>\n * <li>send: First {@link ReceivedEvent} is issued. Then an {@link InitiationProcessedEvent} is added to\n * {@link MatsSocket#initiations}, and then all {@link InitiationProcessedEvent} listeners are invoked</li>\n * <li>request/requestReplyTo: First {@link ReceivedEvent} is issued (i.e. ack/nack), then when the reply\n * comes back to the server, an {@link InitiationProcessedEvent} is added to {@link MatsSocket#initiations}, and\n * then all {@link InitiationProcessedEvent} listeners are invoked, and finally the {@link MessageEvent} is\n * delivered, either as settling of the return Reply-Promise (for 'request'), or invocation of the Terminator's\n * message- or rejectCallbacks (for 'requestReplyTo').\n * </ul>\n *\n * @param {string} endpointId\n * @param {string} clientMessageId\n * @param {Timestamp} sentTimestamp\n * @param {FractionalMillis} sessionEstablishedOffsetMillis\n * @param {string} traceId\n * @param {Object} initiationMessage\n * @param {FractionalMillis} acknowledgeRoundTripMillis\n * @param {MessageEventType} replyMessageEventType\n * @param {string} replyToTerminatorId\n * @param {FractionalMillis} requestRoundTripMillis\n * @param {MessageEvent} replyMessageEvent\n * @class\n */\nfunction InitiationProcessedEvent(endpointId, clientMessageId, sentTimestamp, sessionEstablishedOffsetMillis, traceId, initiationMessage, acknowledgeRoundTripMillis, replyMessageEventType, replyToTerminatorId, requestRoundTripMillis, replyMessageEvent) {\n /**\n * Which initiation type of this flow, enum of {@link InitiationProcessedEventType}.\n *\n * @type {InitiationProcessedEventType}\n */\n this.type = ((replyToTerminatorId ? InitiationProcessedEventType.REQUEST_REPLY_TO : (replyMessageEventType ? InitiationProcessedEventType.REQUEST : InitiationProcessedEventType.SEND)));\n\n /**\n * Target Server MatsSocket Endpoint or Terminator Id (envelope's 'eid').\n *\n * @type {string}\n */\n this.endpointId = endpointId;\n\n /**\n * The Client MessageId of the Initiation (envelope's 'cmid'). For this particular MatsSocket library, this\n * is currently an integer sequence id.\n *\n * @type {string}\n */\n this.clientMessageId = clientMessageId;\n\n /**\n * Millis-from-epoch when this initiation was sent.\n *\n * @type {Timestamp}\n */\n this.sentTimestamp = sentTimestamp;\n\n /**\n * The number of milliseconds offset for sending this message from the initial {@link ConnectionEventType#SESSION_ESTABLISHED} event for\n * this MatsSocket - <b>this number will typically be negative for the first messages</b>: A negative number\n * implies that the message was sent before the WELCOME was received, which again implies that the very first\n * message will by definition have a negative offset since it is this message that starts the HELLO/WELCOME\n * handshake and is thus enqueued before the WELCOME has been received. This is desirable: Upon application\n * startup, stack up all requests that you need answer for to show the initial screen, and they will all be\n * sent in a single pipeline, directly trailing the HELLO, their answers coming in as soon as possible after\n * the WELCOME.\n *\n * @type {FractionalMillis}\n */\n this.sessionEstablishedOffsetMillis = sessionEstablishedOffsetMillis;\n\n /**\n * TraceId for the initiation - which follows through all parts of the processing (envelope's 'tid').\n *\n * @type {string}\n */\n this.traceId = traceId;\n\n /**\n * The message object that was sent with the initiation, i.e. on send(), request() or requestReplyTo() (outgoing envelope's 'msg').\n *\n * @type {Object}\n */\n this.initiationMessage = initiationMessage;\n\n /**\n * The experienced round-trip time for the Received Acknowledgement - this is the time back-and-forth.\n *\n * <b>Note that this number can be a float, not necessarily integer</b>.\n *\n * @type {FractionalMillis}\n */\n this.acknowledgeRoundTripMillis = acknowledgeRoundTripMillis;\n\n // === For Requests.\n\n /**\n * The {@link MessageEventType} for Replies to Request Initiations.\n *\n * @type {string}\n */\n this.replyMessageEventType = replyMessageEventType;\n\n /**\n * The 'replyToTerminatorId' for {@link MatsSocket#requestReplyTo()}-Requests.\n *\n * @type {string}\n */\n this.replyToTerminatorId = replyToTerminatorId;\n\n /**\n * The experienced round-trip time from a Request initiation to the Reply (RESOLVE or REJECT) comes back.\n *\n * @type {FractionalMillis}\n */\n this.requestReplyRoundTripMillis = requestRoundTripMillis;\n\n /**\n * The Reply {@link MessageEvent} that was supplied to the Promise (on resolve/then or reject/catch) or ReplyTo\n * Client {@link #terminator() Terminator}.\n *\n * @type {MessageEvent}\n */\n this.replyMessageEvent = replyMessageEvent;\n}\n\n/**\n * Type of {@link InitiationProcessedEvent} - the type of the <i>initiation</i> of a flow, which also\n * determines which fields of the <code>InitiationProcessedEvent</code> are set.\n *\n * @enum {string}\n * @readonly\n */\nconst InitiationProcessedEventType = {\n /**\n * Flow initiated with {@link MatsSocket#send()}. Fields whose name does not start with \"reply\" or \"request\"\n * will be set.\n */\n SEND: \"send\",\n\n /**\n * Flow initiated with {@link MatsSocket#request()}. Will have all fields except\n * {@link InitiationProcessedEvent#replyToTerminatorId} set.\n */\n REQUEST: \"request\",\n\n /**\n * Flow initiated with {@link MatsSocket#requestReplyTo()}. Will have <i>all</i> fields set.\n */\n REQUEST_REPLY_TO: \"requestreplyto\"\n};\nObject.freeze(InitiationProcessedEventType);\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nexport { PingPong }\n\n/**\n * (Metric) A \"holding struct\" for pings and their experienced round-trip times - you may \"subscribe\" to ping results\n * using {@link MatsSocket#addPingPongListener()}, and you may get the latest pings from the property\n * {@link MatsSocket#pings}.\n *\n * @param {number} pingId\n * @param {Timestamp} sentTimestamp\n * @class\n */\nfunction PingPong(pingId, sentTimestamp) {\n /**\n * Sequence of the ping.\n *\n * @type {number}\n */\n this.pingId = pingId;\n\n /**\n * Millis-from-epoch when this ping was sent.\n *\n * @type {Timestamp}\n */\n this.sentTimestamp = sentTimestamp;\n\n /**\n * The experienced round-trip time for this ping-pong - this is the time back-and-forth.\n *\n * @type {FractionalMillis}\n */\n this.roundTripMillis = undefined;\n}\n","export { MatsSocketCloseCodes, MatsSocketCloseCodesUtil }\n\n/**\n * <b>Copied directly from MatsSocketServer.java</b>:\n * WebSocket CloseCodes used in MatsSocket, and for what. Using both standard codes, and MatsSocket-specific/defined\n * codes.\n * <p/>\n * Note: Plural \"Codes\" since that is what the JSR 356 Java WebSocket API {@link CloseCodes does..!}\n *\n * @enum {number}\n * @readonly\n */\nconst MatsSocketCloseCodes = {\n /**\n * Standard code 1008 - From Server side, Client should REJECT all outstanding and \"crash\"/reboot application:\n * used when the we cannot authenticate.\n */\n VIOLATED_POLICY: 1008,\n\n /**\n * Standard code 1011 - From Server side, Client should REJECT all outstanding and \"crash\"/reboot application.\n * This is the default close code if the MatsSocket \"onMessage\"-handler throws anything, and may also explicitly\n * be used by the implementation if it encounters a situation it cannot recover from.\n */\n UNEXPECTED_CONDITION: 1011,\n\n /**\n * Standard code 1012 - From Server side, Client should REISSUE all outstanding upon reconnect: used when\n * {@link MatsSocketServer#stop(int)} is invoked. Please reconnect.\n */\n SERVICE_RESTART: 1012,\n\n /**\n * Standard code 1001 - From Client/Browser side, client should have REJECTed all outstanding: Synonym for\n * {@link #CLOSE_SESSION}, as the WebSocket documentation states <i>\"indicates that an endpoint is \"going away\",\n * such as a server going down <b>or a browser having navigated away from a page.</b>\"</i>, the latter point\n * being pretty much exactly correct wrt. when to close a session. So, if a browser decides to use this code\n * when the user navigates away and the client MatsSocket library or employing application does not catch it,\n * we'd want to catch this as a Close Session. Notice that I've not experienced a browser that actually utilizes\n * this close code yet, though!\n * <p/>\n * <b>Notice that if a close with this close code <i>is initiated from the Server-side</i>, this should NOT be\n * considered a CLOSE_SESSION by the neither the client nor the server!</b> At least Jetty's implementation of\n * JSR 356 WebSocket API for Java sends GOING_AWAY upon socket close due to timeout. Since a timeout can happen\n * if we loose connection and thus can't convey PINGs, the MatsSocketServer must not interpret Jetty's\n * timeout-close as Close Session. Likewise, if the client just experienced massive lag on the connection, and\n * thus didn't get the PING over to the server in a timely fashion, but then suddenly gets Jetty's timeout close\n * with GOING_AWAY, this should not be interpreted by the client as the server wants to close the session.\n */\n GOING_AWAY: 1001,\n\n /**\n * 4000: Both from Server side and Client/Browser side, client should REJECT all outstanding:\n * <ul>\n * <li>From Browser: Used when the browser closes WebSocket \"on purpose\", wanting to close the session -\n * typically when the user explicitly logs out, or navigates away from web page. All traces of the\n * MatsSocketSession are effectively deleted from the server, including any undelivered replies and messages\n * (\"push\") from server.</li>\n * <li>From Server: {@link MatsSocketServer#closeSession(String)} was invoked, and the WebSocket to that client\n * was still open, so we close it.</li>\n * </ul>\n */\n CLOSE_SESSION: 4000,\n\n /**\n * 4001: From Server side, Client should REJECT all outstanding and \"crash\"/reboot application: A\n * HELLO:RECONNECT was attempted, but the session was gone. A considerable amount of time has probably gone by\n * since it last was connected. The client application must get its state synchronized with the server side's\n * view of the world, thus the suggestion of \"reboot\".\n */\n SESSION_LOST: 4001,\n\n /**\n * 4002: Both from Server side and from Client/Browser side: REISSUE all outstanding upon reconnect:\n * <ul>\n * <li>From Client: The client just fancied a little break (just as if lost connection in a tunnel), used from\n * integration tests.</li>\n * <li>From Server: We ask that the client reconnects. This gets us a clean state and in particular new\n * authentication (In case of using OAuth/OIDC tokens, the client is expected to fetch a fresh token from token\n * server).</li>\n * </ul>\n */\n RECONNECT: 4002,\n\n /**\n * 4003: From Server side: Currently used in the specific situation where a MatsSocket client connects with\n