@stream-io/video-client 1.11.6 → 1.11.7

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.
Files changed (31) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/index.browser.es.js +68 -562
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +53 -547
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.es.js +68 -562
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/src/coordinator/connection/client.d.ts +0 -18
  9. package/dist/src/coordinator/connection/connection.d.ts +4 -12
  10. package/dist/src/coordinator/connection/signing.d.ts +1 -7
  11. package/dist/src/coordinator/connection/token_manager.d.ts +0 -2
  12. package/dist/src/coordinator/connection/types.d.ts +5 -6
  13. package/dist/src/coordinator/connection/utils.d.ts +6 -8
  14. package/package.json +6 -10
  15. package/src/__tests__/Call.test.ts +3 -2
  16. package/src/coordinator/connection/client.ts +12 -149
  17. package/src/coordinator/connection/connection.ts +40 -109
  18. package/src/coordinator/connection/signing.ts +31 -17
  19. package/src/coordinator/connection/token_manager.ts +3 -9
  20. package/src/coordinator/connection/types.ts +5 -9
  21. package/src/coordinator/connection/utils.ts +18 -50
  22. package/src/devices/__tests__/InputMediaDeviceManagerState.test.ts +13 -8
  23. package/src/devices/__tests__/mocks.ts +0 -4
  24. package/dist/src/coordinator/connection/base64.d.ts +0 -2
  25. package/dist/src/coordinator/connection/connection_fallback.d.ts +0 -39
  26. package/dist/src/coordinator/connection/errors.d.ts +0 -16
  27. package/dist/src/coordinator/connection/insights.d.ts +0 -57
  28. package/src/coordinator/connection/base64.ts +0 -80
  29. package/src/coordinator/connection/connection_fallback.ts +0 -242
  30. package/src/coordinator/connection/errors.ts +0 -80
  31. package/src/coordinator/connection/insights.ts +0 -88
package/dist/index.es.js CHANGED
@@ -1,15 +1,13 @@
1
1
  import 'webrtc-adapter';
2
2
  import { MessageType, isJsonObject, typeofJsonValue, PbLong } from '@protobuf-ts/runtime';
3
3
  import { ServiceType, stackIntercept, RpcError } from '@protobuf-ts/runtime-rpc';
4
- import axios, { AxiosHeaders } from 'axios';
4
+ import axios from 'axios';
5
5
  export { AxiosError } from 'axios';
6
6
  import { TwirpFetchTransport, TwirpErrorCode } from '@protobuf-ts/twirp-transport';
7
7
  import { UAParser } from 'ua-parser-js';
8
- import { ReplaySubject, combineLatest, BehaviorSubject, map as map$1, shareReplay, distinctUntilChanged, takeWhile, distinctUntilKeyChanged, fromEventPattern, startWith, concatMap, from, fromEvent, debounceTime, merge, pairwise, of } from 'rxjs';
8
+ import { ReplaySubject, combineLatest, BehaviorSubject, map, shareReplay, distinctUntilChanged, takeWhile, distinctUntilKeyChanged, fromEventPattern, startWith, concatMap, from, fromEvent, debounceTime, merge, pairwise, of } from 'rxjs';
9
9
  import * as SDP from 'sdp-transform';
10
10
  import https from 'https';
11
- import WebSocket$1 from 'isomorphic-ws';
12
- import { fromByteArray } from 'base64-js';
13
11
 
14
12
  /**
15
13
  * @export
@@ -3175,42 +3173,6 @@ function getRandomBytes(length) {
3175
3173
  getRandomValues(bytes);
3176
3174
  return bytes;
3177
3175
  }
3178
- function convertErrorToJson(err) {
3179
- const jsonObj = {};
3180
- if (!err)
3181
- return jsonObj;
3182
- try {
3183
- Object.getOwnPropertyNames(err).forEach((key) => {
3184
- jsonObj[key] = Object.getOwnPropertyDescriptor(err, key);
3185
- });
3186
- }
3187
- catch (_) {
3188
- return {
3189
- error: 'failed to serialize the error',
3190
- };
3191
- }
3192
- return jsonObj;
3193
- }
3194
- /**
3195
- * isOnline safely return the navigator.online value for browser env
3196
- * if navigator is not in global object, it always return true
3197
- */
3198
- function isOnline(logger) {
3199
- const nav = typeof navigator !== 'undefined'
3200
- ? navigator
3201
- : typeof window !== 'undefined' && window.navigator
3202
- ? window.navigator
3203
- : undefined;
3204
- if (!nav) {
3205
- logger('warn', 'isOnline failed to access window.navigator and assume browser is online');
3206
- return true;
3207
- }
3208
- // RN navigator has undefined for onLine
3209
- if (typeof nav.onLine !== 'boolean') {
3210
- return true;
3211
- }
3212
- return nav.onLine;
3213
- }
3214
3176
  /**
3215
3177
  * listenForConnectionChanges - Adds an event listener fired on browser going online or offline
3216
3178
  */
@@ -3226,6 +3188,13 @@ function removeConnectionEventListeners(cb) {
3226
3188
  window.removeEventListener('online', cb);
3227
3189
  }
3228
3190
  }
3191
+ function isErrorResponse(res) {
3192
+ return !res.status || res.status < 200 || 300 <= res.status;
3193
+ }
3194
+ // Type guards to check WebSocket error type
3195
+ function isCloseEvent(res) {
3196
+ return res.code !== undefined;
3197
+ }
3229
3198
 
