@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/CHANGELOG.md +14 -0
- package/dist/index.browser.es.js +71 -36
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +71 -36
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +71 -36
- package/dist/index.es.js.map +1 -1
- package/dist/src/coordinator/connection/client.d.ts +4 -0
- package/dist/src/coordinator/connection/location.d.ts +1 -1
- package/dist/src/coordinator/connection/types.d.ts +4 -0
- package/dist/src/coordinator/connection/utils.d.ts +4 -0
- package/package.json +1 -1
- package/src/__tests__/Call.test.ts +40 -0
- package/src/coordinator/connection/client.ts +26 -13
- package/src/coordinator/connection/connection.ts +11 -0
- package/src/coordinator/connection/location.ts +28 -22
- package/src/coordinator/connection/types.ts +4 -0
- package/src/coordinator/connection/utils.ts +11 -0
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
11914
|
-
const
|
|
11915
|
-
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
const
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
11924
|
-
|
|
11925
|
-
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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,
|