mezon-js 2.13.61 → 2.13.63

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.
package/api.gen.ts CHANGED
@@ -206,6 +206,8 @@ export interface MezonUpdateClanDescBody {
206
206
  about?: string;
207
207
  // short url for community
208
208
  short_url?: string;
209
+ // prevent anonymous
210
+ prevent_anonymous?: boolean;
209
211
  }
210
212
 
211
213
  /** */
@@ -2441,14 +2443,6 @@ export interface ApiSearchMessageResponse {
2441
2443
  total?: number;
2442
2444
  }
2443
2445
 
2444
- /** */
2445
- export interface ApiConfigAllowAnonymousRequest {
2446
- //
2447
- allow?: boolean;
2448
- //
2449
- clan_id?: string;
2450
- }
2451
-
2452
2446
  /** A user's session used to authenticate messages. */
2453
2447
  export interface ApiSession {
2454
2448
  //True if the corresponding account was just created, false otherwise.
@@ -11763,41 +11757,5 @@ export class MezonApi {
11763
11757
  ]);
11764
11758
  }
11765
11759
 
11766
- /** */
11767
- configAllowAnonymous(bearerToken: string,
11768
- body:ApiConfigAllowAnonymousRequest,
11769
- options: any = {}): Promise<any> {
11770
-
11771
- if (body === null || body === undefined) {
11772
- throw new Error("'body' is a required parameter but is null or undefined.");
11773
- }
11774
- const urlPath = "/v2/anonymous/config";
11775
- const queryParams = new Map<string, any>();
11776
-
11777
- let bodyJson : string = "";
11778
- bodyJson = JSON.stringify(body || {});
11779
-
11780
- const fullUrl = this.buildFullUrl(this.basePath, urlPath, queryParams);
11781
- const fetchOptions = buildFetchOptions("POST", options, bodyJson);
11782
- if (bearerToken) {
11783
- fetchOptions.headers["Authorization"] = "Bearer " + bearerToken;
11784
- }
11785
-
11786
- return Promise.race([
11787
- fetch(fullUrl, fetchOptions).then((response) => {
11788
- if (response.status == 204) {
11789
- return response;
11790
- } else if (response.status >= 200 && response.status < 300) {
11791
- return response.json();
11792
- } else {
11793
- throw response;
11794
- }
11795
- }),
11796
- new Promise((_, reject) =>
11797
- setTimeout(reject, this.timeoutMs, "Request timed out.")
11798
- ),
11799
- ]);
11800
- }
11801
-
11802
11760
  }
11803
11761
 
package/client.ts CHANGED
@@ -180,7 +180,6 @@ import {
180
180
  ApiUpdateUsernameRequest,
181
181
  ApiBannedUserList,
182
182
  ApiIsBannedResponse,
183
- ApiConfigAllowAnonymousRequest,
184
183
  } from "./api.gen";
185
184
 
186
185
  import { Session } from "./session";
@@ -4988,23 +4987,4 @@ export class Client {
4988
4987
  return Promise.resolve(response);
4989
4988
  });
4990
4989
  }
4991
-
4992
- async configAllowAnonymous(
4993
- session: Session,
4994
- req: ApiConfigAllowAnonymousRequest,
4995
- ): Promise<any> {
4996
- if (
4997
- this.autoRefreshSession &&
4998
- session.refresh_token &&
4999
- session.isexpired(Date.now() / 1000)
5000
- ) {
5001
- await this.sessionRefresh(session);
5002
- }
5003
-
5004
- return this.apiClient
5005
- .configAllowAnonymous(session.token, req)
5006
- .then((response: any) => {
5007
- return response !== undefined;
5008
- });
5009
- }
5010
4990
  }
package/dist/api.gen.d.ts CHANGED
@@ -118,6 +118,7 @@ export interface MezonUpdateClanDescBody {
118
118
  description?: string;
119
119
  about?: string;
120
120
  short_url?: string;
121
+ prevent_anonymous?: boolean;
121
122
  }
122
123
  /** */
