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