3230
3199
  /**
3231
3200
  * Checks whether we are using React Native
@@ -3329,7 +3298,7 @@ const retryable = async (rpc, signal) => {
3329
3298
  return result;
3330
3299
  };
3331
3300
 
3332
- const version = "1.11.6";
3301
+ const version = "1.11.7";
3333
3302
  const [major, minor, patch] = version.split('.');
3334
3303
  let sdkInfo = {
3335
3304
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -5089,12 +5058,12 @@ class CallState {
5089
5058
  this.participants$ = this.participantsSubject.asObservable().pipe(
5090
5059
  // maintain stable-sort by mutating the participants stored
5091
5060
  // in the original subject
5092
- map$1((ps) => ps.sort(this.sortParticipantsBy)), shareReplay({ bufferSize: 1, refCount: true }));
5093
- this.localParticipant$ = this.participants$.pipe(map$1((participants) => participants.find((p) => p.isLocalParticipant)), shareReplay({ bufferSize: 1, refCount: true }));
5094
- this.remoteParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !p.isLocalParticipant)), shareReplay({ bufferSize: 1, refCount: true }));
5095
- this.pinnedParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !!p.pin)), shareReplay({ bufferSize: 1, refCount: true }));
5096
- this.dominantSpeaker$ = this.participants$.pipe(map$1((participants) => participants.find((p) => p.isDominantSpeaker)), shareReplay({ bufferSize: 1, refCount: true }));
5097
- this.hasOngoingScreenShare$ = this.participants$.pipe(map$1((participants) => participants.some((p) => hasScreenShare(p))), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }));
5061
+ map((ps) => ps.sort(this.sortParticipantsBy)), shareReplay({ bufferSize: 1, refCount: true }));
5062
+ this.localParticipant$ = this.participants$.pipe(map((participants) => participants.find((p) => p.isLocalParticipant)), shareReplay({ bufferSize: 1, refCount: true }));
5063
+ this.remoteParticipants$ = this.participants$.pipe(map((participants) => participants.filter((p) => !p.isLocalParticipant)), shareReplay({ bufferSize: 1, refCount: true }));
5064
+ this.pinnedParticipants$ = this.participants$.pipe(map((participants) => participants.filter((p) => !!p.pin)), shareReplay({ bufferSize: 1, refCount: true }));
5065
+ this.dominantSpeaker$ = this.participants$.pipe(map((participants) => participants.find((p) => p.isDominantSpeaker)), shareReplay({ bufferSize: 1, refCount: true }));
5066
+ this.hasOngoingScreenShare$ = this.participants$.pipe(map((participants) => participants.some((p) => hasScreenShare(p))), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }));
5098
5067
  // dates
5099
5068
  this.createdAt$ = this.createdAtSubject.asObservable();
5100
5069
  this.endedAt$ = this.endedAtSubject.asObservable();
@@ -7629,7 +7598,7 @@ class DynascaleManager {
7629
7598
  this.pendingSubscriptionsUpdate = null;
7630
7599
  this.videoTrackSubscriptionOverridesSubject = new BehaviorSubject({});
7631
7600
  this.videoTrackSubscriptionOverrides$ = this.videoTrackSubscriptionOverridesSubject.asObservable();
7632
- this.incomingVideoSettings$ = this.videoTrackSubscriptionOverrides$.pipe(map$1((overrides) => {
7601
+ this.incomingVideoSettings$ = this.videoTrackSubscriptionOverrides$.pipe(map((overrides) => {
7633
7602
  const { [globalOverrideKey]: globalSettings, ...participants } = overrides;
7634
7603
  return {
7635
7604
  enabled: globalSettings?.enabled !== false,
@@ -7765,7 +7734,7 @@ class DynascaleManager {
7765
7734
  });
7766
7735
  this.applyTrackSubscriptions(debounceType);
7767
7736
  };
7768
- const participant$ = this.callState.participants$.pipe(map$1((participants) => participants.find((participant) => participant.sessionId === sessionId)), takeWhile((participant) => !!participant), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }));
7737
+ const participant$ = this.callState.participants$.pipe(map((participants) => participants.find((participant) => participant.sessionId === sessionId)), takeWhile((participant) => !!participant), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }));
7769
7738
  /**
7770
7739
  * Since the video elements are now being removed from the DOM (React SDK) upon
7771
7740
  * visibility change, this subscription is not in use an stays here only for the
@@ -7777,7 +7746,7 @@ class DynascaleManager {
7777
7746
  const viewportVisibilityStateSubscription = boundParticipant.isLocalParticipant
7778
7747
  ? null
7779
7748
  : participant$
7780
- .pipe(map$1((p) => p.viewportVisibilityState?.[trackType]), distinctUntilChanged())
7749
+ .pipe(map((p) => p.viewportVisibilityState?.[trackType]), distinctUntilChanged())
7781
7750
  .subscribe((nextViewportVisibilityState) => {
7782
7751
  // skip initial trigger
7783
7752
  if (!viewportVisibilityState) {
@@ -7821,7 +7790,7 @@ class DynascaleManager {
7821
7790
  const publishedTracksSubscription = boundParticipant.isLocalParticipant
7822
7791
  ? null
7823
7792
  : participant$
7824
- .pipe(distinctUntilKeyChanged('publishedTracks'), map$1((p) => trackType === 'videoTrack' ? hasVideo(p) : hasScreenShare(p)), distinctUntilChanged())
7793
+ .pipe(distinctUntilKeyChanged('publishedTracks'), map((p) => trackType === 'videoTrack' ? hasVideo(p) : hasScreenShare(p)), distinctUntilChanged())
7825
7794
  .subscribe((isPublishing) => {
7826
7795
  if (isPublishing) {
7827
7796
  // the participant just started to publish a track
@@ -7883,7 +7852,7 @@ class DynascaleManager {
7883
7852
  const participant = this.callState.findParticipantBySessionId(sessionId);
7884
7853
  if (!participant || participant.isLocalParticipant)
7885
7854
  return;
7886
- const participant$ = this.callState.participants$.pipe(map$1((participants) => participants.find((p) => p.sessionId === sessionId)), takeWhile((p) => !!p), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }));
7855
+ const participant$ = this.callState.participants$.pipe(map((participants) => participants.find((p) => p.sessionId === sessionId)), takeWhile((p) => !!p), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }));
7887
7856
  const updateMediaStreamSubscription = participant$
7888
7857
  .pipe(distinctUntilKeyChanged(trackType === 'screenShareAudioTrack'
7889
7858
  ? 'screenShareAudioStream'
@@ -8207,7 +8176,7 @@ class BrowserPermission {
8207
8176
  // permissionState stays in 'prompt' state forever.
8208
8177
  // Typically, this happens when a user grants one-time permission.
8209
8178
  // Instead of checking if a permission is granted, we check if it isn't denied
8210
- map$1((state) => state !== 'denied'));
8179
+ map((state) => state !== 'denied'));
8211
8180
  }
8212
8181
  setState(state) {
8213
8182
  if (this.state !== state) {
@@ -8308,7 +8277,7 @@ const getDeviceChangeObserver = lazy(() => {
8308
8277
  // an observable that will never fire
8309
8278
  if (!navigator.mediaDevices.addEventListener)
8310
8279
  return from([]);
8311
- return fromEvent(navigator.mediaDevices, 'devicechange').pipe(map$1(() => undefined), debounceTime(500));
8280
+ return fromEvent(navigator.mediaDevices, 'devicechange').pipe(map(() => undefined), debounceTime(500));
8312
8281
  });
8313
8282
  /**
8314
8283
  * Prompts the user for a permission to use audio devices (if not already granted
@@ -11501,68 +11470,6 @@ class Call {
11501
11470
  }
11502
11471
  }
11503
11472
 
11504
- class InsightMetrics {
11505
- constructor() {
11506
- this.connectionStartTimestamp = null;
11507
- this.wsTotalFailures = 0;
11508
- this.wsConsecutiveFailures = 0;
11509
- this.instanceClientId = randomId();
11510
- }
11511
- }
11512
- /**
11513
- * postInsights is not supposed to be used by end users directly within chat application, and thus is kept isolated
11514
- * from all the client/connection code/logic.
11515
- *
11516
- * @param insightType
11517
- * @param insights
11518
- */
11519
- const postInsights = async (insightType, insights) => {
11520
- const maxAttempts = 3;
11521
- for (let i = 0; i < maxAttempts; i++) {
11522
- try {
11523
- await axios.post(`https://chat-insights.getstream.io/insights/${insightType}`, insights);
11524
- }
11525
- catch (e) {
11526
- await sleep((i + 1) * 3000);
11527
- continue;
11528
- }
11529
- break;
11530
- }
11531
- };
11532
- function buildWsFatalInsight(connection, event) {
11533
- return {
11534
- ...event,
11535
- ...buildWsBaseInsight(connection),
11536
- };
11537
- }
11538
- function buildWsBaseInsight(connection) {
11539
- const { client } = connection;
11540
- return {
11541
- ready_state: connection.ws?.readyState,
11542
- url: connection._buildUrl(),
11543
- api_key: client.key,
11544
- start_ts: client.insightMetrics.connectionStartTimestamp,
11545
- end_ts: new Date().getTime(),
11546
- auth_type: client.getAuthType(),
11547
- token: client.tokenManager.token,
11548
- user_id: client.userID,
11549
- user_details: client._user,
11550
- // device: client.options.device,
11551
- device: 'browser',
11552
- client_id: connection.connectionID,
11553
- ws_details: connection.ws,
11554
- ws_consecutive_failures: client.insightMetrics.wsConsecutiveFailures,
11555
- ws_total_failures: client.insightMetrics.wsTotalFailures,
11556
- request_id: connection.requestID,
11557
- online: typeof navigator !== 'undefined' ? navigator?.onLine : null,
11558
- user_agent: typeof navigator !== 'undefined' ? navigator?.userAgent : null,
11559
- instance_client_id: client.insightMetrics.instanceClientId,
11560
- };
11561
- }
11562
- function buildWsSuccessAfterFailureInsight(connection) {
11563
- return buildWsBaseInsight(connection);
11564
- }
11565
-
11566
11473
  /**
11567
11474
  * Saving a long-lived reference to a promise that can reject can be unsafe,
11568
11475
  * since rejecting the promise causes an unhandled rejection error (even if the
@@ -11590,9 +11497,6 @@ function makeSafePromise(promise) {
11590
11497
  return unwrapPromise;
11591
11498
  }
11592
11499
 
11593
- // Type guards to check WebSocket error type
11594
- const isCloseEvent = (res) => res.code !== undefined;
11595
- const isErrorEvent = (res) => res.error !== undefined;
11596
11500
  /**
11597
11501
  * StableWSConnection - A WS connection that reconnects upon failure.
11598
11502
  * - the browser will sometimes report that you're online or offline
@@ -11627,12 +11531,9 @@ class StableWSConnection {
11627
11531
  */
