mezon-js 2.13.60 → 2.13.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -57,6 +57,7 @@ __export(index_exports, {
57
57
  ChannelStreamMode: () => ChannelStreamMode,
58
58
  ChannelType: () => ChannelType,
59
59
  Client: () => Client,
60
+ ConnectionState: () => ConnectionState,
60
61
  DefaultSocket: () => DefaultSocket,
61
62
  NotificationType: () => NotificationType,
62
63
  Session: () => Session,
@@ -715,11 +716,15 @@ function b64DecodeUnicode(str) {
715
716
  }
716
717
  function safeJSONParse(jsonStr) {
717
718
  try {
718
- const parsedData = JSON.parse(jsonStr);
719
- return parsedData;
719
+ return JSON.parse(jsonStr);
720
720
  } catch (error) {
721
721
  if (jsonStr !== "") {
722
- console.error("Error parsing JSON:", jsonStr, error);
722
+ const fixedJsonStr = jsonStr.replace(/\n/g, "\\n");
723
+ try {
724
+ return JSON.parse(fixedJsonStr);
725
+ } catch (e) {
726
+ console.error("Error parsing JSON:", jsonStr, error);
727
+ }
723
728
  }
724
729
  return { t: jsonStr };
725
730
  }
@@ -7465,6 +7470,12 @@ function CreateChannelMessageFromEvent(message) {
7465
7470
  };
7466
7471
  return e;
7467
7472
  }
7473
+ var __hasConnectedOnce = false;
7474
+ var ConnectionState = {
7475
+ DISCONNECTED: "disconnected",
7476
+ CONNECTING: "connecting",
7477
+ CONNECTED: "connected"
7478
+ };
7468
7479
  var _DefaultSocket = class _DefaultSocket {
7469
7480
  constructor(host, port, useSSL = false, verbose = false, adapter = new WebSocketAdapterText(), sendTimeoutMs = _DefaultSocket.DefaultSendTimeoutMs) {
7470
7481
  this.host = host;
@@ -7476,7 +7487,7 @@ var _DefaultSocket = class _DefaultSocket {
7476
7487
  this.cIds = {};
7477
7488
  this.nextCid = 1;
7478
7489
  this._heartbeatTimeoutMs = _DefaultSocket.DefaultHeartbeatTimeoutMs;
7479
- this.hasConnectedBefore = false;
7490
+ this._connectionState = ConnectionState.DISCONNECTED;
7480
7491
  }
7481
7492
  generatecid() {
7482
7493
  const cid = this.nextCid.toString();
@@ -7484,12 +7495,17 @@ var _DefaultSocket = class _DefaultSocket {
7484
7495
  return cid;
7485
7496
  }
7486
7497
  isOpen() {
7487
- return this.adapter.isOpen();
7498
+ return this._connectionState === ConnectionState.CONNECTED;
7488
7499
  }
7489
7500
  connect(session, createStatus = false, platform = "", connectTimeoutMs = _DefaultSocket.DefaultConnectTimeoutMs, signal) {
7490
- if (this.adapter.isOpen()) {
7501
+ if (this._connectionState === ConnectionState.CONNECTED) {
7491
7502
  return Promise.resolve(session);
7492
7503
  }
7504
+ if (this._connectionState === ConnectionState.CONNECTING && this._connectPromise) {
7505
+ return this._connectPromise;
7506
+ }
7507
+ this.clearConnectTimeout();
7508
+ this._connectionState = ConnectionState.CONNECTING;
7493
7509
  const scheme = this.useSSL ? "wss://" : "ws://";
7494
7510
  this.adapter.connect(
7495
7511
  scheme,
@@ -7501,11 +7517,11 @@ var _DefaultSocket = class _DefaultSocket {
7501
7517
  signal
7502
7518
  );
7503
7519
  this.adapter.onClose = (evt) => {
7520
+ this._connectionState = ConnectionState.DISCONNECTED;
7521
+ this.stopHeartbeatLoop();
7522
+ this.clearConnectTimeout();
7504
7523
  this.ondisconnect(evt);
7505
7524
  };
7506
- this.adapter.onError = (evt) => {
7507
- this.onerror(evt);
7508
- };
7509
7525
  this.adapter.onMessage = (message) => __async(this, null, function* () {
7510
7526
  if (this.verbose && window && window.console) {
7511
7527
  console.log("Response: %o", JSON.stringify(message));
@@ -7710,29 +7726,46 @@ var _DefaultSocket = class _DefaultSocket {
7710
7726
  }
7711
7727
  }
7712
7728
  });
7713
- return new Promise((resolve, reject) => {
7729
+ const connectPromise = new Promise((resolve, reject) => {
7714
7730
  this.adapter.onOpen = (evt) => {
7715
7731
  if (this.verbose && window && window.console) {
7716
7732
  console.log(evt);
7717
7733
  }
7718
- const isReconnect = this.hasConnectedBefore;
7719
- this.hasConnectedBefore = true;
7720
- this.pingPong();
7734
+ const isReconnect = __hasConnectedOnce;
7735
+ __hasConnectedOnce = true;
7736
+ this.clearConnectTimeout();
7737
+ this._connectionState = ConnectionState.CONNECTED;
7738
+ this.startHeartbeatLoop();
7739
+ this._connectPromise = void 0;
7721
7740
  resolve(session);
7722
7741
  if (isReconnect) {
7723
7742
  this.onreconnect(evt);
7724
7743
  }
7725
7744
  };
7726
7745
  this.adapter.onError = (evt) => {
7727
- reject(evt);
7746
+ this._connectionState = ConnectionState.DISCONNECTED;
7747
+ this.stopHeartbeatLoop();
7748
+ this.clearConnectTimeout();
7749
+ this.onerror(evt);
7750
+ this._connectPromise = void 0;
7728
7751
  this.adapter.close();
7752
+ reject(evt);
7729
7753
  };
7730
- setTimeout(() => {
7754
+ this._connectTimeoutTimer = setTimeout(() => {
7755
+ this._connectionState = ConnectionState.DISCONNECTED;
7756
+ this.stopHeartbeatLoop();
7757
+ this.adapter.close();
7758
+ this._connectPromise = void 0;
7731
7759
  reject("The socket timed out when trying to connect.");
7760
+ this._connectTimeoutTimer = void 0;
7732
7761
  }, connectTimeoutMs);
7733
7762
  });
7763
+ this._connectPromise = connectPromise;
7764
+ return this._connectPromise;
7734
7765
  }
7735
7766
  disconnect(fireDisconnectEvent = true) {
7767
+ this._connectionState = ConnectionState.DISCONNECTED;
7768
+ this.stopHeartbeatLoop();
7736
7769
  if (this.adapter.isOpen()) {
7737
7770
  this.adapter.close();
7738
7771
  }
@@ -7757,6 +7790,8 @@ var _DefaultSocket = class _DefaultSocket {
7757
7790
  }
7758
7791
  }
7759
7792
  onerror(evt) {
7793
+ this._connectionState = ConnectionState.DISCONNECTED;
7794
+ this.stopHeartbeatLoop();
7760
7795
  if (this.verbose && window && window.console) {
7761
7796
  console.log(evt);
7762
7797
  }
@@ -8127,9 +8162,11 @@ var _DefaultSocket = class _DefaultSocket {
8127
8162
  }
8128
8163
  const cid = this.generatecid();
8129
8164
  this.cIds[cid] = { resolve, reject };
8130
- setTimeout(() => {
8131
- reject("The socket timed out while waiting for a response.");
8132
- }, sendTimeout);
8165
+ if (sendTimeout !== Infinity && sendTimeout > 0) {
8166
+ setTimeout(() => {
8167
+ reject("The socket timed out while waiting for a response.");
8168
+ }, sendTimeout);
8169
+ }
8133
8170
  untypedMessage.cid = cid;
8134
8171
  this.adapter.send(untypedMessage);
8135
8172
  }
@@ -8322,7 +8359,7 @@ var _DefaultSocket = class _DefaultSocket {
8322
8359
  code,
8323
8360
  topic_id
8324
8361
  }
8325
- });
8362
+ }, Infinity);
8326
8363
  return response.channel_message_ack;
8327
8364
  });
8328
8365
  }
@@ -8527,12 +8564,16 @@ var _DefaultSocket = class _DefaultSocket {
8527
8564
  }
8528
8565
  pingPong() {
8529
8566
  return __async(this, null, function* () {
8530
- if (!this.adapter.isOpen()) {
8567
+ if (!this.isOpen()) {
8568
+ this._connectionState = ConnectionState.DISCONNECTED;
8569
+ this.stopHeartbeatLoop();
8531
8570
  return;
8532
8571
  }
8533
8572
  try {
8534
8573
  yield this.send({ ping: {} }, this._heartbeatTimeoutMs);
8535
8574
  } catch (e) {
8575
+ this._connectionState = ConnectionState.DISCONNECTED;
8576
+ this.stopHeartbeatLoop();
8536
8577
  if (this.adapter.isOpen()) {
8537
8578
  if (window && window.console) {
8538
8579
  console.error("Server unreachable from heartbeat.");
@@ -8542,9 +8583,28 @@ var _DefaultSocket = class _DefaultSocket {
8542
8583
  }
8543
8584
  return;
8544
8585
  }
8545
- setTimeout(() => this.pingPong(), this._heartbeatTimeoutMs);
8586
+ this.startHeartbeatLoop();
8546
8587
  });
8547
8588
  }
8589
+ startHeartbeatLoop() {
8590
+ this.stopHeartbeatLoop();
8591
+ this._heartbeatTimer = setTimeout(
8592
+ () => this.pingPong(),
8593
+ this._heartbeatTimeoutMs
8594
+ );
8595
+ }
8596
+ stopHeartbeatLoop() {
8597
+ if (this._heartbeatTimer !== void 0) {
8598
+ clearTimeout(this._heartbeatTimer);
8599
+ this._heartbeatTimer = void 0;
8600
+ }
8601
+ }
8602
+ clearConnectTimeout() {
8603
+ if (this._connectTimeoutTimer !== void 0) {
8604
+ clearTimeout(this._connectTimeoutTimer);
8605
+ this._connectTimeoutTimer = void 0;
8606
+ }
8607
+ }
8548
8608
  };
8549
8609
  _DefaultSocket.DefaultHeartbeatTimeoutMs = 1e4;
8550
8610
  _DefaultSocket.DefaultSendTimeoutMs = 1e4;
@@ -681,11 +681,15 @@ function b64DecodeUnicode(str) {
681
681
  }
682
682
  function safeJSONParse(jsonStr) {
683
683
  try {
684
- const parsedData = JSON.parse(jsonStr);
685
- return parsedData;
684
+ return JSON.parse(jsonStr);
686
685
  } catch (error) {
687
686
  if (jsonStr !== "") {
688
- console.error("Error parsing JSON:", jsonStr, error);
687
+ const fixedJsonStr = jsonStr.replace(/\n/g, "\\n");
688
+ try {
689
+ return JSON.parse(fixedJsonStr);
690
+ } catch (e) {
691
+ console.error("Error parsing JSON:", jsonStr, error);
692
+ }
689
693
  }
690
694
  return { t: jsonStr };
691
695
  }
@@ -7431,6 +7435,12 @@ function CreateChannelMessageFromEvent(message) {
7431
7435
  };
7432
7436
  return e;
7433
7437
  }
7438
+ var __hasConnectedOnce = false;
7439
+ var ConnectionState = {
7440
+ DISCONNECTED: "disconnected",
7441
+ CONNECTING: "connecting",
7442
+ CONNECTED: "connected"
7443
+ };
7434
7444
  var _DefaultSocket = class _DefaultSocket {
7435
7445
  constructor(host, port, useSSL = false, verbose = false, adapter = new WebSocketAdapterText(), sendTimeoutMs = _DefaultSocket.DefaultSendTimeoutMs) {
7436
7446
  this.host = host;
@@ -7442,7 +7452,7 @@ var _DefaultSocket = class _DefaultSocket {
7442
7452
  this.cIds = {};
7443
7453
  this.nextCid = 1;
7444
7454
  this._heartbeatTimeoutMs = _DefaultSocket.DefaultHeartbeatTimeoutMs;
7445
- this.hasConnectedBefore = false;
7455
+ this._connectionState = ConnectionState.DISCONNECTED;
7446
7456
  }
7447
7457
  generatecid() {
7448
7458
  const cid = this.nextCid.toString();
@@ -7450,12 +7460,17 @@ var _DefaultSocket = class _DefaultSocket {
7450
7460
  return cid;
7451
7461
  }
7452
7462
  isOpen() {
7453
- return this.adapter.isOpen();
7463
+ return this._connectionState === ConnectionState.CONNECTED;
7454
7464
  }
7455
7465
  connect(session, createStatus = false, platform = "", connectTimeoutMs = _DefaultSocket.DefaultConnectTimeoutMs, signal) {
7456
- if (this.adapter.isOpen()) {
7466
+ if (this._connectionState === ConnectionState.CONNECTED) {
7457
7467
  return Promise.resolve(session);
7458
7468
  }
7469
+ if (this._connectionState === ConnectionState.CONNECTING && this._connectPromise) {
7470
+ return this._connectPromise;
7471
+ }
7472
+ this.clearConnectTimeout();
7473
+ this._connectionState = ConnectionState.CONNECTING;
7459
7474
  const scheme = this.useSSL ? "wss://" : "ws://";
7460
7475
  this.adapter.connect(
7461
7476
  scheme,
@@ -7467,11 +7482,11 @@ var _DefaultSocket = class _DefaultSocket {
7467
7482
  signal
7468
7483
  );
7469
7484
  this.adapter.onClose = (evt) => {
7485
+ this._connectionState = ConnectionState.DISCONNECTED;
7486
+ this.stopHeartbeatLoop();
7487
+ this.clearConnectTimeout();
7470
7488
  this.ondisconnect(evt);
7471
7489
  };
7472
- this.adapter.onError = (evt) => {
7473
- this.onerror(evt);
7474
- };
7475
7490
  this.adapter.onMessage = (message) => __async(this, null, function* () {
7476
7491
  if (this.verbose && window && window.console) {
7477
7492
  console.log("Response: %o", JSON.stringify(message));
@@ -7676,29 +7691,46 @@ var _DefaultSocket = class _DefaultSocket {
7676
7691
  }
7677
7692
  }
7678
7693
  });
7679
- return new Promise((resolve, reject) => {
7694
+ const connectPromise = new Promise((resolve, reject) => {
7680
7695
  this.adapter.onOpen = (evt) => {
7681
7696
  if (this.verbose && window && window.console) {
7682
7697
  console.log(evt);
7683
7698
  }
7684
- const isReconnect = this.hasConnectedBefore;
7685
- this.hasConnectedBefore = true;
7686
- this.pingPong();
7699
+ const isReconnect = __hasConnectedOnce;
7700
+ __hasConnectedOnce = true;
7701
+ this.clearConnectTimeout();
7702
+ this._connectionState = ConnectionState.CONNECTED;
7703
+ this.startHeartbeatLoop();
7704
+ this._connectPromise = void 0;
7687
7705
  resolve(session);
7688
7706
  if (isReconnect) {
7689
7707
  this.onreconnect(evt);
7690
7708
  }
7691
7709
  };
7692
7710
  this.adapter.onError = (evt) => {
7693
- reject(evt);
7711
+ this._connectionState = ConnectionState.DISCONNECTED;
7712
+ this.stopHeartbeatLoop();
7713
+ this.clearConnectTimeout();
7714
+ this.onerror(evt);
7715
+ this._connectPromise = void 0;
7694
7716
  this.adapter.close();
7717
+ reject(evt);
7695
7718
  };
7696
- setTimeout(() => {
7719
+ this._connectTimeoutTimer = setTimeout(() => {
7720
+ this._connectionState = ConnectionState.DISCONNECTED;
7721
+ this.stopHeartbeatLoop();
7722
+ this.adapter.close();
7723
+ this._connectPromise = void 0;
7697
7724
  reject("The socket timed out when trying to connect.");
7725
+ this._connectTimeoutTimer = void 0;
7698
7726
  }, connectTimeoutMs);
7699
7727
  });
7728
+ this._connectPromise = connectPromise;
7729
+ return this._connectPromise;
7700
7730
  }
7701
7731
  disconnect(fireDisconnectEvent = true) {
7732
+ this._connectionState = ConnectionState.DISCONNECTED;
7733
+ this.stopHeartbeatLoop();
7702
7734
  if (this.adapter.isOpen()) {
7703
7735
  this.adapter.close();
7704
7736
  }
@@ -7723,6 +7755,8 @@ var _DefaultSocket = class _DefaultSocket {
7723
7755
  }
7724
7756
  }
7725
7757
  onerror(evt) {
7758
+ this._connectionState = ConnectionState.DISCONNECTED;
7759
+ this.stopHeartbeatLoop();
7726
7760
  if (this.verbose && window && window.console) {
7727
7761
  console.log(evt);
7728
7762
  }
@@ -8093,9 +8127,11 @@ var _DefaultSocket = class _DefaultSocket {
8093
8127
  }
8094
8128
  const cid = this.generatecid();
8095
8129
  this.cIds[cid] = { resolve, reject };
8096
- setTimeout(() => {
8097
- reject("The socket timed out while waiting for a response.");
8098
- }, sendTimeout);
8130
+ if (sendTimeout !== Infinity && sendTimeout > 0) {
8131
+ setTimeout(() => {
8132
+ reject("The socket timed out while waiting for a response.");
8133
+ }, sendTimeout);
8134
+ }
8099
8135
  untypedMessage.cid = cid;
8100
8136
  this.adapter.send(untypedMessage);
8101
8137
  }
@@ -8288,7 +8324,7 @@ var _DefaultSocket = class _DefaultSocket {
8288
8324
  code,
8289
8325
  topic_id
8290
8326
  }
8291
- });
8327
+ }, Infinity);
8292
8328
  return response.channel_message_ack;
8293
8329
  });
8294
8330
  }
@@ -8493,12 +8529,16 @@ var _DefaultSocket = class _DefaultSocket {
8493
8529
  }
8494
8530
  pingPong() {
8495
8531
  return __async(this, null, function* () {
8496
- if (!this.adapter.isOpen()) {
8532
+ if (!this.isOpen()) {
8533
+ this._connectionState = ConnectionState.DISCONNECTED;
8534
+ this.stopHeartbeatLoop();
8497
8535
  return;
8498
8536
  }
8499
8537
  try {
8500
8538
  yield this.send({ ping: {} }, this._heartbeatTimeoutMs);
8501
8539
  } catch (e) {
8540
+ this._connectionState = ConnectionState.DISCONNECTED;
8541
+ this.stopHeartbeatLoop();
8502
8542
  if (this.adapter.isOpen()) {
8503
8543
  if (window && window.console) {
8504
8544
  console.error("Server unreachable from heartbeat.");
@@ -8508,9 +8548,28 @@ var _DefaultSocket = class _DefaultSocket {
8508
8548
  }
8509
8549
  return;
8510
8550
  }
8511
- setTimeout(() => this.pingPong(), this._heartbeatTimeoutMs);
8551
+ this.startHeartbeatLoop();
8512
8552
  });
8513
8553
  }
8554
+ startHeartbeatLoop() {
8555
+ this.stopHeartbeatLoop();
8556
+ this._heartbeatTimer = setTimeout(
8557
+ () => this.pingPong(),
8558
+ this._heartbeatTimeoutMs
8559
+ );
8560
+ }
8561
+ stopHeartbeatLoop() {
8562
+ if (this._heartbeatTimer !== void 0) {
8563
+ clearTimeout(this._heartbeatTimer);
8564
+ this._heartbeatTimer = void 0;
8565
+ }
8566
+ }
8567
+ clearConnectTimeout() {
8568
+ if (this._connectTimeoutTimer !== void 0) {
8569
+ clearTimeout(this._connectTimeoutTimer);
8570
+ this._connectTimeoutTimer = void 0;
8571
+ }
8572
+ }
8514
8573
  };
8515
8574
  _DefaultSocket.DefaultHeartbeatTimeoutMs = 1e4;
8516
8575
  _DefaultSocket.DefaultSendTimeoutMs = 1e4;
@@ -11228,6 +11287,7 @@ export {
11228
11287
  ChannelStreamMode,
11229
11288
  ChannelType,
11230
11289
  Client,
11290
+ ConnectionState,
11231
11291
  DefaultSocket,
11232
11292
  NotificationType,
11233
11293
  Session,
package/dist/socket.d.ts CHANGED
@@ -1073,7 +1073,12 @@ export interface SocketError {
1073
1073
  /** A message in English to help developers debug the response. */
1074
1074
  message: string;
1075
1075
  }
1076
- /** A socket connection to Mezon server implemented with the DOM's WebSocket API. */
1076
+ export declare const ConnectionState: {
1077
+ readonly DISCONNECTED: "disconnected";
1078
+ readonly CONNECTING: "connecting";
1079
+ readonly CONNECTED: "connected";
1080
+ };
1081
+ export type ConnectionStateType = typeof ConnectionState[keyof typeof ConnectionState];
1077
1082
  export declare class DefaultSocket implements Socket {
1078
1083
  readonly host: string;
1079
1084
  readonly port: string;
@@ -1087,7 +1092,10 @@ export declare class DefaultSocket implements Socket {
1087
1092
  private readonly cIds;
1088
1093
  private nextCid;
1089
1094
  private _heartbeatTimeoutMs;
1090
- private hasConnectedBefore;
1095
+ private _connectionState;
1096
+ private _heartbeatTimer?;
1097
+ private _connectTimeoutTimer?;
1098
+ private _connectPromise?;
1091
1099
  constructor(host: string, port: string, useSSL?: boolean, verbose?: boolean, adapter?: WebSocketAdapter, sendTimeoutMs?: number);
1092
1100
  generatecid(): string;
1093
1101
  isOpen(): boolean;
@@ -1196,5 +1204,8 @@ export declare class DefaultSocket implements Socket {
1196
1204
  writeChannelAppEvent(clan_id: string, channel_id: string, action: number): Promise<ChannelAppEvent>;
1197
1205
  listDataSocket(request: ListDataSocket): Promise<any>;
1198
1206
  private pingPong;
1207
+ private startHeartbeatLoop;
1208
+ private stopHeartbeatLoop;
1209
+ private clearConnectTimeout;
1199
1210
  }
1200
1211
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mezon-js",
3
- "version": "2.13.60",
3
+ "version": "2.13.62",
4
4
  "scripts": {
5
5
  "build": "npx tsc && npx rollup -c --bundleConfigAsCjs && node build.mjs"
6
6
  },
package/socket.ts CHANGED
@@ -1859,6 +1859,16 @@ export interface SocketError {
1859
1859
  }
1860
1860
 
1861
1861
  /** A socket connection to Mezon server implemented with the DOM's WebSocket API. */
1862
+ let __hasConnectedOnce = false;
1863
+
1864
+ export const ConnectionState = {
1865
+ DISCONNECTED: "disconnected",
1866
+ CONNECTING: "connecting",
1867
+ CONNECTED: "connected",
1868
+ } as const;
1869
+
1870
+ export type ConnectionStateType = typeof ConnectionState[keyof typeof ConnectionState];
1871
+
1862
1872
  export class DefaultSocket implements Socket {
1863
1873
  public static readonly DefaultHeartbeatTimeoutMs = 10000;
1864
1874
  public static readonly DefaultSendTimeoutMs = 10000;
@@ -1867,7 +1877,10 @@ export class DefaultSocket implements Socket {
1867
1877
  private readonly cIds: { [key: string]: PromiseExecutor };
1868
1878
  private nextCid: number;
1869
1879
  private _heartbeatTimeoutMs: number;
1870
- private hasConnectedBefore: boolean;
1880
+ private _connectionState: ConnectionStateType;
1881
+ private _heartbeatTimer?: ReturnType<typeof setTimeout>;
1882
+ private _connectTimeoutTimer?: ReturnType<typeof setTimeout>;
1883
+ private _connectPromise?: Promise<Session>;
1871
1884
 
1872
1885
  constructor(
1873
1886
  readonly host: string,
@@ -1880,7 +1893,7 @@ export class DefaultSocket implements Socket {
1880
1893
  this.cIds = {};
1881
1894
  this.nextCid = 1;
1882
1895
  this._heartbeatTimeoutMs = DefaultSocket.DefaultHeartbeatTimeoutMs;
1883
- this.hasConnectedBefore = false;
1896
+ this._connectionState = ConnectionState.DISCONNECTED;
1884
1897
  }
1885
1898
 
1886
1899
  generatecid(): string {
@@ -1890,7 +1903,7 @@ export class DefaultSocket implements Socket {
1890
1903
  }
1891
1904
 
1892
1905
  isOpen(): boolean {
1893
- return this.adapter.isOpen();
1906
+ return this._connectionState === ConnectionState.CONNECTED;
1894
1907
  }
1895
1908
 
1896
1909
  connect(
@@ -1900,10 +1913,17 @@ export class DefaultSocket implements Socket {
1900
1913
  connectTimeoutMs: number = DefaultSocket.DefaultConnectTimeoutMs,
1901
1914
  signal?: AbortSignal
1902
1915
  ): Promise<Session> {
1903
- if (this.adapter.isOpen()) {
1916
+ if (this._connectionState === ConnectionState.CONNECTED) {
1904
1917
  return Promise.resolve(session);
1905
1918
  }
1906
1919
 
1920
+ if (this._connectionState === ConnectionState.CONNECTING && this._connectPromise) {
1921
+ return this._connectPromise;
1922
+ }
1923
+
1924
+ this.clearConnectTimeout();
1925
+ this._connectionState = ConnectionState.CONNECTING;
1926
+
1907
1927
  const scheme = this.useSSL ? "wss://" : "ws://";
1908
1928
  this.adapter.connect(
1909
1929
  scheme,
@@ -1916,13 +1936,12 @@ export class DefaultSocket implements Socket {
1916
1936
  );
1917
1937
 
1918
1938
  this.adapter.onClose = (evt: Event) => {
1939
+ this._connectionState = ConnectionState.DISCONNECTED;
1940
+ this.stopHeartbeatLoop();
1941
+ this.clearConnectTimeout();
1919
1942
  this.ondisconnect(evt);
1920
1943
  };
1921
1944
 
1922
- this.adapter.onError = (evt: Event) => {
1923
- this.onerror(evt);
1924
- };
1925
-
1926
1945
  this.adapter.onMessage = async (message: any) => {
1927
1946
  if (this.verbose && window && window.console) {
1928
1947
  console.log("Response: %o", JSON.stringify(message));
@@ -2130,16 +2149,20 @@ export class DefaultSocket implements Socket {
2130
2149
  }
2131
2150
  };
2132
2151
 
2133
- return new Promise((resolve, reject) => {
2152
+ const connectPromise = new Promise<Session>((resolve, reject) => {
2134
2153
  this.adapter.onOpen = (evt: Event) => {
2135
2154
  if (this.verbose && window && window.console) {
2136
2155
  console.log(evt);
2137
2156
  }
2138
2157
 
2139
- const isReconnect = this.hasConnectedBefore;
2140
- this.hasConnectedBefore = true;
2158
+ const isReconnect = __hasConnectedOnce;
2159
+ __hasConnectedOnce = true;
2141
2160
 
2142
- this.pingPong();
2161
+ this.clearConnectTimeout();
2162
+ this._connectionState = ConnectionState.CONNECTED;
2163
+ this.startHeartbeatLoop();
2164
+ this._connectPromise = undefined;
2165
+
2143
2166
  resolve(session);
2144
2167
 
2145
2168
  if (isReconnect) {
@@ -2147,18 +2170,33 @@ export class DefaultSocket implements Socket {
2147
2170
  }
2148
2171
  };
2149
2172
  this.adapter.onError = (evt: Event) => {
2150
- reject(evt);
2173
+ this._connectionState = ConnectionState.DISCONNECTED;
2174
+ this.stopHeartbeatLoop();
2175
+ this.clearConnectTimeout();
2176
+ this.onerror(evt);
2177
+ this._connectPromise = undefined;
2151
2178
  this.adapter.close();
2179
+ reject(evt);
2152
2180
  };
2153
2181
 
2154
- setTimeout(() => {
2182
+ this._connectTimeoutTimer = setTimeout(() => {
2155
2183
  // if promise has resolved by now, the reject() is a no-op
2184
+ this._connectionState = ConnectionState.DISCONNECTED;
2185
+ this.stopHeartbeatLoop();
2186
+ this.adapter.close();
2187
+ this._connectPromise = undefined;
2156
2188
  reject("The socket timed out when trying to connect.");
2189
+ this._connectTimeoutTimer = undefined;
2157
2190
  }, connectTimeoutMs);
2158
2191
  });
2192
+
2193
+ this._connectPromise = connectPromise;
2194
+ return this._connectPromise;
2159
2195
  }
2160
2196
 
2161
2197
  disconnect(fireDisconnectEvent: boolean = true) {
2198
+ this._connectionState = ConnectionState.DISCONNECTED;
2199
+ this.stopHeartbeatLoop();
2162
2200
  if (this.adapter.isOpen()) {
2163
2201
  this.adapter.close();
2164
2202
  }
@@ -2188,6 +2226,8 @@ export class DefaultSocket implements Socket {
2188
2226
  }
2189
2227
 
2190
2228
  onerror(evt: Event) {
2229
+ this._connectionState = ConnectionState.DISCONNECTED;
2230
+ this.stopHeartbeatLoop();
2191
2231
  if (this.verbose && window && window.console) {
2192
2232
  console.log(evt);
2193
2233
  }
@@ -2653,11 +2693,12 @@ export class DefaultSocket implements Socket {
2653
2693
 
2654
2694
  const cid = this.generatecid();
2655
2695
  this.cIds[cid] = { resolve, reject };
2656
- setTimeout(() => {
2657
- reject("The socket timed out while waiting for a response.");
2658
- }, sendTimeout);
2696
+ if (sendTimeout !== Infinity && sendTimeout > 0) {
2697
+ setTimeout(() => {
2698
+ reject("The socket timed out while waiting for a response.");
2699
+ }, sendTimeout);
2700
+ }
2659
2701
 
2660
- /** Add id for promise executor. */
2661
2702
  untypedMessage.cid = cid;
2662
2703
  this.adapter.send(untypedMessage);
2663
2704
  }
@@ -2933,7 +2974,7 @@ export class DefaultSocket implements Socket {
2933
2974
  code: code,
2934
2975
  topic_id: topic_id,
2935
2976
  },
2936
- });
2977
+ }, Infinity);
2937
2978
  return response.channel_message_ack;
2938
2979
  }
2939
2980
 
@@ -3212,13 +3253,17 @@ export class DefaultSocket implements Socket {
3212
3253
  }
3213
3254
 
3214
3255
  private async pingPong(): Promise<void> {
3215
- if (!this.adapter.isOpen()) {
3256
+ if (!this.isOpen()) {
3257
+ this._connectionState = ConnectionState.DISCONNECTED;
3258
+ this.stopHeartbeatLoop();
3216
3259
  return;
3217
3260
  }
3218
3261
 
3219
3262
  try {
3220
3263
  await this.send({ ping: {} }, this._heartbeatTimeoutMs);
3221
3264
  } catch {
3265
+ this._connectionState = ConnectionState.DISCONNECTED;
3266
+ this.stopHeartbeatLoop();
3222
3267
  if (this.adapter.isOpen()) {
3223
3268
  if (window && window.console) {
3224
3269
  console.error("Server unreachable from heartbeat.");
@@ -3230,9 +3275,29 @@ export class DefaultSocket implements Socket {
3230
3275
  return;
3231
3276
  }
3232
3277
 
3233
- // reuse the timeout as the interval for now.
3234
- // we can separate them out into separate values if needed later.
3235
- setTimeout(() => this.pingPong(), this._heartbeatTimeoutMs);
3278
+ this.startHeartbeatLoop();
3279
+ }
3280
+
3281
+ private startHeartbeatLoop() {
3282
+ this.stopHeartbeatLoop();
3283
+ this._heartbeatTimer = setTimeout(
3284
+ () => this.pingPong(),
3285
+ this._heartbeatTimeoutMs
3286
+ );
3287
+ }
3288
+
3289
+ private stopHeartbeatLoop() {
3290
+ if (this._heartbeatTimer !== undefined) {
3291
+ clearTimeout(this._heartbeatTimer);
3292
+ this._heartbeatTimer = undefined;
3293
+ }
3294
+ }
3295
+
3296
+ private clearConnectTimeout() {
3297
+ if (this._connectTimeoutTimer !== undefined) {
3298
+ clearTimeout(this._connectTimeoutTimer);
3299
+ this._connectTimeoutTimer = undefined;
3300
+ }
3236
3301
  }
3237
3302
  }
3238
3303
 
package/utils.ts CHANGED
@@ -50,11 +50,15 @@ export function b64DecodeUnicode(str: string) {
50
50
 
51
51
  export function safeJSONParse(jsonStr: string) {
52
52
  try {
53
- const parsedData = JSON.parse(jsonStr);
54
- return parsedData;
53
+ return JSON.parse(jsonStr);
55
54
  } catch (error) {
56
55
  if (jsonStr !== "") {
57
- console.error('Error parsing JSON:', jsonStr, error);
56
+ const fixedJsonStr = jsonStr.replace(/\n/g, "\\n");
57
+ try {
58
+ return JSON.parse(fixedJsonStr);
59
+ } catch (e) {
60
+ console.error('Error parsing JSON:', jsonStr, error);
61
+ }
58
62
  }
59
63
  return {t: jsonStr}; // Handle the error gracefully or throw an exception if necessary
60
64
  }