@stream-io/video-client 1.17.1 → 1.18.1

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,26 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [1.18.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.18.0...@stream-io/video-client-1.18.1) (2025-02-28)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * prevent reconnecting state when offline ([#1703](https://github.com/GetStream/stream-video-js/issues/1703)) ([aeac90d](https://github.com/GetStream/stream-video-js/commit/aeac90d8b7b14820e3e0e30282e51fc7824f8bf8))
11
+
12
+ ## [1.18.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.17.1...@stream-io/video-client-1.18.0) (2025-02-26)
13
+
14
+
15
+ ### Features
16
+
17
+ * align SDK version reporting, use higher-entropy user agent data for stats ([#1696](https://github.com/GetStream/stream-video-js/issues/1696)) ([e02e8d9](https://github.com/GetStream/stream-video-js/commit/e02e8d9b3843086a3fa859a8bd31ba65ace5a7fd))
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * don't implicitly mark calls as `ringing` ([#1697](https://github.com/GetStream/stream-video-js/issues/1697)) ([3429a7b](https://github.com/GetStream/stream-video-js/commit/3429a7ba52e13a43b96d2c3c28f270da111f84b2)), closes [/github.com/GetStream/stream-video-js/issues/1561#issuecomment-2662584543](https://github.com/GetStream//github.com/GetStream/stream-video-js/issues/1561/issues/issuecomment-2662584543)
23
+ * use axios version that doesnt import node specific module ([#1699](https://github.com/GetStream/stream-video-js/issues/1699)) ([414e01b](https://github.com/GetStream/stream-video-js/commit/414e01b9c7e4c4862b429e48c506673bcc228fa4))
24
+
5
25
  ## [1.17.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.17.0...@stream-io/video-client-1.17.1) (2025-02-19)
6
26
 
7
27
 
@@ -7463,7 +7463,7 @@ const aggregate = (stats) => {
7463
7463
  return report;
7464
7464
  };
7465
7465
 
7466
- const version = "1.17.1";
7466
+ const version = "1.18.1";
7467
7467
  const [major, minor, patch] = version.split('.');
7468
7468
  let sdkInfo = {
7469
7469
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -7484,15 +7484,9 @@ const getSdkInfo = () => {
7484
7484
  const setOSInfo = (info) => {
7485
7485
  osInfo = info;
7486
7486
  };
7487
- const getOSInfo = () => {
7488
- return osInfo;
7489
- };
7490
7487
  const setDeviceInfo = (info) => {
7491
7488
  deviceInfo = info;
7492
7489
  };
7493
- const getDeviceInfo = () => {
7494
- return deviceInfo;
7495
- };
7496
7490
  const getWebRTCInfo = () => {
7497
7491
  return webRtcInfo;
7498
7492
  };
@@ -7560,26 +7554,40 @@ const setPowerState = (powerMode) => {
7560
7554
  const getDeviceState = () => {
7561
7555
  return deviceState;
7562
7556
  };
7563
- const getClientDetails = () => {
7557
+ const getClientDetails = async () => {
7564
7558
  if (isReactNative()) {
7565
7559
  // Since RN doesn't support web, sharing browser info is not required
7566
7560
  return {
7567
- sdk: getSdkInfo(),
7568
- os: getOSInfo(),
7569
- device: getDeviceInfo(),
7561
+ sdk: sdkInfo,
7562
+ os: osInfo,
7563
+ device: deviceInfo,
7570
7564
  };
7571
7565
  }
7566
+ // @ts-expect-error - userAgentData is not yet in the TS types
7567
+ const userAgentDataApi = navigator.userAgentData;
7568
+ let userAgentData;
7569
+ if (userAgentDataApi && userAgentDataApi.getHighEntropyValues) {
7570
+ try {
7571
+ userAgentData = await userAgentDataApi.getHighEntropyValues([
7572
+ 'platform',
7573
+ 'platformVersion',
7574
+ ]);
7575
+ }
7576
+ catch (e) {
7577
+ // Ignore the error
7578
+ }
7579
+ }
7572
7580
  const userAgent = new UAParser(navigator.userAgent);
7573
7581
  const { browser, os, device, cpu } = userAgent.getResult();
7574
7582
  return {
7575
- sdk: getSdkInfo(),
7583
+ sdk: sdkInfo,
7576
7584
  browser: {
7577
7585
  name: browser.name || navigator.userAgent,
7578
7586
  version: browser.version || '',
7579
7587
  },
7580
7588
  os: {
7581
- name: os.name || '',
7582
- version: os.version || '',
7589
+ name: userAgentData?.platform || os.name || '',
7590
+ version: userAgentData?.platformVersion || os.version || '',
7583
7591
  architecture: cpu.architecture || '',
7584
7592
  },
7585
7593
  device: {
@@ -7808,8 +7816,6 @@ const globalOverrideKey = Symbol('globalOverrideKey');
7808
7816
  class DynascaleManager {
7809
7817
  /**
7810
7818
  * Creates a new DynascaleManager instance.
7811
- *
7812
- * @param call the call to manage.
7813
7819
  */
7814
7820
  constructor(callState, speaker) {
7815
7821
  /**
@@ -10447,6 +10453,7 @@ class Call {
10447
10453
  this.leaveCallHooks.forEach((hook) => hook());
10448
10454
  this.initialized = false;
10449
10455
  this.hasJoinedOnce = false;
10456
+ this.ringingSubject.next(false);
10450
10457
  this.clientStore.unregisterCall(this);
10451
10458
  this.camera.dispose();
10452
10459
  this.microphone.dispose();
@@ -10505,7 +10512,7 @@ class Call {
10505
10512
  this.state.updateFromCallResponse(response.call);
10506
10513
  this.state.setMembers(response.members);
10507
10514
  this.state.setOwnCapabilities(response.own_capabilities);
10508
- if (params?.ring || this.ringing) {
10515
+ if (params?.ring) {
10509
10516
  // the call response can indicate where the call is still ringing or not
10510
10517
  this.ringingSubject.next(true);
10511
10518
  }
@@ -10527,7 +10534,7 @@ class Call {
10527
10534
  this.state.updateFromCallResponse(response.call);
10528
10535
  this.state.setMembers(response.members);
10529
10536
  this.state.setOwnCapabilities(response.own_capabilities);
10530
- if (data?.ring || this.ringing) {
10537
+ if (data?.ring) {
10531
10538
  // the call response can indicate where the call is still ringing or not
10532
10539
  this.ringingSubject.next(true);
10533
10540
  }
@@ -10617,8 +10624,13 @@ class Call {
10617
10624
  statsOptions = joinResponse.stats_options;
10618
10625
  }
10619
10626
  catch (error) {
10620
- // restore the previous call state if the join-flow fails
10621
- this.state.setCallingState(callingState);
10627
+ // prevent triggering reconnect flow if the state is OFFLINE
10628
+ const avoidRestoreState = this.state.callingState === CallingState.OFFLINE &&
10629
+ callingState === CallingState.RECONNECTING;
10630
+ if (!avoidRestoreState) {
10631
+ // restore the previous call state if the join-flow fails
10632
+ this.state.setCallingState(callingState);
10633
+ }
10622
10634
  throw error;
10623
10635
  }
10624
10636
  }
@@ -10639,7 +10651,7 @@ class Call {
10639
10651
  : previousSfuClient;
10640
10652
  this.sfuClient = sfuClient;
10641
10653
  this.dynascaleManager.setSfuClient(sfuClient);
10642
- const clientDetails = getClientDetails();
10654
+ const clientDetails = await getClientDetails();
10643
10655
  // we don't need to send JoinRequest if we are re-using an existing healthy SFU client
10644
10656
  if (previousSfuClient !== sfuClient) {
10645
10657
  // prepare a generic SDP and send it to the SFU.
@@ -10898,7 +10910,7 @@ class Call {
10898
10910
  this.state.updateFromCallResponse(joinResponse.call);
10899
10911
  this.state.setMembers(joinResponse.members);
10900
10912
  this.state.setOwnCapabilities(joinResponse.own_capabilities);
10901
- if (data?.ring && !this.ringing) {
10913
+ if (data?.ring) {
10902
10914
  this.ringingSubject.next(true);
10903
10915
  }
10904
10916
  if (this.ringing && !this.isCreatedByMe) {
@@ -11767,7 +11779,7 @@ class Call {
11767
11779
  * @param custom Custom data
11768
11780
  */
11769
11781
  this.submitFeedback = async (rating, { reason, custom, } = {}) => {
11770
- const { sdkName, sdkVersion, ...platform } = getSdkSignature(getClientDetails());
11782
+ const { sdkName, sdkVersion, ...platform } = getSdkSignature(await getClientDetails());
11771
11783
  return this.streamClient.post(`${this.streamClientBasePath}/feedback`, {
11772
11784
  rating,
11773
11785
  reason,
@@ -12453,7 +12465,7 @@ class StableWSConnection {
12453
12465
  }
12454
12466
  }
12455
12467
  catch (err) {
12456
- await this.client._setupConnectionIdPromise();
12468
+ this.client._setupConnectionIdPromise();
12457
12469
  this.isConnecting = false;
12458
12470
  // @ts-ignore
12459
12471
  this._log(`_connect() - Error - `, err);
@@ -12766,8 +12778,7 @@ class StreamClient {
12766
12778
  if (this.userID) {
12767
12779
  throw new Error('Use client.disconnect() before trying to connect as a different user. connectUser was called twice.');
12768
12780
  }
12769
- if ((this._isUsingServerAuth() || this.node) &&
12770
- !this.options.allowServerSideConnect) {
12781
+ if ((this.secret || this.node) && !this.options.allowServerSideConnect) {
12771
12782
  this.logger('warn', 'Please do not use connectUser server side. Use our @stream-io/node-sdk instead: https://getstream.io/video/docs/api/');
12772
12783
  }
12773
12784
  // we generate the client id client side
@@ -12835,7 +12846,7 @@ class StreamClient {
12835
12846
  this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists');
12836
12847
  return;
12837
12848
  }
12838
- await this._setupConnectionIdPromise();
12849
+ this._setupConnectionIdPromise();
12839
12850
  this.clientID = `${this.userID}--${randomId()}`;
12840
12851
  const newWsPromise = this.connect();
12841
12852
  this.wsPromiseSafe = makeSafePromise(newWsPromise);
@@ -12872,7 +12883,7 @@ class StreamClient {
12872
12883
  */
12873
12884
  this.connectAnonymousUser = async (user, tokenOrProvider) => {
12874
12885
  addConnectionEventListeners(this.updateNetworkConnectionStatus);
12875
- await this._setupConnectionIdPromise();
12886
+ this._setupConnectionIdPromise();
12876
12887
  this.anonymous = true;
12877
12888
  await this._setToken(user, tokenOrProvider, this.anonymous);
12878
12889
  this._setUser(user);
@@ -12922,12 +12933,16 @@ class StreamClient {
12922
12933
  }));
12923
12934
  };
12924
12935
  this._logApiRequest = (type, url, data, config) => {
12936
+ if (getLogLevel() !== 'trace')
12937
+ return;
12925
12938
  this.logger('trace', `client: ${type} - Request - ${url}`, {
12926
12939
  payload: data,
12927
12940
  config,
12928
12941
  });
12929
12942
  };
12930
12943
  this._logApiResponse = (type, url, response) => {
12944
+ if (getLogLevel() !== 'trace')
12945
+ return;
12931
12946
  this.logger('trace', `client:${type} - Response - url: ${url} > status ${response.status}`, {
12932
12947
  response,
12933
12948
  });
@@ -13076,17 +13091,17 @@ class StreamClient {
13076
13091
  return await this.wsConnection.connect(this.defaultWSTimeout);
13077
13092
  };
13078
13093
  this.getUserAgent = () => {
13079
- const version = "1.17.1";
13080
- return (this.userAgent ||
13081
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
13082
- };
13083
- this.setUserAgent = (userAgent) => {
13084
- this.userAgent = userAgent;
13094
+ if (!this.cachedUserAgent) {
13095
+ const { clientAppIdentifier = {} } = this.options;
13096
+ const { sdkName = 'js', sdkVersion = "1.18.1", ...extras } = clientAppIdentifier;
13097
+ this.cachedUserAgent = [
13098
+ `stream-video-${sdkName}-v${sdkVersion}`,
13099
+ ...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
13100
+ `client_bundle=${"browser-esm"}`,
13101
+ ].join('|');
13102
+ }
13103
+ return this.cachedUserAgent;
13085
13104
  };
13086
- /**
13087
- * _isUsingServerAuth - Returns true if we're using server side auth
13088
- */
13089
- this._isUsingServerAuth = () => !!this.secret;
13090
13105
  this._enrichAxiosOptions = (options = {
13091
13106
  params: {},
13092
13107
  headers: {},
@@ -13199,24 +13214,32 @@ class StreamClient {
13199
13214
  const getInstanceKey = (apiKey, user) => {
13200
13215
  return `${apiKey}/${user.id}`;
13201
13216
  };
13217
+ /**
13218
+ * Utility function to get the client app identifier.
13219
+ */
13220
+ const getClientAppIdentifier = (options) => {
13221
+ const appId = options?.clientAppIdentifier || {};
13222
+ const sdkInfo = getSdkInfo();
13223
+ if (sdkInfo) {
13224
+ // ensure the sdk name and version are set correctly,
13225
+ // overriding any user-provided values
13226
+ appId.sdkName = SdkType[sdkInfo.type].toLowerCase();
13227
+ appId.sdkVersion = `${sdkInfo.major}.${sdkInfo.minor}.${sdkInfo.patch}`;
13228
+ }
13229
+ return appId;
13230
+ };
13202
13231
  /**
13203
13232
  * Creates a coordinator client.
13204
13233
  */
13205
13234
  const createCoordinatorClient = (apiKey, options) => {
13235
+ const clientAppIdentifier = getClientAppIdentifier(options);
13206
13236
  const coordinatorLogger = getLogger(['coordinator']);
13207
- const streamClient = new StreamClient(apiKey, {
13237
+ return new StreamClient(apiKey, {
13208
13238
  persistUserOnConnectionFailure: true,
13209
13239
  ...options,
13240
+ clientAppIdentifier,
13210
13241
  logger: coordinatorLogger,
13211
13242
  });
13212
- const sdkInfo = getSdkInfo();
13213
- if (sdkInfo) {
13214
- const sdkName = SdkType[sdkInfo.type].toLowerCase();
13215
- const sdkVersion = `${sdkInfo.major}.${sdkInfo.minor}.${sdkInfo.patch}`;
13216
- const userAgent = streamClient.getUserAgent();
13217
- streamClient.setUserAgent(`${userAgent}-video-${sdkName}-sdk-${sdkVersion}`);
13218
- }
13219
- return streamClient;
13220
13243
  };
13221
13244
  /**
13222
13245
  * Creates a token provider and allows integrators to provide
@@ -13583,5 +13606,5 @@ class StreamVideoClient {
13583
13606
  }
13584
13607
  StreamVideoClient._instances = new Map();
13585
13608
 
13586
- export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, FrameRecordingSettingsRequestModeEnum, FrameRecordingSettingsResponseModeEnum, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestClosedCaptionModeEnum, TranscriptionSettingsRequestLanguageEnum, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseClosedCaptionModeEnum, TranscriptionSettingsResponseLanguageEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioBrowserPermission, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceInfo, getDeviceState, getLogLevel, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoBrowserPermission, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setPowerState, setSdkInfo, setThermalState, setWebRTCInfo, speakerLayoutSortPreset, speaking };
13609
+ export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, FrameRecordingSettingsRequestModeEnum, FrameRecordingSettingsResponseModeEnum, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestClosedCaptionModeEnum, TranscriptionSettingsRequestLanguageEnum, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseClosedCaptionModeEnum, TranscriptionSettingsResponseLanguageEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioBrowserPermission, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceState, getLogLevel, getLogger, getScreenShareStream, getSdkInfo, getVideoBrowserPermission, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setPowerState, setSdkInfo, setThermalState, setWebRTCInfo, speakerLayoutSortPreset, speaking };
13587
13610
  //# sourceMappingURL=index.browser.es.js.map