@stream-io/video-client 1.53.2 → 1.54.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [1.54.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.53.2...@stream-io/video-client-1.54.0) (2026-06-19)
6
+
7
+ ### Features
8
+
9
+ - **client:** allow disabling client event reporter ([#2286](https://github.com/GetStream/stream-video-js/issues/2286)) ([d727916](https://github.com/GetStream/stream-video-js/commit/d72791614c98ca3bedafe0538e0ac68050260ead))
10
+
11
+ ### Bug Fixes
12
+
13
+ - **client:** avoid SFU socket close when online fires without offline recovery ([#2292](https://github.com/GetStream/stream-video-js/issues/2292)) ([3034188](https://github.com/GetStream/stream-video-js/commit/30341888eddbe878e97d39bb2f11c5b4455755d6))
14
+ - **client:** send migrating_from after repeated rejoin failures ([#2287](https://github.com/GetStream/stream-video-js/issues/2287)) ([1c14617](https://github.com/GetStream/stream-video-js/commit/1c14617ce8cccbb97cc68e8ba75225f49607ccbe))
15
+
5
16
  ## [1.53.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.53.1...@stream-io/video-client-1.53.2) (2026-06-12)
6
17
 
7
18
  ### Bug Fixes
@@ -6640,7 +6640,7 @@ const getSdkVersion = (sdk) => {
6640
6640
  return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
6641
6641
  };
6642
6642
 
6643
- const version = "1.53.2";
6643
+ const version = "1.54.0";
6644
6644
  const [major, minor, patch] = version.split('.');
6645
6645
  let sdkInfo = {
6646
6646
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -14554,7 +14554,7 @@ class Call {
14554
14554
  ]);
14555
14555
  const isReconnecting = this.reconnectStrategy !== WebsocketReconnectStrategy.UNSPECIFIED;
14556
14556
  const reconnectDetails = isReconnecting
14557
- ? this.getReconnectDetails(data?.migrating_from, previousSessionId)
14557
+ ? this.getReconnectDetails(previousSfuClient?.edgeName, previousSessionId)
14558
14558
  : undefined;
14559
14559
  const preferredPublishOptions = !isReconnecting
14560
14560
  ? this.getPreferredPublishOptions()
@@ -14923,6 +14923,7 @@ class Call {
14923
14923
  const reconnectStartTime = Date.now();
14924
14924
  this.reconnectStrategy = strategy;
14925
14925
  this.reconnectReason = reason;
14926
+ const sfuRejoinFailures = new Map();
14926
14927
  const markAsReconnectingFailed = async () => {
14927
14928
  try {
14928
14929
  // attempt to fetch the call data from the server, as the call
@@ -14981,7 +14982,8 @@ class Call {
14981
14982
  if (this.reconnectStrategy !== WebsocketReconnectStrategy.FAST) {
14982
14983
  this.reconnectAttempts++;
14983
14984
  }
14984
- const currentStrategy = WebsocketReconnectStrategy[this.reconnectStrategy];
14985
+ const attemptedStrategy = this.reconnectStrategy;
14986
+ const currentStrategy = WebsocketReconnectStrategy[attemptedStrategy];
14985
14987
  try {
14986
14988
  // wait until the network is available
14987
14989
  await this.networkAvailableTask?.promise;
@@ -14994,9 +14996,24 @@ class Call {
14994
14996
  case WebsocketReconnectStrategy.FAST:
14995
14997
  await this.reconnectFast();
14996
14998
  break;
14997
- case WebsocketReconnectStrategy.REJOIN:
14998
- await this.reconnectRejoin();
14999
+ case WebsocketReconnectStrategy.REJOIN: {
15000
+ const confirmedBadSfus = Array.from(sfuRejoinFailures)
15001
+ .filter(([, failures]) => failures >= 2)
15002
+ .map(([sfu]) => sfu);
15003
+ if (this.joinCallData && confirmedBadSfus.length) {
15004
+ this.joinCallData.migrating_from =
15005
+ confirmedBadSfus[confirmedBadSfus.length - 1];
15006
+ this.joinCallData.migrating_from_list = confirmedBadSfus;
15007
+ }
15008
+ try {
15009
+ await this.reconnectRejoin();
15010
+ }
15011
+ finally {
15012
+ delete this.joinCallData?.migrating_from;
15013
+ delete this.joinCallData?.migrating_from_list;
15014
+ }
14999
15015
  break;
15016
+ }
15000
15017
  case WebsocketReconnectStrategy.MIGRATE:
15001
15018
  await this.reconnectMigrate();
15002
15019
  break;
@@ -15009,6 +15026,15 @@ class Call {
15009
15026
  break; // do-while loop, reconnection worked, exit the loop
15010
15027
  }
15011
15028
  catch (error) {
15029
+ if (attemptedStrategy === WebsocketReconnectStrategy.REJOIN) {
15030
+ const failedSfu = this.credentials?.server.edge_name;
15031
+ if (failedSfu) {
15032
+ const switchSfu = error instanceof SfuJoinError &&
15033
+ SfuJoinError.isJoinErrorCode(error.errorEvent);
15034
+ const failures = (sfuRejoinFailures.get(failedSfu) ?? 0) + 1;
15035
+ sfuRejoinFailures.set(failedSfu, switchSfu ? Math.max(failures, 2) : failures);
15036
+ }
15037
+ }
15012
15038
  if (this.state.callingState === CallingState.OFFLINE) {
15013
15039
  this.logger.debug(`[Reconnect] Can't reconnect while offline, stopping reconnection attempts`);
15014
15040
  break;
@@ -15204,6 +15230,8 @@ class Call {
15204
15230
  this.state.setCallingState(CallingState.OFFLINE);
15205
15231
  }
15206
15232
  else {
15233
+ if (!this.networkAvailableTask)
15234
+ return;
15207
15235
  this.logger.debug('[Reconnect] Going online');
15208
15236
  this.sfuClient?.close(StreamSfuClient.DISPOSE_OLD_SOCKET, 'Closing WS to reconnect after going online');
15209
15237
  // we went online, release the previous waiters and reset the state
@@ -17464,11 +17492,11 @@ class StreamClient {
17464
17492
  return await this.wsConnection.connect(this.defaultWSTimeout);
17465
17493
  };
17466
17494
  this.getSdkVersion = () => this.options.clientAppIdentifier?.sdkVersion ||
17467
- "1.53.2";
17495
+ "1.54.0";
17468
17496
  this.getUserAgent = () => {
17469
17497
  if (!this.cachedUserAgent) {
17470
17498
  const { clientAppIdentifier = {} } = this.options;
17471
- const { sdkName = 'js', sdkVersion = "1.53.2", ...extras } = clientAppIdentifier;
17499
+ const { sdkName = 'js', sdkVersion = "1.54.0", ...extras } = clientAppIdentifier;
17472
17500
  this.cachedUserAgent = [
17473
17501
  `stream-video-${sdkName}-v${sdkVersion}`,
17474
17502
  ...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
@@ -18146,6 +18174,8 @@ class ClientEventReporter {
18146
18174
  };
18147
18175
  };
18148
18176
  this.send = (body) => {
18177
+ if (!this.enabled)
18178
+ return;
18149
18179
  void this.sendWithRetry(body);
18150
18180
  };
18151
18181
  this.sendWithRetry = async (body) => {
@@ -18171,6 +18201,7 @@ class ClientEventReporter {
18171
18201
  return false;
18172
18202
  };
18173
18203
  this.streamClient = options.streamClient;
18204
+ this.enabled = options.enabled ?? true;
18174
18205
  }
18175
18206
  }
18176
18207
  const readPermissionStatus = (permission) => {
@@ -18651,6 +18682,7 @@ class StreamVideoClient {
18651
18682
  this.streamClient = createCoordinatorClient(apiKey, clientOptions);
18652
18683
  this.clientEventReporter = new ClientEventReporter({
18653
18684
  streamClient: this.streamClient,
18685
+ enabled: clientOptions?.clientEventsReportingEnabled ?? true,
18654
18686
  });
18655
18687
  this.writeableStateStore = new StreamVideoWriteableStateStore();
18656
18688
  this.readOnlyStateStore = new StreamVideoReadOnlyStateStore(this.writeableStateStore);