123
124
  export interface MezonUpdateClanDescProfileBody {
@@ -1393,11 +1394,6 @@ export interface ApiSearchMessageResponse {
1393
1394
  messages?: Array<ApiSearchMessageDocument>;
1394
1395
  total?: number;
1395
1396
  }
1396
- /** */
1397
- export interface ApiConfigAllowAnonymousRequest {
1398
- allow?: boolean;
1399
- clan_id?: string;
1400
- }
1401
1397
  /** A user's session used to authenticate messages. */
1402
1398
  export interface ApiSession {
1403
1399
  created?: boolean;
@@ -2409,6 +2405,4 @@ export declare class MezonApi {
2409
2405
  updateUsername(bearerToken: string, body: ApiUpdateUsernameRequest, options?: any): Promise<ApiSession>;
2410
2406
  /** Ban a set of users from a channel. */
2411
2407
  isBanned(bearerToken: string, channelId: string, options?: any): Promise<ApiIsBannedResponse>;
2412
- /** */
2413
- configAllowAnonymous(bearerToken: string, body: ApiConfigAllowAnonymousRequest, options?: any): Promise<any>;
2414
2408
  }
package/dist/client.d.ts CHANGED
@@ -13,7 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { ApiAccount, ApiAccountMezon, ApiAccountEmail, ApiChannelDescList, ApiChannelDescription, ApiCreateChannelDescRequest, ApiDeleteRoleRequest, ApiClanDescList, ApiCreateClanDescRequest, ApiClanDesc, ApiCategoryDesc, ApiCategoryDescList, ApiPermissionList, ApiRoleUserList, ApiRole, ApiCreateRoleRequest, ApiAddRoleChannelDescRequest, ApiCreateCategoryDescRequest, ApiUpdateCategoryDescRequest, ApiEvent, ApiNotificationList, ApiUpdateAccountRequest, ApiSession, ApiClanProfile, ApiChannelUserList, ApiClanUserList, ApiLinkInviteUserRequest, ApiLinkInviteUser, ApiInviteUserRes, ApiUploadAttachmentRequest, ApiUploadAttachment, ApiMessageReaction, ApiMessageMention, ApiMessageAttachment, ApiMessageRef, ApiChannelMessageHeader, ApiVoiceChannelUserList, ApiChannelAttachmentList, ApiCreateEventRequest, ApiEventManagement, ApiEventList, ApiDeleteEventRequest, ApiSetDefaultNotificationRequest, ApiSetNotificationRequest, ApiSetMuteRequest, ApiSearchMessageRequest, ApiSearchMessageResponse, ApiPinMessageRequest, ApiPinMessagesList, ApiDeleteChannelDescRequest, ApiChangeChannelPrivateRequest, ApiClanEmojiCreateRequest, MezonUpdateClanEmojiByIdBody, ApiWebhookCreateRequest, ApiWebhookListResponse, MezonUpdateWebhookByIdBody, ApiWebhookGenerateResponse, ApiCheckDuplicateClanNameResponse, ApiClanStickerAddRequest, MezonUpdateClanStickerByIdBody, MezonChangeChannelCategoryBody, ApiUpdateRoleChannelRequest, ApiAddAppRequest, ApiAppList, ApiApp, MezonUpdateAppBody, ApiSystemMessagesList, ApiSystemMessage, ApiSystemMessageRequest, MezonUpdateSystemMessageBody, ApiUpdateCategoryOrderRequest, ApiGiveCoffeeEvent, ApiListStreamingChannelsResponse, ApiStreamingChannelUserList, ApiRegisterStreamingChannelRequest, ApiRoleList, ApiListChannelAppsResponse, ApiNotificationChannelCategorySettingList, ApiNotificationUserChannel, ApiNotificationSetting, ApiNotifiReactMessage, ApiHashtagDmList, ApiEmojiListedResponse, ApiStickerListedResponse, ApiAllUsersAddChannelResponse, ApiRoleListEventResponse, ApiAllUserClans, ApiUserPermissionInChannelListResponse, ApiPermissionRoleChannelListEventResponse, ApiMarkAsReadRequest, ApiChannelCanvasListResponse, ApiEditChannelCanvasRequest, ApiChannelSettingListResponse, ApiAddFavoriteChannelResponse, ApiRegistFcmDeviceTokenResponse, ApiListUserActivity, ApiCreateActivityRequest, ApiLoginIDResponse, ApiLoginRequest, ApiConfirmLoginRequest, ApiUserActivity, ApiChanEncryptionMethod, ApiGetPubKeysResponse, ApiPubKey, ApiGetKeyServerResp, MezonapiListAuditLog, ApiTokenSentEvent, MezonDeleteWebhookByIdBody, ApiListOnboardingResponse, ApiCreateOnboardingRequest, MezonUpdateOnboardingBody, ApiOnboardingItem, ApiGenerateClanWebhookRequest, ApiGenerateClanWebhookResponse, ApiListClanWebhookResponse, MezonUpdateClanWebhookByIdBody, MezonUpdateClanDescBody, ApiUserStatusUpdate, ApiUserStatus, ApiListOnboardingStepResponse, MezonUpdateOnboardingStepByClanIdBody, ApiWalletLedgerList, ApiSdTopicList, ApiSdTopicRequest, ApiSdTopic, MezonUpdateEventBody, ApiTransactionDetail, MezonapiCreateRoomChannelApps, ApiGenerateMeetTokenRequest, ApiGenerateMeetTokenResponse, ApiMezonOauthClientList, ApiMezonOauthClient, ApiCreateHashChannelAppsResponse, ApiEmojiRecentList, ApiUserEventRequest, ApiUpdateRoleOrderRequest, ApiGenerateMezonMeetResponse, ApiGenerateMeetTokenExternalResponse, ApiUpdateClanOrderRequest, ApiMessage2InboxRequest, ApiListClanDiscover, ApiClanDiscoverRequest, ApiQuickMenuAccessList, ApiQuickMenuAccessRequest, ApiUnlockedItemRequest, ApiForSaleItemList, ApiUnlockedItemResponse, ApiIsFollowerResponse, ApiIsFollowerRequest, ApiTransferOwnershipRequest, ApiMeetParticipantRequest, ApiLinkAccountConfirmRequest, ApiLinkAccountMezon, ApiUser, ApiFriend, ApiListClanUnreadMsgIndicatorResponse, ApiAddFriendsResponse, ApiUpdateUsernameRequest, ApiBannedUserList, ApiIsBannedResponse, ApiConfigAllowAnonymousRequest } from "./api.gen";
16
+ import { ApiAccount, ApiAccountMezon, ApiAccountEmail, ApiChannelDescList, ApiChannelDescription, ApiCreateChannelDescRequest, ApiDeleteRoleRequest, ApiClanDescList, ApiCreateClanDescRequest, ApiClanDesc, ApiCategoryDesc, ApiCategoryDescList, ApiPermissionList, ApiRoleUserList, ApiRole, ApiCreateRoleRequest, ApiAddRoleChannelDescRequest, ApiCreateCategoryDescRequest, ApiUpdateCategoryDescRequest, ApiEvent, ApiNotificationList, ApiUpdateAccountRequest, ApiSession, ApiClanProfile, ApiChannelUserList, ApiClanUserList, ApiLinkInviteUserRequest, ApiLinkInviteUser, ApiInviteUserRes, ApiUploadAttachmentRequest, ApiUploadAttachment, ApiMessageReaction, ApiMessageMention, ApiMessageAttachment, ApiMessageRef, ApiChannelMessageHeader, ApiVoiceChannelUserList, ApiChannelAttachmentList, ApiCreateEventRequest, ApiEventManagement, ApiEventList, ApiDeleteEventRequest, ApiSetDefaultNotificationRequest, ApiSetNotificationRequest, ApiSetMuteRequest, ApiSearchMessageRequest, ApiSearchMessageResponse, ApiPinMessageRequest, ApiPinMessagesList, ApiDeleteChannelDescRequest, ApiChangeChannelPrivateRequest, ApiClanEmojiCreateRequest, MezonUpdateClanEmojiByIdBody, ApiWebhookCreateRequest, ApiWebhookListResponse, MezonUpdateWebhookByIdBody, ApiWebhookGenerateResponse, ApiCheckDuplicateClanNameResponse, ApiClanStickerAddRequest, MezonUpdateClanStickerByIdBody, MezonChangeChannelCategoryBody, ApiUpdateRoleChannelRequest, ApiAddAppRequest, ApiAppList, ApiApp, MezonUpdateAppBody, ApiSystemMessagesList, ApiSystemMessage, ApiSystemMessageRequest, MezonUpdateSystemMessageBody, ApiUpdateCategoryOrderRequest, ApiGiveCoffeeEvent, ApiListStreamingChannelsResponse, ApiStreamingChannelUserList, ApiRegisterStreamingChannelRequest, ApiRoleList, ApiListChannelAppsResponse, ApiNotificationChannelCategorySettingList, ApiNotificationUserChannel, ApiNotificationSetting, ApiNotifiReactMessage, ApiHashtagDmList, ApiEmojiListedResponse, ApiStickerListedResponse, ApiAllUsersAddChannelResponse, ApiRoleListEventResponse, ApiAllUserClans, ApiUserPermissionInChannelListResponse, ApiPermissionRoleChannelListEventResponse, ApiMarkAsReadRequest, ApiChannelCanvasListResponse, ApiEditChannelCanvasRequest, ApiChannelSettingListResponse, ApiAddFavoriteChannelResponse, ApiRegistFcmDeviceTokenResponse, ApiListUserActivity, ApiCreateActivityRequest, ApiLoginIDResponse, ApiLoginRequest, ApiConfirmLoginRequest, ApiUserActivity, ApiChanEncryptionMethod, ApiGetPubKeysResponse, ApiPubKey, ApiGetKeyServerResp, MezonapiListAuditLog, ApiTokenSentEvent, MezonDeleteWebhookByIdBody, ApiListOnboardingResponse, ApiCreateOnboardingRequest, MezonUpdateOnboardingBody, ApiOnboardingItem, ApiGenerateClanWebhookRequest, ApiGenerateClanWebhookResponse, ApiListClanWebhookResponse, MezonUpdateClanWebhookByIdBody, MezonUpdateClanDescBody, ApiUserStatusUpdate, ApiUserStatus, ApiListOnboardingStepResponse, MezonUpdateOnboardingStepByClanIdBody, ApiWalletLedgerList, ApiSdTopicList, ApiSdTopicRequest, ApiSdTopic, MezonUpdateEventBody, ApiTransactionDetail, MezonapiCreateRoomChannelApps, ApiGenerateMeetTokenRequest, ApiGenerateMeetTokenResponse, ApiMezonOauthClientList, ApiMezonOauthClient, ApiCreateHashChannelAppsResponse, ApiEmojiRecentList, ApiUserEventRequest, ApiUpdateRoleOrderRequest, ApiGenerateMezonMeetResponse, ApiGenerateMeetTokenExternalResponse, ApiUpdateClanOrderRequest, ApiMessage2InboxRequest, ApiListClanDiscover, ApiClanDiscoverRequest, ApiQuickMenuAccessList, ApiQuickMenuAccessRequest, ApiUnlockedItemRequest, ApiForSaleItemList, ApiUnlockedItemResponse, ApiIsFollowerResponse, ApiIsFollowerRequest, ApiTransferOwnershipRequest, ApiMeetParticipantRequest, ApiLinkAccountConfirmRequest, ApiLinkAccountMezon, ApiUser, ApiFriend, ApiListClanUnreadMsgIndicatorResponse, ApiAddFriendsResponse, ApiUpdateUsernameRequest, ApiBannedUserList, ApiIsBannedResponse } from "./api.gen";
17
17
  import { Session } from "./session";
18
18
  import { Socket } from "./socket";
19
19
  import { WebSocketAdapter } from "./web_socket_adapter";
@@ -533,5 +533,4 @@ export declare class Client {
533
533
  isFollower(session: Session, req: ApiIsFollowerRequest): Promise<ApiIsFollowerResponse>;
534
534
  transferOwnership(session: Session, req: ApiTransferOwnershipRequest): Promise<any>;
535
535
  isBanned(session: Session, channelId: string): Promise<ApiIsBannedResponse>;
536
- configAllowAnonymous(session: Session, req: ApiConfigAllowAnonymousRequest): Promise<any>;
537
536
  }
@@ -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,
@@ -7207,35 +7208,6 @@ var MezonApi = class {
7207
7208
  )
7208
7209
  ]);
