@stream-io/video-client 1.7.2 → 1.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -2896,6 +2896,13 @@ function convertErrorToJson(err) {
2896
2896
  }
2897
2897
  return jsonObj;
2898
2898
  }
2899
+ /**
2900
+ * Informs if a promise is yet to be resolved or rejected
2901
+ */
2902
+ async function isPromisePending(promise) {
2903
+ const emptyObj = {};
2904
+ return Promise.race([promise, emptyObj]).then((value) => (value === emptyObj ? true : false), () => false);
2905
+ }
2899
2906
  /**
2900
2907
  * isOnline safely return the navigator.online value for browser env
2901
2908
  * if navigator is not in global object, it always return true
@@ -2949,7 +2956,7 @@ const logLevels = Object.freeze({
2949
2956
  warn: 3,
2950
2957
  error: 4,
2951
2958
  });
2952
- let logger$1;
2959
+ let logger;
2953
2960
  let level = 'info';
2954
2961
  const logToConsole = (logLevel, message, ...args) => {
2955
2962
  let logMethod;
@@ -2983,7 +2990,7 @@ const logToConsole = (logLevel, message, ...args) => {
2983
2990
  logMethod(message, ...args);
2984
2991
  };
2985
2992
  const setLogger = (l, lvl) => {
2986
- logger$1 = l;
2993
+ logger = l;
2987
2994
  if (lvl) {
2988
2995
  setLogLevel(lvl);
2989
2996
  }
@@ -2993,7 +3000,7 @@ const setLogLevel = (l) => {
2993
3000
  };
2994
3001
  const getLogLevel = () => level;
2995
3002
  const getLogger = (withTags) => {
2996
- const loggerMethod = logger$1 || logToConsole;
3003
+ const loggerMethod = logger || logToConsole;
2997
3004
  const tags = (withTags || []).filter(Boolean).join(':');
2998
3005
  const result = (logLevel, message, ...args) => {
2999
3006
  if (logLevels[logLevel] >= logLevels[level]) {
@@ -3034,7 +3041,7 @@ const retryable = async (rpc, signal) => {
3034
3041
  return result;
3035
3042
  };
3036
3043
 
3037
- const version = "1.7.2";
3044
+ const version = "1.7.4";
3038
3045
  const [major, minor, patch] = version.split('.');
3039
3046
  let sdkInfo = {
3040
3047
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -11384,6 +11391,15 @@ class StableWSConnection {
11384
11391
  this._log(`_connect() - tokenProvider failed before, so going to retry`);
11385
11392
  await this.client.tokenManager.loadToken();
11386
11393
  }
11394
+ let mustSetupConnectionIdPromise = true;
11395
+ if (this.client.connectionIdPromise) {
11396
+ if (await isPromisePending(this.client.connectionIdPromise)) {
11397
+ mustSetupConnectionIdPromise = false;
11398
+ }
11399
+ }
11400
+ if (mustSetupConnectionIdPromise) {
11401
+ this.client._setupConnectionIdPromise();
11402
+ }
11387
11403
  this._setupConnectionPromise();
11388
11404
  const wsURL = this._buildUrl();
11389
11405
  this._log(`_connect() - Connecting to ${wsURL}`, {
@@ -11409,6 +11425,7 @@ class StableWSConnection {
11409
11425
  }
11410
11426
  }
11411
11427
  catch (err) {
11428
+ await this.client._setupConnectionIdPromise();
11412
11429
  this.isConnecting = false;
11413
11430
  // @ts-ignore
11414
11431
  this._log(`_connect() - Error - `, err);
@@ -11910,27 +11927,31 @@ class WSConnectionFallback {
11910
11927
  }
11911
11928
  }
11912
11929
 
11913
- const logger = getLogger(['location']);
11914
- const HINT_URL = `https://hint.stream-io-video.com/`;
11915
- const getLocationHint = async (hintUrl = HINT_URL, timeout = 2000) => {
11916
- const abortController = new AbortController();
11917
- const timeoutId = setTimeout(() => abortController.abort(), timeout);
11918
- try {
11919
- const response = await fetch(hintUrl, {
11920
- method: 'HEAD',
11921
- signal: abortController.signal,
11922
- });
11923
- const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
11924
- logger('debug', `Location header: ${awsPop}`);
11925
- return awsPop.substring(0, 3); // AMS1-P2 -> AMS
11926
- }
11927
- catch (e) {
11928
- logger('warn', `Failed to get location hint from ${hintUrl}`, e);
11929
- return 'ERR';
11930
- }
11931
- finally {
11932
- clearTimeout(timeoutId);
11933
- }
11930
+ const getLocationHint = async (hintUrl = `https://hint.stream-io-video.com/`, timeout = 2000, maxAttempts = 3) => {
11931
+ const logger = getLogger(['location-hint']);
11932
+ let attempt = 0;
11933
+ let locationHint = 'ERR';
11934
+ do {
11935
+ const abortController = new AbortController();
11936
+ const timeoutId = setTimeout(() => abortController.abort(), timeout);
11937
+ try {
11938
+ const response = await fetch(hintUrl, {
11939
+ method: 'HEAD',
11940
+ signal: abortController.signal,
11941
+ });
11942
+ const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
11943
+ logger('debug', `Location header: ${awsPop}`);
11944
+ locationHint = awsPop.substring(0, 3); // AMS1-P2 -> AMS
11945
+ }
11946
+ catch (e) {
11947
+ logger('warn', `Failed to get location hint from ${hintUrl}`, e);
11948
+ locationHint = 'ERR';
11949
+ }
11950
+ finally {
11951
+ clearTimeout(timeoutId);
11952
+ }
11953
+ } while (locationHint === 'ERR' && ++attempt < maxAttempts);
11954
+ return locationHint;
11934
11955
  };
11935
11956
 
11936
11957
  class StreamClient {
@@ -12066,10 +12087,7 @@ class StreamClient {
12066
12087
  this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists');
12067
12088
  return Promise.resolve();
12068
12089
  }
12069
- this.connectionIdPromise = new Promise((resolve, reject) => {
12070
- this.resolveConnectionId = resolve;
12071
- this.rejectConnectionId = reject;
12072
- });
12090
+ this._setupConnectionIdPromise();
12073
12091
  this.clientID = `${this.userID}--${randomId()}`;
12074
12092
  this.wsPromise = this.connect();
12075
12093
  return this.wsPromise;
@@ -12109,10 +12127,7 @@ class StreamClient {
12109
12127
  */
