@stream-io/video-client 0.0.39 → 0.0.40

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
@@ -6868,7 +6868,7 @@ class StreamSfuClient {
6868
6868
  * from this SFU.
6869
6869
  */
6870
6870
  this.isMigratingAway = false;
6871
- this.pingIntervalInMs = 25 * 1000;
6871
+ this.pingIntervalInMs = 10 * 1000;
6872
6872
  this.unhealthyTimeoutInMs = this.pingIntervalInMs + 5 * 1000;
6873
6873
  this.close = (code = 1000, reason = 'Requested signal connection close') => {
6874
6874
  this.signalWs.close(code, reason);
@@ -9104,13 +9104,6 @@ const getClientDetails = () => {
9104
9104
  * An object representation of a `Call`.
9105
9105
  */
9106
9106
  class Call {
9107
- /**
9108
- * A promise that exposes the reconnection logic
9109
- * The use-case is for the react-native platform where online/offline events are not available in the window
9110
- */
9111
- get rejoin() {
9112
- return this.rejoinPromise;
9113
- }
9114
9107
  /**
9115
9108
  * Constructs a new `Call` instance.
9116
9109
  *
@@ -9156,7 +9149,6 @@ class Call {
9156
9149
  if (callingState === exports.CallingState.LEFT) {
9157
9150
  throw new Error('Cannot leave call that has already been left.');
9158
9151
  }
9159
- this.rejoinPromise = undefined;
9160
9152
  if (this.ringing) {
9161
9153
  // I'm the one who started the call, so I should cancel it.
9162
9154
  const hasOtherParticipants = this.state.remoteParticipants.length > 0;
@@ -9360,7 +9352,7 @@ class Call {
9360
9352
  // we shouldn't be republishing the streams if we're migrating
9361
9353
  // as the underlying peer connection will take care of it as part
9362
9354
  // of the ice-restart process
9363
- if (localParticipant && !isReactNative() && !migrate) {
9355
+ if (localParticipant && !migrate) {
9364
9356
  const { audioStream, videoStream, screenShareStream: screenShare, } = localParticipant;
9365
9357
  // restore previous publishing state
9366
9358
  if (audioStream)
@@ -9372,7 +9364,6 @@ class Call {
9372
9364
  }
9373
9365
  this.logger('info', `[Rejoin]: State restored. Attempt: ${this.reconnectAttempts}`);
9374
9366
  });
9375
- this.rejoinPromise = rejoin;
9376
9367
  // reconnect if the connection was closed unexpectedly. example:
9377
9368
  // - SFU crash or restart
9378
9369
  // - network change
@@ -9405,9 +9396,6 @@ class Call {
9405
9396
  if (e.code === KnownCodes.WS_CLOSED_ABRUPTLY &&
9406
9397
  sfuClient.isMigratingAway)
9407
9398
  return;
9408
- // do nothing for react-native as it is handled by SDK
9409
- if (isReactNative())
9410
- return;
9411
9399
  if (this.reconnectAttempts < this.maxReconnectAttempts) {
9412
9400
  rejoin().catch((err) => {
9413
9401
  this.logger('error', `[Rejoin]: Rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
@@ -9421,28 +9409,34 @@ class Call {
9421
9409
  });
9422
9410
  });
9423
9411
  // handlers for connection online/offline events
9424
- // Note: window.addEventListener is not available in React Native, hence the check
9425
- if (typeof window !== 'undefined' && window.addEventListener) {
9426
- const handleOnOffline = () => {
9427
- window.removeEventListener('offline', handleOnOffline);
9428
- this.logger('warn', '[Rejoin]: Going offline...');
9429
- this.state.setCallingState(exports.CallingState.OFFLINE);
9430
- };
9431
- const handleOnOnline = () => {
9432
- window.removeEventListener('online', handleOnOnline);
9433
- if (this.state.callingState === exports.CallingState.OFFLINE) {
9434
- this.logger('info', '[Rejoin]: Going online...');
9435
- rejoin().catch((err) => {
9436
- this.logger('error', `[Rejoin]: Rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
9437
- this.state.setCallingState(exports.CallingState.RECONNECTING_FAILED);
9438
- });
9439
- }
9440
- };
9441
- window.addEventListener('offline', handleOnOffline);
9442
- window.addEventListener('online', handleOnOnline);
9443
- // register cleanup hooks
9444
- this.leaveCallHooks.push(() => window.removeEventListener('offline', handleOnOffline), () => window.removeEventListener('online', handleOnOnline));
9445
- }
9412
+ const unsubscribeOnlineEvent = this.streamClient.on('connection.changed', (e) => {
9413
+ if (e.type !== 'connection.changed')
9414
+ return;
9415
+ if (!e.online)
9416
+ return;
9417
+ unsubscribeOnlineEvent();
9418
+ const currentCallingState = this.state.callingState;
9419
+ if (currentCallingState === exports.CallingState.OFFLINE ||
9420
+ currentCallingState === exports.CallingState.RECONNECTING_FAILED) {
9421
+ this.logger('info', '[Rejoin]: Going online...');
9422
+ rejoin().catch((err) => {
9423
+ this.logger('error', `[Rejoin]: Rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
9424
+ this.state.setCallingState(exports.CallingState.RECONNECTING_FAILED);
9425
+ });
9426
+ }
9427
+ });
9428
+ const unsubscribeOfflineEvent = this.streamClient.on('connection.changed', (e) => {
9429
+ if (e.type !== 'connection.changed')
9430
+ return;
9431
+ if (e.online)
9432
+ return;
9433
+ unsubscribeOfflineEvent();
9434
+ this.state.setCallingState(exports.CallingState.OFFLINE);
9435
+ });
9436
+ this.leaveCallHooks.push(() => {
9437
+ unsubscribeOnlineEvent();
9438
+ unsubscribeOfflineEvent();
9439
+ });
9446
9440
  if (!this.subscriber) {
9447
9441
  this.subscriber = new Subscriber({
9448
9442
  sfuClient,
@@ -10291,6 +10285,9 @@ const isErrorEvent = (res) => res.error !== undefined;
10291
10285
  */
10292
10286
  class StableWSConnection {
10293
10287
  constructor(client) {
10288
+ this._log = (msg, extra = {}, level = 'info') => {
10289
+ this.client.logger(level, 'connection:' + msg, Object.assign({}, extra));
10290
+ };
10294
10291
  this.setClient = (client) => {
10295
10292
  this.client = client;
10296
10293
  };
@@ -10319,7 +10316,8 @@ class StableWSConnection {
10319
10316
  if (event.type === 'offline') {
10320
10317
  // mark the connection as down
10321
10318
  this._log('onlineStatusChanged() - Status changing to offline');
10322
- this._setHealth(false);
10319
+ // we know that the app is offline so dispatch the unhealthy connection event immediately
10320
+ this._setHealth(false, true);
10323
10321
  }
10324
10322
  else if (event.type === 'online') {
10325
10323
  // retry right now...
@@ -10447,13 +10445,14 @@ class StableWSConnection {
10447
10445
  * Broadcasts an event in case the connection status changed.
10448
10446
  *
10449
10447
  * @param {boolean} healthy boolean indicating if the connection is healthy or not
10448
+ * @param {boolean} dispatchImmediately boolean indicating to dispatch event immediately even if the connection is unhealthy
10450
10449
  *
10451
10450
  */
10452
- this._setHealth = (healthy) => {
10451
+ this._setHealth = (healthy, dispatchImmediately = false) => {
10453
10452
  if (healthy === this.isHealthy)
10454
10453
  return;
10455
10454
  this.isHealthy = healthy;
10456
- if (this.isHealthy) {
10455
+ if (this.isHealthy || dispatchImmediately) {
10457
10456
  this.client.dispatchEvent({
10458
10457
  type: 'connection.changed',
10459
10458
  online: this.isHealthy,
@@ -10575,9 +10574,6 @@ class StableWSConnection {
10575
10574
  this.connectionCheckTimeout = this.pingInterval + 10 * 1000;
10576
10575
  addConnectionEventListeners(this.onlineStatusChanged);
10577
10576
  }
10578
- _log(msg, extra = {}, level = 'info') {
10579
- this.client.logger(level, 'connection:' + msg, Object.assign({}, extra));
10580
- }
10581
10577
  /**
10582
10578
  * connect - Connect to the WS URL
10583
10579
  * the default 15s timeout allows between 2~3 tries
@@ -11329,6 +11325,18 @@ class StreamClient {
11329
11325
  constructor(key, options) {
11330
11326
  var _a;
11331
11327
  this.nextRequestAbortController = null;
11328
+ this.devToken = (userID) => {
11329
+ return DevToken(userID);
11330
+ };
11331
+ this.getAuthType = () => {
11332
+ return this.anonymous ? 'anonymous' : 'jwt';
11333
+ };
11334
+ this.setBaseURL = (baseURL) => {
11335
+ this.baseURL = baseURL;
11336
+ this.wsBaseURL = this.baseURL
11337
+ .replace('http', 'ws')
11338
+ .replace(':3030', ':8800');
11339
+ };
11332
11340
  this._getConnectionID = () => { var _a, _b; return ((_a = this.wsConnection) === null || _a === void 0 ? void 0 : _a.connectionID) || ((_b = this.wsFallback) === null || _b === void 0 ? void 0 : _b.connectionID); };
11333
11341
  this._hasConnectionID = () => Boolean(this._getConnectionID());
11334
11342
  /**
@@ -11393,6 +11401,16 @@ class StreamClient {
11393
11401
  }
11394
11402
  });
11395
11403
  this._setToken = (user, userTokenOrProvider, isAnonymous) => this.tokenManager.setTokenOrProvider(userTokenOrProvider, user, isAnonymous);
11404
+ this._setUser = (user) => {
11405
+ /**
11406
+ * This one is used by the frontend. This is a copy of the current user object stored on backend.
11407
+ * It contains reserved properties and own user properties which are not present in `this._user`.
11408
+ */
11409
+ this.user = user;
11410
+ this.userID = user.id;
11411
+ // this one is actually used for requests. This is a copy of current user provided to `connectUser` function.
11412
+ this._user = Object.assign({}, user);
11413
+ };
11396
11414
  /**
11397
11415
  * Disconnects the websocket connection, without removing the user set on client.
11398
11416
  * client.closeConnection will not trigger default auto-retry mechanism for reconnection. You need
@@ -11481,6 +11499,66 @@ class StreamClient {
11481
11499
  // resolve the connection_id here.
11482
11500
  this.resolveConnectionId();
11483
11501
  });
11502
+ /**
11503
+ * on - Listen to events on all channels and users your watching
11504
+ *
11505
+ * client.on('message.new', event => {console.log("my new message", event, channel.state.messages)})
11506
+ * or
11507
+ * client.on(event => {console.log(event.type)})
11508
+ *
11509
+ * @param {EventHandler | string} callbackOrEventName The event type to listen for (optional)
11510
+ * @param {EventHandler} [callbackOrNothing] The callback to call
11511
+ *
11512
+ * @return {Function} Returns a function which, when called, unsubscribes the event handler.
11513
+ */
11514
+ this.on = (callbackOrEventName, callbackOrNothing) => {
11515
+ const key = callbackOrNothing ? callbackOrEventName : 'all';
11516
+ const callback = callbackOrNothing
11517
+ ? callbackOrNothing
11518
+ : callbackOrEventName;
11519
+ if (!(key in this.listeners)) {
11520
+ this.listeners[key] = [];
11521
+ }
11522
+ this.listeners[key].push(callback);
11523
+ return () => {
11524
+ this.off(key, callback);
11525
+ };
11526
+ };
11527
+ /**
11528
+ * off - Remove the event handler
11529
+ *
11530
+ */
11531
+ this.off = (callbackOrEventName, callbackOrNothing) => {
11532
+ const key = callbackOrNothing ? callbackOrEventName : 'all';
11533
+ const callback = callbackOrNothing
11534
+ ? callbackOrNothing
11535
+ : callbackOrEventName;
11536
+ if (!(key in this.listeners)) {
11537
+ this.listeners[key] = [];
11538
+ }
11539
+ this.logger('debug', `Removing listener for ${key} event`);
11540
+ this.listeners[key] = this.listeners[key].filter((value) => value !== callback);
11541
+ };
11542
+ this._logApiRequest = (type, url, data, config) => {
11543
+ this.logger('trace', `client: ${type} - Request - ${url}`, {
11544
+ payload: data,
11545
+ config,
11546
+ });
11547
+ };
11548
+ this._logApiResponse = (type, url, response) => {
11549
+ this.logger('trace', `client:${type} - Response - url: ${url} > status ${response.status}`, {
11550
+ response,
11551
+ });
11552
+ this.logger('trace', `client:${type} - Response payload`, {
11553
+ response,
11554
+ });
11555
+ };
11556
+ this._logApiError = (type, url, error) => {
11557
+ this.logger('error', `client:${type} - Error - url: ${url}`, {
11558
+ url,
11559
+ error,
11560
+ });
11561
+ };
11484
11562
  this.doAxiosRequest = (type, url, data, options = {}) => __awaiter(this, void 0, void 0, function* () {
11485
11563
  var _g;
11486
11564
  if (!options.publicEndpoint || this.user) {
@@ -11545,6 +11623,43 @@ class StreamClient {
11545
11623
  }
11546
11624
  }
11547
11625
  });
11626
+ this.get = (url, params) => {
11627
+ return this.doAxiosRequest('get', url, null, {
11628
+ params,
11629
+ });
11630
+ };
11631
+ this.put = (url, data) => {
11632
+ return this.doAxiosRequest('put', url, data);
11633
+ };
11634
+ this.post = (url, data) => {
11635
+ return this.doAxiosRequest('post', url, data);
11636
+ };
11637
+ this.patch = (url, data) => {
11638
+ return this.doAxiosRequest('patch', url, data);
11639
+ };
11640
+ this.delete = (url, params) => {
11641
+ return this.doAxiosRequest('delete', url, null, {
11642
+ params,
11643
+ });
11644
+ };
11645
+ this.errorFromResponse = (response) => {
11646
+ let err;
11647
+ err = new ErrorFromResponse(`Stream error HTTP code: ${response.status}`);
11648
+ if (response.data && response.data.code) {
11649
+ err = new Error(`Stream error code ${response.data.code}: ${response.data.message}`);
11650
+ err.code = response.data.code;
11651
+ }
11652
+ err.response = response;
11653
+ err.status = response.status;
11654
+ return err;
11655
+ };
11656
+ this.handleResponse = (response) => {
11657
+ const data = response.data;
11658
+ if (isErrorResponse(response)) {
11659
+ throw this.errorFromResponse(response);
11660
+ }
11661
+ return data;
11662
+ };
11548
11663
  this.dispatchEvent = (event) => {
11549
11664
  if (!event.received_at)
11550
11665
  event.received_at = new Date();
@@ -11572,10 +11687,119 @@ class StreamClient {
11572
11687
  listener(event);
11573
11688
  }
11574
11689
  };
11690
+ /**
11691
+ * @private
11692
+ */
11693
+ this.connect = () => __awaiter(this, void 0, void 0, function* () {
11694
+ if (!this.userID || !this._user) {
11695
+ throw Error('Call connectUser or connectAnonymousUser before starting the connection');
11696
+ }
11697
+ if (!this.wsBaseURL) {
11698
+ throw Error('Websocket base url not set');
11699
+ }
11700
+ if (!this.clientID) {
11701
+ throw Error('clientID is not set');
11702
+ }
11703
+ if (!this.wsConnection &&
11704
+ (this.options.warmUp || this.options.enableInsights)) {
11705
+ this._sayHi();
11706
+ }
11707
+ // The StableWSConnection handles all the reconnection logic.
11708
+ if (this.options.wsConnection && this.node) {
11709
+ // Intentionally avoiding adding ts generics on wsConnection in options since its only useful for unit test purpose.
11710
+ this.options.wsConnection.setClient(this);
11711
+ this.wsConnection = this.options
11712
+ .wsConnection;
11713
+ }
11714
+ else {
11715
+ this.wsConnection = new StableWSConnection(this);
11716
+ }
11717
+ try {
11718
+ // if fallback is used before, continue using it instead of waiting for WS to fail
11719
+ if (this.wsFallback) {
11720
+ return yield this.wsFallback.connect();
11721
+ }
11722
+ this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
11723
+ // if WSFallback is enabled, ws connect should timeout faster so fallback can try
11724
+ return yield this.wsConnection.connect(this.options.enableWSFallback
11725
+ ? this.defaultWSTimeoutWithFallback
11726
+ : this.defaultWSTimeout);
11727
+ }
11728
+ catch (err) {
11729
+ // run fallback only if it's WS/Network error and not a normal API error
11730
+ // make sure browser is online before even trying the longpoll
11731
+ if (this.options.enableWSFallback &&
11732
+ // @ts-ignore
11733
+ isWSFailure(err) &&
11734
+ isOnline(this.logger)) {
11735
+ this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
11736
+ this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
11737
+ this.wsConnection._destroyCurrentWSConnection();
11738
+ this.wsConnection.disconnect().then(); // close WS so no retry
11739
+ this.wsFallback = new WSConnectionFallback(this);
11740
+ return yield this.wsFallback.connect();
11741
+ }
11742
+ throw err;
11743
+ }
11744
+ });
11745
+ /**
11746
+ * Check the connectivity with server for warmup purpose.
11747
+ *
11748
+ * @private
11749
+ */
11750
+ this._sayHi = () => {
11751
+ const client_request_id = randomId();
11752
+ const opts = {
11753
+ headers: axios.AxiosHeaders.from({
11754
+ 'x-client-request-id': client_request_id,
11755
+ }),
11756
+ };
11757
+ this.doAxiosRequest('get', this.baseURL + '/hi', null, opts).catch((e) => {
11758
+ if (this.options.enableInsights) {
11759
+ postInsights('http_hi_failed', {
11760
+ api_key: this.key,
11761
+ err: e,
11762
+ client_request_id,
11763
+ });
11764
+ }
11765
+ });
11766
+ };
11767
+ this.getUserAgent = () => {
11768
+ return (this.userAgent ||
11769
+ `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.39"}`);
11770
+ };
11771
+ this.setUserAgent = (userAgent) => {
11772
+ this.userAgent = userAgent;
11773
+ };
11575
11774
  /**
11576
11775
  * _isUsingServerAuth - Returns true if we're using server side auth
11577
11776
  */
11578
11777
  this._isUsingServerAuth = () => !!this.secret;
11778
+ this._enrichAxiosOptions = (options = {
11779
+ params: {},
11780
+ headers: {},
11781
+ config: {},
11782
+ }) => {
11783
+ var _a;
11784
+ const token = options.publicEndpoint && !this.user ? undefined : this._getToken();
11785
+ const authorization = token ? { Authorization: token } : undefined;
11786
+ let signal = null;
11787
+ if (this.nextRequestAbortController !== null) {
11788
+ signal = this.nextRequestAbortController.signal;
11789
+ this.nextRequestAbortController = null;
11790
+ }
11791
+ if (!((_a = options.headers) === null || _a === void 0 ? void 0 : _a['x-client-request-id'])) {
11792
+ options.headers = Object.assign(Object.assign({}, options.headers), { 'x-client-request-id': randomId() });
11793
+ }
11794
+ return Object.assign(Object.assign(Object.assign({ params: Object.assign({ user_id: this.userID, connection_id: this._getConnectionID(), api_key: this.key }, options.params), headers: Object.assign(Object.assign(Object.assign({}, authorization), { 'stream-auth-type': options.publicEndpoint && !this.user
11795
+ ? 'anonymous'
11796
+ : this.getAuthType(), 'X-Stream-Client': this.getUserAgent() }), options.headers) }, (signal ? { signal } : {})), options.config), this.options.axiosRequestConfig);
11797
+ };
11798
+ this._getToken = () => {
11799
+ if (!this.tokenManager)
11800
+ return null;
11801
+ return this.tokenManager.getToken();
11802
+ };
11579
11803
  /**
11580
11804
  * encode ws url payload
11581
11805
  * @private
@@ -11588,6 +11812,38 @@ class StreamClient {
11588
11812
  client_request_id,
11589
11813
  });
11590
11814
  };
11815
+ /**
11816
+ * creates an abort controller that will be used by the next HTTP Request.
11817
+ */
11818
+ this.createAbortControllerForNextRequest = () => {
11819
+ return (this.nextRequestAbortController = new AbortController());
11820
+ };
11821
+ /**
11822
+ * createToken - Creates a token to authenticate this user. This function is used server side.
11823
+ * The resulting token should be passed to the client side when the users registers or logs in.
11824
+ *
11825
+ * @param {string} userID The UserWithId ID
11826
+ * @param {number} [exp] The expiration time for the token expressed in the number of seconds since the epoch
11827
+ * @param call_cids for anonymous tokens you have to provide the call cids the use can join
11828
+ *
11829
+ * @return {string} Returns a token
11830
+ */
11831
+ this.createToken = (userID, exp, iat, call_cids) => {
11832
+ if (this.secret == null) {
11833
+ throw Error(`tokens can only be created server-side using the API Secret`);
11834
+ }
11835
+ const extra = {};
11836
+ if (exp) {
11837
+ extra.exp = exp;
11838
+ }
11839
+ if (iat) {
11840
+ extra.iat = iat;
11841
+ }
11842
+ if (call_cids) {
11843
+ extra.call_cids = call_cids;
11844
+ }
11845
+ return JWTUserToken(this.secret, userID, extra, {});
11846
+ };
11591
11847
  // set the key
11592
11848
  this.key = key;
11593
11849
  this.listeners = {};
@@ -11639,268 +11895,6 @@ class StreamClient {
11639
11895
  ? inputOptions.logger
11640
11896
  : () => null;
11641
11897
  }
11642
- devToken(userID) {
11643
- return DevToken(userID);
11644
- }
11645
- getAuthType() {
11646
- return this.anonymous ? 'anonymous' : 'jwt';
11647
- }
11648
- setBaseURL(baseURL) {
11649
- this.baseURL = baseURL;
11650
- this.wsBaseURL = this.baseURL
11651
- .replace('http', 'ws')
11652
- .replace(':3030', ':8800');
11653
- }
11654
- _setUser(user) {
11655
- /**
11656
- * This one is used by the frontend. This is a copy of the current user object stored on backend.
11657
- * It contains reserved properties and own user properties which are not present in `this._user`.
11658
- */
11659
- this.user = user;
11660
- this.userID = user.id;
11661
- // this one is actually used for requests. This is a copy of current user provided to `connectUser` function.
11662
- this._user = Object.assign({}, user);
11663
- }
11664
- /**
11665
- * on - Listen to events on all channels and users your watching
11666
- *
11667
- * client.on('message.new', event => {console.log("my new message", event, channel.state.messages)})
11668
- * or
11669
- * client.on(event => {console.log(event.type)})
11670
- *
11671
- * @param {EventHandler | string} callbackOrEventName The event type to listen for (optional)
11672
- * @param {EventHandler} [callbackOrNothing] The callback to call
11673
- *
11674
- * @return {Function} Returns a function which, when called, unsubscribes the event handler.
11675
- */
11676
- on(callbackOrEventName, callbackOrNothing) {
11677
- const key = callbackOrNothing ? callbackOrEventName : 'all';
11678
- const callback = callbackOrNothing
11679
- ? callbackOrNothing
11680
- : callbackOrEventName;
11681
- if (!(key in this.listeners)) {
11682
- this.listeners[key] = [];
11683
- }
11684
- this.listeners[key].push(callback);
11685
- return () => {
11686
- this.off(key, callback);
11687
- };
11688
- }
11689
- /**
11690
- * off - Remove the event handler
11691
- *
11692
- */
11693
- off(callbackOrEventName, callbackOrNothing) {
11694
- const key = callbackOrNothing ? callbackOrEventName : 'all';
11695
- const callback = callbackOrNothing
11696
- ? callbackOrNothing
11697
- : callbackOrEventName;
11698
- if (!(key in this.listeners)) {
11699
- this.listeners[key] = [];
11700
- }
11701
- this.logger('debug', `Removing listener for ${key} event`);
11702
- this.listeners[key] = this.listeners[key].filter((value) => value !== callback);
11703
- }
11704
- _logApiRequest(type, url, data, config) {
11705
- this.logger('trace', `client: ${type} - Request - ${url}`, {
11706
- payload: data,
11707
- config,
11708
- });
11709
- }
11710
- _logApiResponse(type, url, response) {
11711
- this.logger('trace', `client:${type} - Response - url: ${url} > status ${response.status}`, {
11712
- response,
11713
- });
11714
- this.logger('trace', `client:${type} - Response payload`, {
11715
- response,
11716
- });
11717
- }
11718
- _logApiError(type, url, error) {
11719
- this.logger('error', `client:${type} - Error - url: ${url}`, {
11720
- url,
11721
- error,
11722
- });
11723
- }
11724
- get(url, params) {
11725
- return this.doAxiosRequest('get', url, null, {
11726
- params,
11727
- });
11728
- }
11729
- put(url, data) {
11730
- return this.doAxiosRequest('put', url, data);
11731
- }
11732
- post(url, data) {
11733
- return this.doAxiosRequest('post', url, data);
11734
- }
11735
- patch(url, data) {
11736
- return this.doAxiosRequest('patch', url, data);
11737
- }
11738
- delete(url, params) {
11739
- return this.doAxiosRequest('delete', url, null, {
11740
- params,
11741
- });
11742
- }
11743
- errorFromResponse(response) {
11744
- let err;
11745
- err = new ErrorFromResponse(`Stream error HTTP code: ${response.status}`);
11746
- if (response.data && response.data.code) {
11747
- err = new Error(`Stream error code ${response.data.code}: ${response.data.message}`);
11748
- err.code = response.data.code;
11749
- }
11750
- err.response = response;
11751
- err.status = response.status;
11752
- return err;
11753
- }
11754
- handleResponse(response) {
11755
- const data = response.data;
11756
- if (isErrorResponse(response)) {
11757
- throw this.errorFromResponse(response);
11758
- }
11759
- return data;
11760
- }
11761
- /**
11762
- * @private
11763
- */
11764
- connect() {
11765
- return __awaiter(this, void 0, void 0, function* () {
11766
- if (!this.userID || !this._user) {
11767
- throw Error('Call connectUser or connectAnonymousUser before starting the connection');
11768
- }
11769
- if (!this.wsBaseURL) {
11770
- throw Error('Websocket base url not set');
11771
- }
11772
- if (!this.clientID) {
11773
- throw Error('clientID is not set');
11774
- }
11775
- if (!this.wsConnection &&
11776
- (this.options.warmUp || this.options.enableInsights)) {
11777
- this._sayHi();
11778
- }
11779
- // The StableWSConnection handles all the reconnection logic.
11780
- if (this.options.wsConnection && this.node) {
11781
- // Intentionally avoiding adding ts generics on wsConnection in options since its only useful for unit test purpose.
11782
- this.options.wsConnection.setClient(this);
11783
- this.wsConnection = this.options
11784
- .wsConnection;
11785
- }
11786
- else {
11787
- this.wsConnection = new StableWSConnection(this);
11788
- }
11789
- try {
11790
- // if fallback is used before, continue using it instead of waiting for WS to fail
11791
- if (this.wsFallback) {
11792
- return yield this.wsFallback.connect();
11793
- }
11794
- this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
11795
- // if WSFallback is enabled, ws connect should timeout faster so fallback can try
11796
- return yield this.wsConnection.connect(this.options.enableWSFallback
11797
- ? this.defaultWSTimeoutWithFallback
11798
- : this.defaultWSTimeout);
11799
- }
11800
- catch (err) {
11801
- // run fallback only if it's WS/Network error and not a normal API error
11802
- // make sure browser is online before even trying the longpoll
11803
- if (this.options.enableWSFallback &&
11804
- // @ts-ignore
11805
- isWSFailure(err) &&
11806
- isOnline(this.logger)) {
11807
- this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
11808
- this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
11809
- this.wsConnection._destroyCurrentWSConnection();
11810
- this.wsConnection.disconnect().then(); // close WS so no retry
11811
- this.wsFallback = new WSConnectionFallback(this);
11812
- return yield this.wsFallback.connect();
11813
- }
11814
- throw err;
11815
- }
11816
- });
11817
- }
11818
- /**
11819
- * Check the connectivity with server for warmup purpose.
11820
- *
11821
- * @private
11822
- */
11823
- _sayHi() {
11824
- const client_request_id = randomId();
11825
- const opts = {
11826
- headers: axios.AxiosHeaders.from({
11827
- 'x-client-request-id': client_request_id,
11828
- }),
11829
- };
11830
- this.doAxiosRequest('get', this.baseURL + '/hi', null, opts).catch((e) => {
11831
- if (this.options.enableInsights) {
11832
- postInsights('http_hi_failed', {
11833
- api_key: this.key,
11834
- err: e,
11835
- client_request_id,
11836
- });
11837
- }
11838
- });
11839
- }
11840
- getUserAgent() {
11841
- return (this.userAgent ||
11842
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.38"}`);
11843
- }
11844
- setUserAgent(userAgent) {
11845
- this.userAgent = userAgent;
11846
- }
11847
- _enrichAxiosOptions(options = {
11848
- params: {},
11849
- headers: {},
11850
- config: {},
11851
- }) {
11852
- var _a;
11853
- const token = options.publicEndpoint && !this.user ? undefined : this._getToken();
11854
- const authorization = token ? { Authorization: token } : undefined;
11855
- let signal = null;
11856
- if (this.nextRequestAbortController !== null) {
11857
- signal = this.nextRequestAbortController.signal;
11858
- this.nextRequestAbortController = null;
11859
- }
11860
- if (!((_a = options.headers) === null || _a === void 0 ? void 0 : _a['x-client-request-id'])) {
11861
- options.headers = Object.assign(Object.assign({}, options.headers), { 'x-client-request-id': randomId() });
11862
- }
11863
- return Object.assign(Object.assign(Object.assign({ params: Object.assign({ user_id: this.userID, connection_id: this._getConnectionID(), api_key: this.key }, options.params), headers: Object.assign(Object.assign(Object.assign({}, authorization), { 'stream-auth-type': options.publicEndpoint && !this.user
11864
- ? 'anonymous'
11865
- : this.getAuthType(), 'X-Stream-Client': this.getUserAgent() }), options.headers) }, (signal ? { signal } : {})), options.config), this.options.axiosRequestConfig);
11866
- }
11867
- _getToken() {
11868
- if (!this.tokenManager)
11869
- return null;
11870
- return this.tokenManager.getToken();
11871
- }
11872
- /**
11873
- * creates an abort controller that will be used by the next HTTP Request.
11874
- */
11875
- createAbortControllerForNextRequest() {
11876
- return (this.nextRequestAbortController = new AbortController());
11877
- }
11878
- /**
11879
- * createToken - Creates a token to authenticate this user. This function is used server side.
11880
- * The resulting token should be passed to the client side when the users registers or logs in.
11881
- *
11882
- * @param {string} userID The UserWithId ID
11883
- * @param {number} [exp] The expiration time for the token expressed in the number of seconds since the epoch
11884
- * @param call_cids for anonymous tokens you have to provide the call cids the use can join
11885
- *
11886
- * @return {string} Returns a token
11887
- */
11888
- createToken(userID, exp, iat, call_cids) {
11889
- if (this.secret == null) {
11890
- throw Error(`tokens can only be created server-side using the API Secret`);
11891
- }
11892
- const extra = {};
11893
- if (exp) {
11894
- extra.exp = exp;
11895
- }
11896
- if (iat) {
11897
- extra.iat = iat;
11898
- }
11899
- if (call_cids) {
11900
- extra.call_cids = call_cids;
11901
- }
11902
- return JWTUserToken(this.secret, userID, extra, {});
11903
- }
11904
11898
  }
11905
11899
 
11906
11900
  /**