7209
7210
  }
7210
- /** */
7211
- configAllowAnonymous(bearerToken, body, options = {}) {
7212
- if (body === null || body === void 0) {
7213
- throw new Error("'body' is a required parameter but is null or undefined.");
7214
- }
7215
- const urlPath = "/v2/anonymous/config";
7216
- const queryParams = /* @__PURE__ */ new Map();
7217
- let bodyJson = "";
7218
- bodyJson = JSON.stringify(body || {});
7219
- const fullUrl = this.buildFullUrl(this.basePath, urlPath, queryParams);
7220
- const fetchOptions = buildFetchOptions("POST", options, bodyJson);
7221
- if (bearerToken) {
7222
- fetchOptions.headers["Authorization"] = "Bearer " + bearerToken;
7223
- }
7224
- return Promise.race([
7225
- fetch(fullUrl, fetchOptions).then((response) => {
7226
- if (response.status == 204) {
7227
- return response;
7228
- } else if (response.status >= 200 && response.status < 300) {
7229
- return response.json();
7230
- } else {
7231
- throw response;
7232
- }
7233
- }),
7234
- new Promise(
7235
- (_, reject) => setTimeout(reject, this.timeoutMs, "Request timed out.")
7236
- )
7237
- ]);
7238
- }
7239
7211
  };