11628
11532
  this._buildUrl = () => {
11629
11533
  const params = new URLSearchParams();
11630
- // const qs = encodeURIComponent(this.client._buildWSPayload(this.requestID));
11631
- // params.set('json', qs);
11632
11534
  params.set('api_key', this.client.key);
11633
11535
  params.set('stream-auth-type', this.client.getAuthType());
11634
11536
  params.set('X-Stream-Client', this.client.getUserAgent());
11635
- // params.append('authorization', this.client._getToken()!);
11636
11537
  return `${this.client.wsBaseURL}/connect?${params.toString()}`;
11637
11538
  };
11638
11539
  /**
@@ -11681,7 +11582,6 @@ class StableWSConnection {
11681
11582
  custom: user.custom,
11682
11583
  },
11683
11584
  };
11684
- this.authenticationSent = true;
11685
11585
  this.ws?.send(JSON.stringify(authMessage));
11686
11586
  this._log('onopen() - onopen callback', { wsID });
11687
11587
  };
@@ -11698,7 +11598,6 @@ class StableWSConnection {
11698
11598
  if (!this.isResolved && data && data.type === 'connection.error') {
11699
11599
  this.isResolved = true;
11700
11600
  if (data.error) {
11701
- // @ts-expect-error - the types of _errorFromWSEvent are incorrect
11702
11601
  this.rejectPromise?.(this._errorFromWSEvent(data, false));
11703
11602
  return;
11704
11603
  }
@@ -11740,9 +11639,13 @@ class StableWSConnection {
11740
11639
  // this is a permanent error raised by stream..
11741
11640
  // usually caused by invalid auth details
11742
11641
  const error = new Error(`WS connection reject with error ${event.reason}`);
11642
+ // @ts-expect-error
11743
11643
  error.reason = event.reason;
11644
+ // @ts-expect-error
11744
11645
  error.code = event.code;
11646
+ // @ts-expect-error
11745
11647
  error.wasClean = event.wasClean;
11648
+ // @ts-expect-error
11746
11649
  error.target = event.target;
11747
11650
  this.rejectPromise?.(error);
11748
11651
  this._log(`onclose() - WS connection reject with error ${event.reason}`, {
@@ -11769,7 +11672,7 @@ class StableWSConnection {
11769
11672
  this.totalFailures += 1;
11770
11673
  this._setHealth(false);
11771
11674
  this.isConnecting = false;
11772
- this.rejectPromise?.(this._errorFromWSEvent(event));
11675
+ this.rejectPromise?.(new Error(`WebSocket error: ${event}`));
11773
11676
  this._log(`onerror() - WS connection resulted into error`, { event });
11774
11677
  this._reconnect();
11775
11678
  };
@@ -11779,7 +11682,6 @@ class StableWSConnection {
11779
11682
  *
11780
11683
  * @param {boolean} healthy boolean indicating if the connection is healthy or not
11781
11684
  * @param {boolean} dispatchImmediately boolean indicating to dispatch event immediately even if the connection is unhealthy
11782
- *
11783
11685
  */