12110
12128
  this.connectAnonymousUser = async (user, tokenOrProvider) => {
12111
12129
  addConnectionEventListeners(this.updateNetworkConnectionStatus);
12112
- this.connectionIdPromise = new Promise((resolve, reject) => {
12113
- this.resolveConnectionId = resolve;
12114
- this.rejectConnectionId = reject;
12115
- });
12130
+ this._setupConnectionIdPromise();
12116
12131
  this.anonymous = true;
12117
12132
  await this._setToken(user, tokenOrProvider, this.anonymous);
12118
12133
  this._setUser(user);
@@ -12151,6 +12166,16 @@ class StreamClient {
12151
12166
  this.logger('debug', `Removing listener for ${eventName} event`);
12152
12167
  this.listeners[eventName] = this.listeners[eventName]?.filter((value) => value !== callback);
12153
12168
  };
12169
+ /**
12170
+ * sets up the this.connectionIdPromise
12171
+ */
12172
+ this._setupConnectionIdPromise = async () => {
12173
+ /** a promise that is resolved once connection id is set */
12174
+ this.connectionIdPromise = new Promise((resolve, reject) => {
12175
+ this.resolveConnectionId = resolve;
12176
+ this.rejectConnectionId = reject;
12177
+ });
12178
+ };
12154
12179
  this._logApiRequest = (type, url, data, config) => {
12155
12180
  this.logger('trace', `client: ${type} - Request - ${url}`, {
12156
12181
  payload: data,
@@ -12173,8 +12198,18 @@ class StreamClient {
12173
12198
  await Promise.all([
12174
12199
  this.tokenManager.tokenReady(),
12175
12200
  this.guestUserCreatePromise,
12176
- this.connectionIdPromise,
12177
12201
  ]);
12202
+ // we need to wait for presence of connection id before making requests
12203
+ try {
12204
+ await this.connectionIdPromise;
12205
+ }
12206
+ catch (e) {
12207
+ // in case connection id was rejected
12208
+ // reconnection maybe in progress
12209
+ // we can wait for healthy connection to resolve, which rejects when 15s timeout is reached
12210
+ await this.wsConnection?._waitForHealthy();
12211
+ await this.connectionIdPromise;
12212
+ }
12178
12213
  }
12179
12214
  const requestConfig = this._enrichAxiosOptions(options);
12180
12215
  try {
@@ -12357,7 +12392,7 @@ class StreamClient {
12357
12392
  });
12358
12393
  };
12359
12394
  this.getUserAgent = () => {
12360
- const version = "1.7.2";
12395
+ const version = "1.7.4";
12361
12396
  return (this.userAgent ||
12362
12397
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
12363
12398
  };
@@ -12440,7 +12475,7 @@ class StreamClient {
12440
12475
  this.browser = inputOptions.browser || typeof window !== 'undefined';
12441
12476
  this.node = !this.browser;
12442
12477
  if (this.browser) {
12443
- this.locationHint = getLocationHint(options?.locationHintUrl, options?.locationHintTimeout);
12478
+ this.locationHint = getLocationHint(options?.locationHintUrl, options?.locationHintTimeout, options?.locationHintMaxAttempts);
12444
12479
  }
12445
12480
  this.options = {
12446
12481
  timeout: 5000,