7240
7212
 
7241
7213
  // session.ts
@@ -7469,6 +7441,12 @@ function CreateChannelMessageFromEvent(message) {
7469
7441
  };
7470
7442
  return e;
7471
7443
  }
7444
+ var __hasConnectedOnce = false;
7445
+ var ConnectionState = {
7446
+ DISCONNECTED: "disconnected",
7447
+ CONNECTING: "connecting",
7448
+ CONNECTED: "connected"
7449
+ };
7472
7450
  var _DefaultSocket = class _DefaultSocket {
7473
7451
  constructor(host, port, useSSL = false, verbose = false, adapter = new WebSocketAdapterText(), sendTimeoutMs = _DefaultSocket.DefaultSendTimeoutMs) {
7474
7452
  this.host = host;
@@ -7480,7 +7458,7 @@ var _DefaultSocket = class _DefaultSocket {
7480
7458
  this.cIds = {};
7481
7459
  this.nextCid = 1;
7482
7460
  this._heartbeatTimeoutMs = _DefaultSocket.DefaultHeartbeatTimeoutMs;
7483
- this.hasConnectedBefore = false;
7461
+ this._connectionState = ConnectionState.DISCONNECTED;
7484
7462
  }
7485
7463
  generatecid() {
7486
7464
  const cid = this.nextCid.toString();
@@ -7488,12 +7466,17 @@ var _DefaultSocket = class _DefaultSocket {
7488
7466
  return cid;
7489
7467
  }
7490
7468
  isOpen() {
7491
- return this.adapter.isOpen();
7469
+ return this._connectionState === ConnectionState.CONNECTED;
7492
7470
  }
7493
7471
  connect(session, createStatus = false, platform = "", connectTimeoutMs = _DefaultSocket.DefaultConnectTimeoutMs, signal) {
7494
- if (this.adapter.isOpen()) {
7472
+ if (this._connectionState === ConnectionState.CONNECTED) {
7495
7473
  return Promise.resolve(session);
7496
7474
  }
7475
+ if (this._connectionState === ConnectionState.CONNECTING && this._connectPromise) {
7476
+ return this._connectPromise;
7477
+ }
7478
+ this.clearConnectTimeout();
7479
+ this._connectionState = ConnectionState.CONNECTING;
7497
7480
  const scheme = this.useSSL ? "wss://" : "ws://";
7498
7481
  this.adapter.connect(
7499
7482
  scheme,
@@ -7505,11 +7488,11 @@ var _DefaultSocket = class _DefaultSocket {
7505
7488
  signal
7506
7489
  );
7507
7490
  this.adapter.onClose = (evt) => {
7491
+ this._connectionState = ConnectionState.DISCONNECTED;
7492
+ this.stopHeartbeatLoop();
7493
+ this.clearConnectTimeout();
7508
7494
  this.ondisconnect(evt);
7509
7495
  };
7510
- this.adapter.onError = (evt) => {
7511
- this.onerror(evt);
7512
- };
7513
7496
  this.adapter.onMessage = (message) => __async(this, null, function* () {
7514
7497
  if (this.verbose && window && window.console) {
7515
7498
  console.log("Response: %o", JSON.stringify(message));
@@ -7714,29 +7697,46 @@ var _DefaultSocket = class _DefaultSocket {
7714
7697
  }
7715
7698
  }
7716
7699
  });
7717
- return new Promise((resolve, reject) => {
7700
+ const connectPromise = new Promise((resolve, reject) => {
7718
7701
  this.adapter.onOpen = (evt) => {
7719
7702
  if (this.verbose && window && window.console) {
7720
7703
  console.log(evt);
7721
7704
  }
7722
- const isReconnect = this.hasConnectedBefore;
7723
- this.hasConnectedBefore = true;
7724
- this.pingPong();
7705
+ const isReconnect = __hasConnectedOnce;
7706
+ __hasConnectedOnce = true;
7707
+ this.clearConnectTimeout();
7708
+ this._connectionState = ConnectionState.CONNECTED;
7709
+ this.startHeartbeatLoop();
7710
+ this._connectPromise = void 0;
7725
7711
  resolve(session);
7726
7712
  if (isReconnect) {
7727
7713
  this.onreconnect(evt);
7728
7714
  }
7729
7715
  };
7730
7716
  this.adapter.onError = (evt) => {
7731
- reject(evt);
7717
+ this._connectionState = ConnectionState.DISCONNECTED;
7718
+ this.stopHeartbeatLoop();
7719
+ this.clearConnectTimeout();
7720
+ this.onerror(evt);
7721
+ this._connectPromise = void 0;
7732
7722
  this.adapter.close();
7723
+ reject(evt);
7733
7724
  };
7734
- setTimeout(() => {
7725
+ this._connectTimeoutTimer = setTimeout(() => {
7726
+ this._connectionState = ConnectionState.DISCONNECTED;
7727
+ this.stopHeartbeatLoop();
7728
+ this.adapter.close();
7729
+ this._connectPromise = void 0;
7735
7730
  reject("The socket timed out when trying to connect.");
7731
+ this._connectTimeoutTimer = void 0;
7736
7732
  }, connectTimeoutMs);
7737
7733
  });
7734
+ this._connectPromise = connectPromise;
7735
+ return this._connectPromise;
7738
7736
  }
7739
7737
  disconnect(fireDisconnectEvent = true) {
7738
+ this._connectionState = ConnectionState.DISCONNECTED;
7739
+ this.stopHeartbeatLoop();
7740
7740
  if (this.adapter.isOpen()) {
7741
7741
  this.adapter.close();
7742
7742
  }
@@ -7761,6 +7761,8 @@ var _DefaultSocket = class _DefaultSocket {
7761
7761
  }
7762
7762
  }
7763
7763
  onerror(evt) {
7764
+ this._connectionState = ConnectionState.DISCONNECTED;
7765
+ this.stopHeartbeatLoop();
7764
7766
  if (this.verbose && window && window.console) {
7765
7767
  console.log(evt);
7766
7768
  }
@@ -8131,9 +8133,11 @@ var _DefaultSocket = class _DefaultSocket {
8131
8133
  }
8132
8134
  const cid = this.generatecid();
8133
8135
  this.cIds[cid] = { resolve, reject };
8134
- setTimeout(() => {
8135
- reject("The socket timed out while waiting for a response.");
8136
- }, sendTimeout);
8136
+ if (sendTimeout !== Infinity && sendTimeout > 0) {
8137
+ setTimeout(() => {
8138
+ reject("The socket timed out while waiting for a response.");
8139
+ }, sendTimeout);
8140
+ }
8137
8141
  untypedMessage.cid = cid;
8138
8142
  this.adapter.send(untypedMessage);
8139
8143
  }
@@ -8326,7 +8330,7 @@ var _DefaultSocket = class _DefaultSocket {
8326
8330
  code,
8327
8331
  topic_id
8328
8332
  }
8329
- });
8333
+ }, Infinity);
8330
8334
  return response.channel_message_ack;
8331
8335
  });
8332
8336
  }
@@ -8531,12 +8535,16 @@ var _DefaultSocket = class _DefaultSocket {
8531
8535
  }
8532
8536
  pingPong() {
8533
8537
  return __async(this, null, function* () {
8534
- if (!this.adapter.isOpen()) {
8538
+ if (!this.isOpen()) {
8539
+ this._connectionState = ConnectionState.DISCONNECTED;
8540
+ this.stopHeartbeatLoop();
8535
8541
  return;
8536
8542
  }
8537
8543
  try {
8538
8544
  yield this.send({ ping: {} }, this._heartbeatTimeoutMs);
8539
8545
  } catch (e) {
8546
+ this._connectionState = ConnectionState.DISCONNECTED;
8547
+ this.stopHeartbeatLoop();
8540
8548
  if (this.adapter.isOpen()) {
8541
8549
  if (window && window.console) {
8542
8550
  console.error("Server unreachable from heartbeat.");
@@ -8546,9 +8554,28 @@ var _DefaultSocket = class _DefaultSocket {
8546
8554
  }
8547
8555
  return;
8548
8556
  }
8549
- setTimeout(() => this.pingPong(), this._heartbeatTimeoutMs);
8557
+ this.startHeartbeatLoop();
8550
8558
  });
8551
8559
  }
8560
+ startHeartbeatLoop() {
8561
+ this.stopHeartbeatLoop();
8562
+ this._heartbeatTimer = setTimeout(
8563
+ () => this.pingPong(),
8564
+ this._heartbeatTimeoutMs
8565
+ );
8566
+ }
8567
+ stopHeartbeatLoop() {
8568
+ if (this._heartbeatTimer !== void 0) {
8569
+ clearTimeout(this._heartbeatTimer);
8570
+ this._heartbeatTimer = void 0;
8571
+ }
8572
+ }
8573
+ clearConnectTimeout() {
8574
+ if (this._connectTimeoutTimer !== void 0) {
8575
+ clearTimeout(this._connectTimeoutTimer);
8576
+ this._connectTimeoutTimer = void 0;
8577
+ }
8578
+ }
8552
8579
  };
8553
8580
  _DefaultSocket.DefaultHeartbeatTimeoutMs = 1e4;
8554
8581
  _DefaultSocket.DefaultSendTimeoutMs = 1e4;
@@ -11251,14 +11278,4 @@ var Client = class {
11251
11278
  });
11252
11279
  });
11253
11280
  }