11784
11686
  this._setHealth = (healthy, dispatchImmediately = false) => {
11785
11687
  if (healthy === this.isHealthy)
@@ -11804,7 +11706,6 @@ class StableWSConnection {
11804
11706
  };
11805
11707
  /**
11806
11708
  * _errorFromWSEvent - Creates an error object for the WS event
11807
- *
11808
11709
  */
11809
11710
  this._errorFromWSEvent = (event, isWSFailure = true) => {
11810
11711
  let code;
@@ -11812,17 +11713,18 @@ class StableWSConnection {
11812
11713
  let message;
11813
11714
  if (isCloseEvent(event)) {
11814
11715
  code = event.code;
11815
- statusCode = 'unknown';
11816
11716
  message = event.reason;
11717
+ statusCode = 0;
11817
11718
  }
11818
- if (isErrorEvent(event)) {
11819
- code = event.error.code;
11820
- statusCode = event.error.StatusCode;
11821
- message = event.error.message;
11822
- }
11823
- // Keeping this `warn` level log, to avoid cluttering of error logs from ws failures.
11824
- this._log(`_errorFromWSEvent() - WS failed with code ${code}`, { event }, 'warn');
11825
- const error = new Error(`WS failed with code ${code} and reason - ${message}`);
11719
+ else {
11720
+ const { error } = event;
11721
+ code = error.code;
11722
+ message = error.message;
11723
+ statusCode = error.StatusCode;
11724
+ }
11725
+ const msg = `WS failed with code: ${code} and reason: ${message}`;
11726
+ this._log(msg, { event }, 'warn');
11727
+ const error = new Error(msg);
11826
11728
  error.code = code;
11827
11729
  /**
11828
11730
  * StatusCode does not exist on any event types but has been left
@@ -11847,10 +11749,8 @@ class StableWSConnection {
11847
11749
  * Schedules a next health check ping for websocket.
11848
11750
  */
11849
11751
  this.scheduleNextPing = () => {
11850
- if (this.healthCheckTimeoutRef) {
11851
- clearTimeout(this.healthCheckTimeoutRef);
11852
- }
11853
11752
  // 30 seconds is the recommended interval (messenger uses this)
11753
+ clearTimeout(this.healthCheckTimeoutRef);
11854
11754
  this.healthCheckTimeoutRef = setTimeout(() => {
11855
11755
  // send the healthcheck..., server replies with a health check event
11856
11756
  const data = [{ type: 'health.check', client_id: this.client.clientID }];
@@ -11869,9 +11769,7 @@ class StableWSConnection {
11869
11769
  * to be reconnected.
11870
11770
  */
11871
11771
  this.scheduleConnectionCheck = () => {
11872
- if (this.connectionCheckTimeoutRef) {
11873
- clearTimeout(this.connectionCheckTimeoutRef);
11874
- }
11772
+ clearTimeout(this.connectionCheckTimeoutRef);
11875
11773
  this.connectionCheckTimeoutRef = setTimeout(() => {
11876
11774
  const now = new Date();
11877
11775
  if (this.lastEvent &&
@@ -11889,8 +11787,6 @@ class StableWSConnection {
11889
11787
  this.totalFailures = 0;
11890
11788
  /** We only make 1 attempt to reconnect at the same time.. */
11891
11789
  this.isConnecting = false;
11892
- /** True after the auth payload is sent to the server */
11893
- this.authenticationSent = false;
11894
11790
  /** To avoid reconnect if client is disconnected */
11895
11791
  this.isDisconnected = false;
11896
11792
  /** Boolean that indicates if the connection promise is resolved */
@@ -11998,18 +11894,10 @@ class StableWSConnection {
11998
11894
  this.isConnecting = false;
11999
11895
  this.isDisconnected = true;
12000
11896
  // start by removing all the listeners
12001
- if (this.healthCheckTimeoutRef) {
12002
- clearInterval(this.healthCheckTimeoutRef);
12003
- }
12004
- if (this.connectionCheckTimeoutRef) {
12005
- clearInterval(this.connectionCheckTimeoutRef);
12006
- }
11897
+ clearInterval(this.healthCheckTimeoutRef);
11898
+ clearInterval(this.connectionCheckTimeoutRef);
12007
11899
  removeConnectionEventListeners(this.onlineStatusChanged);
12008
11900
  this.isHealthy = false;
12009
- // remove ws handlers...
12010
- if (this.ws && this.ws.removeAllListeners) {
12011
- this.ws.removeAllListeners();
12012
- }
12013
11901
  let isClosedPromise;
12014
11902
  // and finally close...
12015
11903
  // Assigning to local here because we will remove it from this before the
@@ -12042,12 +11930,10 @@ class StableWSConnection {
12042
11930
  * @return {ConnectAPIResponse<ConnectedEvent>} Promise that completes once the first health check message is received
12043
11931
  */
12044
11932
  async _connect() {
12045
- if (this.isConnecting ||
12046
- (this.isDisconnected && this.client.options.enableWSFallback))
11933
+ if (this.isConnecting)
12047
11934
  return; // simply ignore _connect if it's currently trying to connect
12048
11935
  this.isConnecting = true;
12049
11936
  this.requestID = randomId();
12050
- this.client.insightMetrics.connectionStartTimestamp = new Date().getTime();
12051
11937
  let isTokenReady = false;
12052
11938
  try {
12053
11939
  this._log(`_connect() - waiting for token`);
@@ -12071,7 +11957,8 @@ class StableWSConnection {
12071
11957
  wsURL,
12072
11958
  requestID: this.requestID,
12073
11959
  });
12074
- this.ws = new WebSocket$1(wsURL);
11960
+ const WS = this.client.options.WebSocketImpl ?? WebSocket;
11961
+ this.ws = new WS(wsURL);
12075
11962
  this.ws.onopen = this.onopen.bind(this, this.wsID);
12076
11963
  this.ws.onclose = this.onclose.bind(this, this.wsID);
12077
11964
  this.ws.onerror = this.onerror.bind(this, this.wsID);
@@ -12081,11 +11968,6 @@ class StableWSConnection {
12081
11968
  if (response) {
12082
11969
  this.connectionID = response.connection_id;
12083
11970
  this.client.resolveConnectionId?.(this.connectionID);
12084
- if (this.client.insightMetrics.wsConsecutiveFailures > 0 &&
12085
- this.client.options.enableInsights) {
12086
- postInsights('ws_success_after_failure', buildWsSuccessAfterFailureInsight(this));
12087
- this.client.insightMetrics.wsConsecutiveFailures = 0;
12088
- }
12089
11971
  return response;
12090
11972
  }
12091
11973
  }
@@ -12094,12 +11976,6 @@ class StableWSConnection {
12094
11976
  this.isConnecting = false;
12095
11977
  // @ts-ignore
12096
11978
  this._log(`_connect() - Error - `, err);
12097
- if (this.client.options.enableInsights) {
12098
- this.client.insightMetrics.wsConsecutiveFailures++;
12099
- this.client.insightMetrics.wsTotalFailures++;
12100
- const insights = buildWsFatalInsight(this, convertErrorToJson(err));
12101
- postInsights?.('ws_fatal', insights);
12102
- }
12103
11979
  this.client.rejectConnectionId?.(err);
12104
11980
  throw err;
12105
11981
  }
@@ -12133,7 +12009,7 @@ class StableWSConnection {
12133
12009
  this._log('_reconnect() - Abort (2) since already connecting or healthy');
12134
12010
  return;
12135
12011
  }
12136
- if (this.isDisconnected && this.client.options.enableWSFallback) {
12012
+ if (this.isDisconnected) {
12137
12013
  this._log('_reconnect() - Abort (3) since disconnect() is called');
12138
12014
  return;
12139
12015
  }
@@ -12175,7 +12051,6 @@ class StableWSConnection {
12175
12051
  // ws connection from now on.
12176
12052
  this.wsID += 1;
12177
12053
  try {
12178
- this?.ws?.removeAllListeners();
12179
12054
  this?.ws?.close();
12180
12055
  }
12181
12056
  catch (e) {
@@ -12187,36 +12062,16 @@ class StableWSConnection {
12187
12062
  }
12188
12063
  }
12189
12064
 
12190
- function isString(arrayOrString) {
12191
- return typeof arrayOrString === 'string';
12192
- }
12193
- function isMapStringCallback(arrayOrString, callback) {
12194
- return !!callback && isString(arrayOrString);
12195
- }
12196
- function map(arrayOrString, callback) {
12197
- const res = [];
12198
- if (isString(arrayOrString) && isMapStringCallback(arrayOrString, callback)) {
12199
- for (let k = 0, len = arrayOrString.length; k < len; k++) {
12200
- if (arrayOrString.charAt(k)) {
12201
- const kValue = arrayOrString.charAt(k);
12202
- const mappedValue = callback(kValue, k, arrayOrString);
12203
- res[k] = mappedValue;
12204
- }
12205
- }
12206
- }
12207
- else if (!isString(arrayOrString) &&
12208
- !isMapStringCallback(arrayOrString, callback)) {
12209
- for (let k = 0, len = arrayOrString.length; k < len; k++) {
12210
- if (k in arrayOrString) {
12211
- const kValue = arrayOrString[k];
12212
- const mappedValue = callback(kValue, k, arrayOrString);
12213
- res[k] = mappedValue;
12214
- }
12215
- }
12065
+ function getUserFromToken(token) {
12066
+ const fragments = token.split('.');
12067
+ if (fragments.length !== 3) {
12068
+ return '';
12216
12069
  }
12217
- return res;
12070
+ const b64Payload = fragments[1];
12071
+ const payload = decodeBase64(b64Payload);
12072
+ const data = JSON.parse(payload);
12073
+ return data.user_id;
12218
12074
  }
12219
- const encodeBase64 = (data) => fromByteArray(new Uint8Array(map(data, (char) => char.charCodeAt(0))));
12220
12075
  // base-64 decoder throws exception if encoded string is not padded by '=' to make string length
12221
12076
  // in multiples of 4. So gonna use our own method for this purpose to keep backwards compatibility
12222
12077
  // https://github.com/beatgammit/base64-js/blob/master/index.js#L26
@@ -12238,29 +12093,6 @@ const decodeBase64 = (s) => {
12238
12093
  return r;
12239
12094
  };
12240
12095
 
12241
- /**
12242
- *
12243
- * @param {string} userId the id of the user
12244
- * @return {string}
12245
- */
12246
- function DevToken(userId) {
12247
- return [
12248
- 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', //{"alg": "HS256", "typ": "JWT"}
12249
- encodeBase64(JSON.stringify({ user_id: userId })),
12250
- 'devtoken', // hardcoded signature
12251
- ].join('.');
12252
- }
12253
- function UserFromToken(token) {
12254
- const fragments = token.split('.');
12255
- if (fragments.length !== 3) {
12256
- return '';
12257
- }
12258
- const b64Payload = fragments[1];
12259
- const payload = decodeBase64(b64Payload);
12260
- const data = JSON.parse(payload);
12261
- return data.user_id;
12262
- }
12263
-
12264
12096
  /**
12265
12097
  * TokenManager
12266
12098
  *
@@ -12269,8 +12101,6 @@ function UserFromToken(token) {
12269
12101
  class TokenManager {
12270
12102
  /**
12271
12103
  * Constructor
12272
- *
12273
- * @param {Secret} secret
12274
12104
  */
12275
12105
  constructor(secret) {
12276
12106
  /**
@@ -12323,7 +12153,7 @@ class TokenManager {
12323
12153
  // Allow empty token for anonymous users
12324
12154
  if (isAnonymous && tokenOrProvider === '')
12325
12155
  return;
12326
- const tokenUserId = UserFromToken(tokenOrProvider);
12156
+ const tokenUserId = getUserFromToken(tokenOrProvider);
12327
12157
  if (tokenOrProvider != null &&
12328
12158
  (tokenUserId == null ||
12329
12159
  tokenUserId === '' ||
@@ -12338,7 +12168,6 @@ class TokenManager {
12338
12168
  // Fetches a token from tokenProvider function and sets in tokenManager.
12339
12169
  // In case of static token, it will simply resolve to static token.
12340
12170
  this.loadToken = () => {
12341
- // eslint-disable-next-line no-async-promise-executor
12342
12171
  this.loadTokenPromise = new Promise(async (resolve, reject) => {
12343
12172
  if (this.type === 'static') {
12344
12173
  return resolve(this.token);
@@ -12367,236 +12196,11 @@ class TokenManager {
12367
12196
  };
12368
12197
  this.isStatic = () => this.type === 'static';
12369
12198
  this.loadTokenPromise = null;
12370
- if (secret) {
12371
- this.secret = secret;
12372
- }
12199
+ this.secret = secret;
12373
12200
  this.type = 'static';
12374
12201
  }
12375
12202
  }
12376
12203
 
12377
- const APIErrorCodes = {
12378
- '-1': { name: 'InternalSystemError', retryable: true },
12379
- '2': { name: 'AccessKeyError', retryable: false },
12380
- '3': { name: 'AuthenticationFailedError', retryable: true },
12381
- '4': { name: 'InputError', retryable: false },
12382
- '6': { name: 'DuplicateUsernameError', retryable: false },
12383
- '9': { name: 'RateLimitError', retryable: true },
12384
- '16': { name: 'DoesNotExistError', retryable: false },
12385
- '17': { name: 'NotAllowedError', retryable: false },
12386
- '18': { name: 'EventNotSupportedError', retryable: false },
12387
- '19': { name: 'ChannelFeatureNotSupportedError', retryable: false },
12388
- '20': { name: 'MessageTooLongError', retryable: false },
12389
- '21': { name: 'MultipleNestingLevelError', retryable: false },
12390
- '22': { name: 'PayloadTooBigError', retryable: false },
12391
- '23': { name: 'RequestTimeoutError', retryable: true },
12392
- '24': { name: 'MaxHeaderSizeExceededError', retryable: false },
12393
- '40': { name: 'AuthErrorTokenExpired', retryable: false },
12394
- '41': { name: 'AuthErrorTokenNotValidYet', retryable: false },
12395
- '42': { name: 'AuthErrorTokenUsedBeforeIssuedAt', retryable: false },
12396
- '43': { name: 'AuthErrorTokenSignatureInvalid', retryable: false },
12397
- '44': { name: 'CustomCommandEndpointMissingError', retryable: false },
12398
- '45': { name: 'CustomCommandEndpointCallError', retryable: true },
12399
- '46': { name: 'ConnectionIDNotFoundError', retryable: false },
12400
- '60': { name: 'CoolDownError', retryable: true },
12401
- '69': { name: 'ErrWrongRegion', retryable: false },
12402
- '70': { name: 'ErrQueryChannelPermissions', retryable: false },
12403
- '71': { name: 'ErrTooManyConnections', retryable: true },
12404
- '99': { name: 'AppSuspendedError', retryable: false },
12405
- };
12406
- function isAPIError(error) {
12407
- return error.code !== undefined;
12408
- }
12409
- function isErrorRetryable(error) {
12410
- if (!error.code)
12411
- return false;
12412
- const err = APIErrorCodes[`${error.code}`];
12413
- if (!err)
12414
- return false;
12415
- return err.retryable;
12416
- }
12417
- function isConnectionIDError(error) {
12418
- return error.code === 46; // ConnectionIDNotFoundError
12419
- }
12420
- function isWSFailure(err) {
12421
- if (typeof err.isWSFailure === 'boolean') {
12422
- return err.isWSFailure;
12423
- }
12424
- try {
12425
- return JSON.parse(err.message).isWSFailure;
12426
- }
12427
- catch (_) {
12428
- return false;
12429
- }
12430
- }
12431
- function isErrorResponse(res) {
12432
- return !res.status || res.status < 200 || 300 <= res.status;
12433
- }
12434
-
12435
- var ConnectionState;
12436
- (function (ConnectionState) {
12437
- ConnectionState["Closed"] = "CLOSED";
12438
- ConnectionState["Connected"] = "CONNECTED";
12439
- ConnectionState["Connecting"] = "CONNECTING";
12440
- ConnectionState["Disconnected"] = "DISCONNECTED";
12441
- ConnectionState["Init"] = "INIT";
12442
- })(ConnectionState || (ConnectionState = {}));
12443
- class WSConnectionFallback {
12444
- constructor(client) {
12445
- /** @private */
12446
- this._onlineStatusChanged = (event) => {
12447
- this._log(`_onlineStatusChanged() - ${event.type}`);
12448
- if (event.type === 'offline') {
12449
- this._setState(ConnectionState.Closed);
12450
- this.cancelToken?.cancel('disconnect() is called');
12451
- this.cancelToken = undefined;
12452
- return;
12453
- }
12454
- if (event.type === 'online' && this.state === ConnectionState.Closed) {
12455
- this.connect(true);
12456
- }
12457
- };
12458
- /** @private */
12459
- this._req = async (params, config, retry) => {
12460
- if (!this.cancelToken && !params.close) {
12461
- this.cancelToken = axios.CancelToken.source();
12462
- }
12463
- try {
12464
- const res = await this.client.doAxiosRequest('get', this.client.baseURL.replace(':3030', ':8900') + '/longpoll', // replace port if present for testing with local API
12465
- undefined, {
12466
- config: { ...config, cancelToken: this.cancelToken?.token },
12467
- params,
12468
- publicEndpoint: true,
12469
- });
12470
- this.consecutiveFailures = 0; // always reset in case of no error
12471
- return res;
12472
- }
12473
- catch (err) {
12474
- this.consecutiveFailures += 1;
12475
- // @ts-ignore
12476
- if (retry && isErrorRetryable(err)) {
12477
- this._log(`_req() - Retryable error, retrying request`);
12478
- await sleep(retryInterval(this.consecutiveFailures));
12479
- return this._req(params, config, retry);
12480
- }
12481
- throw err;
12482
- }
12483
- };
12484
- /** @private */
12485
- this._poll = async () => {
12486
- while (this.state === ConnectionState.Connected) {
12487
- try {
12488
- const data = await this._req({}, {
12489
- timeout: 30000,
12490
- }, true); // 30s => API responds in 20s if there is no event
12491
- if (data.events?.length) {
12492
- for (let i = 0; i < data.events.length; i++) {
12493
- this.client.dispatchEvent(data.events[i]);
12494
- }
12495
- }
12496
- }
12497
- catch (err) {
12498
- if (axios.isCancel(err)) {
12499
- this._log(`_poll() - axios canceled request`);
12500
- return;
12501
- }
12502
- /** client.doAxiosRequest will take care of TOKEN_EXPIRED error */
12503
- // @ts-ignore
12504
- if (isConnectionIDError(err)) {
12505
- this._log(`_poll() - ConnectionID error, connecting without ID...`);
12506
- this._setState(ConnectionState.Disconnected);
12507
- this.connect(true);
12508
- return;
12509
- }
12510
- // @ts-ignore
12511
- if (isAPIError(err) && !isErrorRetryable(err)) {
12512
- this._setState(ConnectionState.Closed);
12513
- return;
12514
- }
12515
- await sleep(retryInterval(this.consecutiveFailures));
12516
- }
12517
- }
12518
- };
12519
- /**
12520
- * connect try to open a longpoll request
12521
- * @param reconnect should be false for first call and true for subsequent calls to keep the connection alive and call recoverState
12522
- */
12523
- this.connect = async (reconnect = false) => {
12524
- if (this.state === ConnectionState.Connecting) {
12525
- this._log('connect() - connecting already in progress', { reconnect }, 'warn');
12526
- return;
12527
- }
12528
- if (this.state === ConnectionState.Connected) {
12529
- this._log('connect() - already connected and polling', { reconnect }, 'warn');
12530
- return;
12531
- }
12532
- this._setState(ConnectionState.Connecting);
12533
- this.connectionID = undefined; // connect should be sent with empty connection_id so API creates one
12534
- try {
12535
- const { event } = await this._req({ json: this.client._buildWSPayload() }, {
12536
- timeout: 8000, // 8s
12537
- }, reconnect);
12538
- this._setState(ConnectionState.Connected);
12539
- this.connectionID = event.connection_id;
12540
- this.client.resolveConnectionId?.();
12541
- // @ts-expect-error
12542
- this.client.dispatchEvent(event);
12543
- this._poll();
12544
- return event;
12545
- }
12546
- catch (err) {
12547
- this._setState(ConnectionState.Closed);
12548
- this.client.rejectConnectionId?.();
12549
- throw err;
12550
- }
12551
- };
12552
- /**
12553
- * isHealthy checks if there is a connectionID and connection is in Connected state
12554
- */
12555
- this.isHealthy = () => {
12556
- return !!this.connectionID && this.state === ConnectionState.Connected;
12557
- };
12558
- this.disconnect = async (timeout = 2000) => {
12559
- removeConnectionEventListeners(this._onlineStatusChanged);
12560
- this._setState(ConnectionState.Disconnected);
12561
- this.cancelToken?.cancel('disconnect() is called');
12562
- this.cancelToken = undefined;
12563
- const connection_id = this.connectionID;
12564
- this.connectionID = undefined;
12565
- try {
12566
- await this._req({ close: true, connection_id }, {
12567
- timeout,
12568
- }, false);
12569
- this._log(`disconnect() - Closed connectionID`);
12570
- }
12571
- catch (err) {
12572
- this._log(`disconnect() - Failed`, { err }, 'error');
12573
- }
12574
- };
12575
- this.client = client;
12576
- this.state = ConnectionState.Init;
12577
- this.consecutiveFailures = 0;
12578
- addConnectionEventListeners(this._onlineStatusChanged);
12579
- }
12580
- _log(msg, extra = {}, level = 'info') {
12581
- this.client.logger(level, 'WSConnectionFallback:' + msg, {
12582
- ...extra,
12583
- });
12584
- }
12585
- _setState(state) {
12586
- this._log(`_setState() - ${state}`);
12587
- // transition from connecting => connected
12588
- if (this.state === ConnectionState.Connecting &&
12589
- state === ConnectionState.Connected) {
12590
- this.client.dispatchEvent({ type: 'connection.changed', online: true });
12591
- }
12592
- if (state === ConnectionState.Closed ||
12593
- state === ConnectionState.Disconnected) {
12594
- this.client.dispatchEvent({ type: 'connection.changed', online: false });
12595
- }
12596
- this.state = state;
12597
- }
12598
- }
12599
-
12600
12204
  const getLocationHint = async (hintUrl = `https://hint.stream-io-video.com/`, timeout = 2000, maxAttempts = 3) => {
12601
12205
  const logger = getLogger(['location-hint']);
12602
12206
  let attempt = 0;
@@ -12639,9 +12243,6 @@ class StreamClient {
12639
12243
  */
12640
12244
  constructor(key, options) {
12641
12245
  this.listeners = {};
12642
- this.devToken = (userID) => {
12643
- return DevToken(userID);
12644
- };
12645
12246
  this.getAuthType = () => {
12646
12247
  return this.anonymous ? 'anonymous' : 'jwt';
12647
12248
  };
@@ -12659,7 +12260,7 @@ class StreamClient {
12659
12260
  }
12660
12261
  return hint;
12661
12262
  };
12662
- this._getConnectionID = () => this.wsConnection?.connectionID || this.wsFallback?.connectionID;
12263
+ this._getConnectionID = () => this.wsConnection?.connectionID;
12663
12264
  this._hasConnectionID = () => Boolean(this._getConnectionID());
12664
12265
  /**
12665
12266
  * connectUser - Set the current user and open a WebSocket connection
@@ -12735,11 +12336,7 @@ class StreamClient {
12735
12336
  * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
12736
12337
  */
12737
12338
  this.closeConnection = async (timeout) => {
12738
- await Promise.all([
12739
- this.wsConnection?.disconnect(timeout),
12740
- this.wsFallback?.disconnect(timeout),
12741
- ]);
12742
- return Promise.resolve();
12339
+ await this.wsConnection?.disconnect(timeout);
12743
12340
  };
12744
12341
  /**
12745
12342
  * Creates a new WebSocket connection with the current user. Returns empty promise, if there is an active connection
@@ -12753,12 +12350,11 @@ class StreamClient {
12753
12350
  this.logger('info', 'client:openConnection() - connection already in progress');
12754
12351
  return await wsPromise;
12755
12352
  }
12756
- if ((this.wsConnection?.isHealthy || this.wsFallback?.isHealthy()) &&
12757
- this._hasConnectionID()) {
12353
+ if (this.wsConnection?.isHealthy && this._hasConnectionID()) {
12758
12354
  this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists');
12759
12355
  return;
12760
12356
  }
12761
- this._setupConnectionIdPromise();
12357
+ await this._setupConnectionIdPromise();
12762
12358
  this.clientID = `${this.userID}--${randomId()}`;
12763
12359
  const newWsPromise = this.connect();
12764
12360
  this.wsPromiseSafe = makeSafePromise(newWsPromise);
@@ -12785,11 +12381,7 @@ class StreamClient {
12785
12381
  this.resolveConnectionId = undefined;
12786
12382
  };
12787
12383
  this.connectGuestUser = async (user) => {
12788
- this.guestUserCreatePromise = this.doAxiosRequest('post', '/guest', {
12789
- user: {
12790
- ...user,
12791
- },
12792
- }, { publicEndpoint: true });
12384
+ this.guestUserCreatePromise = this.doAxiosRequest('post', '/guest', { user }, { publicEndpoint: true });
12793
12385
  const response = await this.guestUserCreatePromise;
12794
12386
  this.guestUserCreatePromise.finally(() => (this.guestUserCreatePromise = undefined));
12795
12387
  return this.connectUser(response.user, response.access_token);
@@ -12799,7 +12391,7 @@ class StreamClient {
12799
12391
  */
12800
12392
  this.connectAnonymousUser = async (user, tokenOrProvider) => {
12801
12393
  addConnectionEventListeners(this.updateNetworkConnectionStatus);
12802
- this._setupConnectionIdPromise();
12394
+ await this._setupConnectionIdPromise();
12803
12395
  this.anonymous = true;
12804
12396
  await this._setToken(user, tokenOrProvider, this.anonymous);
12805
12397
  this._setUser(user);
@@ -12993,78 +12585,17 @@ class StreamClient {
12993
12585
  if (!this.userID || !this._user) {
12994
12586
  throw Error('Call connectUser or connectAnonymousUser before starting the connection');
12995
12587
  }
12996
- if (!this.wsBaseURL) {
12588
+ if (!this.wsBaseURL)
12997
12589
  throw Error('Websocket base url not set');
12998
- }
12999
- if (!this.clientID) {
12590
+ if (!this.clientID)
13000
12591
  throw Error('clientID is not set');
13001
- }
13002
- if (!this.wsConnection &&
13003
- (this.options.warmUp || this.options.enableInsights)) {
13004
- this._sayHi();
13005
- }
13006
12592
  // The StableWSConnection handles all the reconnection logic.
13007
- if (this.options.wsConnection && this.node) {
13008
- // Intentionally avoiding adding ts generics on wsConnection in options since its only useful for unit test purpose.
13009
- this.options.wsConnection.setClient(this);
13010
- this.wsConnection = this.options
13011
- .wsConnection;
13012
- }
13013
- else {
13014
- this.wsConnection = new StableWSConnection(this);
13015
- }
13016
- try {
13017
- // if fallback is used before, continue using it instead of waiting for WS to fail
13018
- if (this.wsFallback) {
13019
- return await this.wsFallback.connect();
13020
- }
13021
- this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
13022
- // if WSFallback is enabled, ws connect should timeout faster so fallback can try
13023
- return await this.wsConnection.connect(this.options.enableWSFallback
13024
- ? this.defaultWSTimeoutWithFallback
13025
- : this.defaultWSTimeout);
13026
- }
13027
- catch (err) {
13028
- // run fallback only if it's WS/Network error and not a normal API error
13029
- // make sure browser is online before even trying the longpoll
13030
- if (this.options.enableWSFallback &&
13031
- // @ts-ignore
13032
- isWSFailure(err) &&
13033
- isOnline(this.logger)) {
13034
- this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
13035
- this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
13036
- this.wsConnection._destroyCurrentWSConnection();
13037
- this.wsConnection.disconnect().then(); // close WS so no retry
13038
- this.wsFallback = new WSConnectionFallback(this);
13039
- return await this.wsFallback.connect();
13040
- }
13041
- throw err;
13042
- }
13043
- };
13044
- /**
13045
- * Check the connectivity with server for warmup purpose.
13046
- *
13047
- * @private
13048
- */
13049
- this._sayHi = () => {
13050
- const client_request_id = randomId();
13051
- const opts = {
13052
- headers: AxiosHeaders.from({
13053
- 'x-client-request-id': client_request_id,
13054
- }),
13055
- };
13056
- this.doAxiosRequest('get', this.baseURL + '/hi', null, opts).catch((e) => {
13057
- if (this.options.enableInsights) {
13058
- postInsights('http_hi_failed', {
13059
- api_key: this.key,
13060
- err: e,
13061
- client_request_id,
13062
- });
13063
- }
13064
- });
12593
+ this.wsConnection = new StableWSConnection(this);
12594
+ this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
12595
+ return await this.wsConnection.connect(this.defaultWSTimeout);
13065
12596
  };
13066
12597
  this.getUserAgent = () => {
13067
- const version = "1.11.6";
12598
+ const version = "1.11.7";
13068
12599
  return (this.userAgent ||
13069
12600
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
13070
12601
  };
@@ -13112,18 +12643,6 @@ class StreamClient {
13112
12643
  return null;
13113
12644
  return this.tokenManager.getToken();
13114
12645
  };
13115
- /**
13116
- * encode ws url payload
13117
- * @private
13118
- * @returns json string
13119
- */
13120
- this._buildWSPayload = (client_request_id) => {
13121
- return JSON.stringify({
13122
- user_id: this.userID,
13123
- user_details: this._user,
13124
- client_request_id,
13125
- });
13126
- };
13127
12646
  this.updateNetworkConnectionStatus = (event) => {
13128
12647
  if (event.type === 'offline') {
13129
12648
  this.logger('debug', 'device went offline');
@@ -13152,7 +12671,6 @@ class StreamClient {
13152
12671
  this.options = {
13153
12672
  timeout: 5000,
13154
12673
  withCredentials: false, // making sure cookies are not sent
13155
- warmUp: false,
13156
12674
  ...inputOptions,
13157
12675
  };
13158
12676
  if (this.node && !this.options.httpsAgent) {
@@ -13162,16 +12680,6 @@ class StreamClient {
13162
12680
  });
13163
12681
  }
13164
12682
  this.setBaseURL(this.options.baseURL || 'https://video.stream-io-api.com/video');
13165
- if (typeof process !== 'undefined' &&
13166
- 'env' in process &&
13167
- process.env.STREAM_LOCAL_TEST_RUN) {
13168
- this.setBaseURL('http://localhost:3030/video');
13169
- }
13170
- if (typeof process !== 'undefined' &&
13171
- 'env' in process &&
13172
- process.env.STREAM_LOCAL_TEST_HOST) {
13173
- this.setBaseURL(`http://${process.env.STREAM_LOCAL_TEST_HOST}/video`);
13174
- }
13175
12683
  this.axiosInstance = axios.create({
13176
12684
  ...this.options,
13177
12685
  baseURL: this.baseURL,
@@ -13188,8 +12696,6 @@ class StreamClient {
13188
12696
  // generated from secret.
13189
12697
  this.tokenManager = new TokenManager(this.secret);
13190
12698
  this.consecutiveFailures = 0;
13191
- this.insightMetrics = new InsightMetrics();
13192
- this.defaultWSTimeoutWithFallback = 6000;
13193
12699
  this.defaultWSTimeout = 15000;
13194
12700
  this.logger = isFunction(inputOptions.logger)
13195
12701
  ? inputOptions.logger