11254
- configAllowAnonymous(session, req) {
11255
- return __async(this, null, function* () {
11256
- if (this.autoRefreshSession && session.refresh_token && session.isexpired(Date.now() / 1e3)) {
11257
- yield this.sessionRefresh(session);
11258
- }
11259
- return this.apiClient.configAllowAnonymous(session.token, req).then((response) => {
11260
- return response !== void 0;
11261
- });
11262
- });
11263
- }
11264
11281
  };
@@ -7173,35 +7173,6 @@ var MezonApi = class {
7173
7173
  )
7174
7174
  ]);
7175
7175
  }
7176
- /** */
7177
- configAllowAnonymous(bearerToken, body, options = {}) {
7178
- if (body === null || body === void 0) {
7179
- throw new Error("'body' is a required parameter but is null or undefined.");
7180
- }
7181
- const urlPath = "/v2/anonymous/config";
7182
- const queryParams = /* @__PURE__ */ new Map();
7183
- let bodyJson = "";
7184
- bodyJson = JSON.stringify(body || {});
7185
- const fullUrl = this.buildFullUrl(this.basePath, urlPath, queryParams);
7186
- const fetchOptions = buildFetchOptions("POST", options, bodyJson);
7187
- if (bearerToken) {
7188
- fetchOptions.headers["Authorization"] = "Bearer " + bearerToken;
7189
- }
7190
- return Promise.race([
7191
- fetch(fullUrl, fetchOptions).then((response) => {
7192
- if (response.status == 204) {
7193
- return response;
7194
- } else if (response.status >= 200 && response.status < 300) {
7195
- return response.json();
7196
- } else {
7197
- throw response;
7198
- }
7199
- }),
7200
- new Promise(
7201
- (_, reject) => setTimeout(reject, this.timeoutMs, "Request timed out.")
7202
- )
7203
- ]);
7204
- }
7205
7176
  };
7206
7177
 
7207
7178
  // session.ts
@@ -7435,6 +7406,12 @@ function CreateChannelMessageFromEvent(message) {
7435
7406
  };
7436
7407
  return e;
7437
7408
  }
7409
+ var __hasConnectedOnce = false;
7410
+ var ConnectionState = {
7411
+ DISCONNECTED: "disconnected",
7412
+ CONNECTING: "connecting",
7413
+ CONNECTED: "connected"
7414
+ };
7438
7415
  var _DefaultSocket = class _DefaultSocket {
7439
7416
  constructor(host, port, useSSL = false, verbose = false, adapter = new WebSocketAdapterText(), sendTimeoutMs = _DefaultSocket.DefaultSendTimeoutMs) {
7440
7417
  this.host = host;
@@ -7446,7 +7423,7 @@ var _DefaultSocket = class _DefaultSocket {
7446
7423
  this.cIds = {};
7447
7424
  this.nextCid = 1;
7448
7425
  this._heartbeatTimeoutMs = _DefaultSocket.DefaultHeartbeatTimeoutMs;
7449
- this.hasConnectedBefore = false;
7426
+ this._connectionState = ConnectionState.DISCONNECTED;
7450
7427
  }
7451
7428
  generatecid() {
7452
7429
  const cid = this.nextCid.toString();
@@ -7454,12 +7431,17 @@ var _DefaultSocket = class _DefaultSocket {
7454
7431
  return cid;
7455
7432
  }
7456
7433
  isOpen() {
7457
- return this.adapter.isOpen();
7434
+ return this._connectionState === ConnectionState.CONNECTED;
7458
7435
  }
7459
7436
  connect(session, createStatus = false, platform = "", connectTimeoutMs = _DefaultSocket.DefaultConnectTimeoutMs, signal) {
7460
- if (this.adapter.isOpen()) {
7437
+ if (this._connectionState === ConnectionState.CONNECTED) {
7461
7438
  return Promise.resolve(session);
7462
7439
  }
7440
+ if (this._connectionState === ConnectionState.CONNECTING && this._connectPromise) {
7441
+ return this._connectPromise;
7442
+ }
7443
+ this.clearConnectTimeout();
7444
+ this._connectionState = ConnectionState.CONNECTING;
7463
7445
  const scheme = this.useSSL ? "wss://" : "ws://";
7464
7446
  this.adapter.connect(
7465
7447
  scheme,
@@ -7471,11 +7453,11 @@ var _DefaultSocket = class _DefaultSocket {
7471
7453
  signal
7472
7454
  );
7473
7455
  this.adapter.onClose = (evt) => {
7456
+ this._connectionState = ConnectionState.DISCONNECTED;
7457
+ this.stopHeartbeatLoop();
7458
+ this.clearConnectTimeout();
7474
7459
  this.ondisconnect(evt);
7475
7460
  };
7476
- this.adapter.onError = (evt) => {
7477
- this.onerror(evt);
7478
- };
7479
7461
  this.adapter.onMessage = (message) => __async(this, null, function* () {
7480
7462
  if (this.verbose && window && window.console) {
7481
7463
  console.log("Response: %o", JSON.stringify(message));
@@ -7680,29 +7662,46 @@ var _DefaultSocket = class _DefaultSocket {
7680
7662
  }
7681
7663
  }
7682
7664
  });
7683
- return new Promise((resolve, reject) => {
7665
+ const connectPromise = new Promise((resolve, reject) => {
7684
7666
  this.adapter.onOpen = (evt) => {
7685
7667
  if (this.verbose && window && window.console) {
7686
7668
  console.log(evt);
7687
7669
  }
7688
- const isReconnect = this.hasConnectedBefore;
7689
- this.hasConnectedBefore = true;
7690
- this.pingPong();
7670
+ const isReconnect = __hasConnectedOnce;
7671
+ __hasConnectedOnce = true;
7672
+ this.clearConnectTimeout();
7673
+ this._connectionState = ConnectionState.CONNECTED;
7674
+ this.startHeartbeatLoop();
7675
+ this._connectPromise = void 0;
7691
7676
  resolve(session);
7692
7677
  if (isReconnect) {
7693
7678
  this.onreconnect(evt);
7694
7679
  }
7695
7680
  };
7696
7681
  this.adapter.onError = (evt) => {
7697
- reject(evt);
7682
+ this._connectionState = ConnectionState.DISCONNECTED;
7683
+ this.stopHeartbeatLoop();
7684
+ this.clearConnectTimeout();
7685
+ this.onerror(evt);
7686
+ this._connectPromise = void 0;
7698
7687
  this.adapter.close();
7688
+ reject(evt);
7699
7689
  };
7700
- setTimeout(() => {
7690
+ this._connectTimeoutTimer = setTimeout(() => {
7691
+ this._connectionState = ConnectionState.DISCONNECTED;
7692
+ this.stopHeartbeatLoop();
7693
+ this.adapter.close();
7694
+ this._connectPromise = void 0;
7701
7695
  reject("The socket timed out when trying to connect.");
7696
+ this._connectTimeoutTimer = void 0;
7702
7697
  }, connectTimeoutMs);
7703
7698
  });
7699
+ this._connectPromise = connectPromise;
7700
+ return this._connectPromise;
7704
7701
  }
7705
7702
  disconnect(fireDisconnectEvent = true) {
7703
+ this._connectionState = ConnectionState.DISCONNECTED;
7704
+ this.stopHeartbeatLoop();
7706
7705
  if (this.adapter.isOpen()) {
7707
7706
  this.adapter.close();
7708
7707
  }
@@ -7727,6 +7726,8 @@ var _DefaultSocket = class _DefaultSocket {
7727
7726
  }
7728
7727
  }
7729
7728
  onerror(evt) {
7729
+ this._connectionState = ConnectionState.DISCONNECTED;
7730
+ this.stopHeartbeatLoop();
7730
7731
  if (this.verbose && window && window.console) {
7731
7732
  console.log(evt);
7732
7733
  }
@@ -8097,9 +8098,11 @@ var _DefaultSocket = class _DefaultSocket {
8097
8098
  }
8098
8099
  const cid = this.generatecid();
8099
8100
  this.cIds[cid] = { resolve, reject };
8100
- setTimeout(() => {
8101
- reject("The socket timed out while waiting for a response.");
8102
- }, sendTimeout);
8101
+ if (sendTimeout !== Infinity && sendTimeout > 0) {
8102
+ setTimeout(() => {
8103
+ reject("The socket timed out while waiting for a response.");
8104
+ }, sendTimeout);
8105
+ }
8103
8106
  untypedMessage.cid = cid;
8104
8107
  this.adapter.send(untypedMessage);
8105
8108
  }
@@ -8292,7 +8295,7 @@ var _DefaultSocket = class _DefaultSocket {
8292
8295
  code,
8293
8296
  topic_id
8294
8297
  }
8295
- });
8298
+ }, Infinity);
8296
8299
  return response.channel_message_ack;
8297
8300
  });
8298
8301
  }
@@ -8497,12 +8500,16 @@ var _DefaultSocket = class _DefaultSocket {
8497
8500
  }
8498
8501
  pingPong() {
8499
8502
  return __async(this, null, function* () {
8500
- if (!this.adapter.isOpen()) {
8503
+ if (!this.isOpen()) {
8504
+ this._connectionState = ConnectionState.DISCONNECTED;
8505
+ this.stopHeartbeatLoop();
8501
8506
  return;
8502
8507
  }
8503
8508
  try {
8504
8509
  yield this.send({ ping: {} }, this._heartbeatTimeoutMs);
8505
8510
  } catch (e) {
8511
+ this._connectionState = ConnectionState.DISCONNECTED;
8512
+ this.stopHeartbeatLoop();
8506
8513
  if (this.adapter.isOpen()) {
8507
8514
  if (window && window.console) {
8508
8515
  console.error("Server unreachable from heartbeat.");
@@ -8512,9 +8519,28 @@ var _DefaultSocket = class _DefaultSocket {
8512
8519
  }
8513
8520
  return;
8514
8521
  }
8515
- setTimeout(() => this.pingPong(), this._heartbeatTimeoutMs);
8522
+ this.startHeartbeatLoop();
8516
8523
  });
8517
8524
  }
8525
+ startHeartbeatLoop() {
8526
+ this.stopHeartbeatLoop();
8527
+ this._heartbeatTimer = setTimeout(
8528
+ () => this.pingPong(),
8529
+ this._heartbeatTimeoutMs
8530
+ );
8531
+ }
8532
+ stopHeartbeatLoop() {
8533
+ if (this._heartbeatTimer !== void 0) {
8534
+ clearTimeout(this._heartbeatTimer);
8535
+ this._heartbeatTimer = void 0;
8536
+ }
8537
+ }
8538
+ clearConnectTimeout() {
8539
+ if (this._connectTimeoutTimer !== void 0) {
8540
+ clearTimeout(this._connectTimeoutTimer);
8541
+ this._connectTimeoutTimer = void 0;
8542
+ }
8543
+ }
8518
8544
  };
8519
8545
  _DefaultSocket.DefaultHeartbeatTimeoutMs = 1e4;
8520
8546
  _DefaultSocket.DefaultSendTimeoutMs = 1e4;
@@ -11217,21 +11243,12 @@ var Client = class {
11217
11243
  });
11218
11244
  });
11219
11245
  }
11220
- configAllowAnonymous(session, req) {
11221
- return __async(this, null, function* () {
11222
- if (this.autoRefreshSession && session.refresh_token && session.isexpired(Date.now() / 1e3)) {
11223
- yield this.sessionRefresh(session);
11224
- }
11225
- return this.apiClient.configAllowAnonymous(session.token, req).then((response) => {
11226
- return response !== void 0;
11227
- });
11228
- });
11229
- }
11230
11246
  };
11231
11247
  export {
11232
11248
  ChannelStreamMode,
11233
11249
  ChannelType,
11234
11250
  Client,
11251
+ ConnectionState,
11235
11252
  DefaultSocket,
11236
11253
  NotificationType,
11237
11254
  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.61",
3
+ "version": "2.13.63",
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