@stream-io/video-client 0.0.39 → 0.0.41

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.es.js CHANGED
@@ -6283,7 +6283,7 @@ class Publisher {
6283
6283
  this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
6284
6284
  const { candidate } = e;
6285
6285
  if (!candidate) {
6286
- this.logger('warn', 'null ice candidate');
6286
+ this.logger('debug', 'null ice candidate');
6287
6287
  return;
6288
6288
  }
6289
6289
  yield this.sfuClient.iceTrickle({
@@ -6443,10 +6443,10 @@ class Publisher {
6443
6443
  this.logger('error', `ICE Candidate error`, errorMessage);
6444
6444
  };
6445
6445
  this.onIceConnectionStateChange = () => {
6446
- this.logger('error', `ICE Connection state changed`, this.pc.iceConnectionState);
6446
+ this.logger('debug', `ICE Connection state changed`, this.pc.iceConnectionState);
6447
6447
  };
6448
6448
  this.onIceGatheringStateChange = () => {
6449
- this.logger('error', `ICE Gathering State`, this.pc.iceGatheringState);
6449
+ this.logger('debug', `ICE Gathering State`, this.pc.iceGatheringState);
6450
6450
  };
6451
6451
  this.onSignalingStateChange = () => {
6452
6452
  this.logger('debug', `Signaling state changed`, this.pc.signalingState);
@@ -6613,7 +6613,7 @@ class Subscriber {
6613
6613
  this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
6614
6614
  const { candidate } = e;
6615
6615
  if (!candidate) {
6616
- logger$1('warn', 'null ice candidate');
6616
+ logger$1('debug', 'null ice candidate');
6617
6617
  return;
6618
6618
  }
6619
6619
  yield this.sfuClient.iceTrickle({
@@ -6848,7 +6848,7 @@ class StreamSfuClient {
6848
6848
  * from this SFU.
6849
6849
  */
6850
6850
  this.isMigratingAway = false;
6851
- this.pingIntervalInMs = 25 * 1000;
6851
+ this.pingIntervalInMs = 10 * 1000;
6852
6852
  this.unhealthyTimeoutInMs = this.pingIntervalInMs + 5 * 1000;
6853
6853
  this.close = (code = 1000, reason = 'Requested signal connection close') => {
6854
6854
  this.signalWs.close(code, reason);
@@ -6922,7 +6922,7 @@ class StreamSfuClient {
6922
6922
  if (this.lastMessageTimestamp) {
6923
6923
  const timeSinceLastMessage = new Date().getTime() - this.lastMessageTimestamp.getTime();
6924
6924
  if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
6925
- this.logger('error', 'SFU connection unhealthy, closing');
6925
+ this.logger('debug', 'SFU connection unhealthy, closing');
6926
6926
  this.close(4001, `SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`);
6927
6927
  }
6928
6928
  }
@@ -8029,6 +8029,16 @@ const watchParticipantCountChanged = (dispatcher, state) => {
8029
8029
  }
8030
8030
  });
8031
8031
  };
8032
+ const watchLiveEnded = (dispatcher, call) => {
8033
+ return dispatcher.on('error', (e) => {
8034
+ if (e.eventPayload.oneofKind !== 'error' ||
8035
+ !e.eventPayload.error.error ||
8036
+ e.eventPayload.error.error.code !== ErrorCode.LIVE_ENDED)
8037
+ return;
8038
+ if (!call.permissionsContext.hasPermission(OwnCapability.JOIN_BACKSTAGE))
8039
+ call.leave();
8040
+ });
8041
+ };
8032
8042
  /**
8033
8043
  * Watches and logs the errors reported by the currently connected SFU.
8034
8044
  */
@@ -8418,6 +8428,7 @@ const registerEventHandlers = (call, state, dispatcher) => {
8418
8428
  'call.user_muted': () => console.log('call.user_muted received'),
8419
8429
  };
8420
8430
  const eventHandlers = [
8431
+ watchLiveEnded(dispatcher, call),
8421
8432
  watchSfuErrorReports(dispatcher),
8422
8433
  watchChangePublishQuality(dispatcher, call),
8423
8434
  watchConnectionQualityChanged(dispatcher, state),
@@ -8676,7 +8687,7 @@ const createStatsReporter = ({ subscriber, publisher, state, pollingIntervalInMs
8676
8687
  if (pollingIntervalInMs > 0) {
8677
8688
  const loop = () => __awaiter(void 0, void 0, void 0, function* () {
8678
8689
  yield run().catch((e) => {
8679
- logger('warn', 'Failed to collect stats', e);
8690
+ logger('debug', 'Failed to collect stats', e);
8680
8691
  });
8681
8692
  timeoutId = setTimeout(loop, pollingIntervalInMs);
8682
8693
  });
@@ -9084,13 +9095,6 @@ const getClientDetails = () => {
9084
9095
  * An object representation of a `Call`.
9085
9096
  */
9086
9097
  class Call {
9087
- /**
9088
- * A promise that exposes the reconnection logic
9089
- * The use-case is for the react-native platform where online/offline events are not available in the window
9090
- */
9091
- get rejoin() {
9092
- return this.rejoinPromise;
9093
- }
9094
9098
  /**
9095
9099
  * Constructs a new `Call` instance.
9096
9100
  *
@@ -9136,7 +9140,6 @@ class Call {
9136
9140
  if (callingState === CallingState.LEFT) {
9137
9141
  throw new Error('Cannot leave call that has already been left.');
9138
9142
  }
9139
- this.rejoinPromise = undefined;
9140
9143
  if (this.ringing) {
9141
9144
  // I'm the one who started the call, so I should cancel it.
9142
9145
  const hasOtherParticipants = this.state.remoteParticipants.length > 0;
@@ -9340,7 +9343,7 @@ class Call {
9340
9343
  // we shouldn't be republishing the streams if we're migrating
9341
9344
  // as the underlying peer connection will take care of it as part
9342
9345
  // of the ice-restart process
9343
- if (localParticipant && !isReactNative() && !migrate) {
9346
+ if (localParticipant && !migrate) {
9344
9347
  const { audioStream, videoStream, screenShareStream: screenShare, } = localParticipant;
9345
9348
  // restore previous publishing state
9346
9349
  if (audioStream)
@@ -9352,7 +9355,6 @@ class Call {
9352
9355
  }
9353
9356
  this.logger('info', `[Rejoin]: State restored. Attempt: ${this.reconnectAttempts}`);
9354
9357
  });
9355
- this.rejoinPromise = rejoin;
9356
9358
  // reconnect if the connection was closed unexpectedly. example:
9357
9359
  // - SFU crash or restart
9358
9360
  // - network change
@@ -9385,9 +9387,6 @@ class Call {
9385
9387
  if (e.code === KnownCodes.WS_CLOSED_ABRUPTLY &&
9386
9388
  sfuClient.isMigratingAway)
9387
9389
  return;
9388
- // do nothing for react-native as it is handled by SDK
9389
- if (isReactNative())
9390
- return;
9391
9390
  if (this.reconnectAttempts < this.maxReconnectAttempts) {
9392
9391
  rejoin().catch((err) => {
9393
9392
  this.logger('error', `[Rejoin]: Rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
@@ -9401,28 +9400,34 @@ class Call {
9401
9400
  });
9402
9401
  });
9403
9402
  // handlers for connection online/offline events
9404
- // Note: window.addEventListener is not available in React Native, hence the check
9405
- if (typeof window !== 'undefined' && window.addEventListener) {
9406
- const handleOnOffline = () => {
9407
- window.removeEventListener('offline', handleOnOffline);
9408
- this.logger('warn', '[Rejoin]: Going offline...');
9409
- this.state.setCallingState(CallingState.OFFLINE);
9410
- };
9411
- const handleOnOnline = () => {
9412
- window.removeEventListener('online', handleOnOnline);
9413
- if (this.state.callingState === CallingState.OFFLINE) {
9414
- this.logger('info', '[Rejoin]: Going online...');
9415
- rejoin().catch((err) => {
9416
- this.logger('error', `[Rejoin]: Rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
9417
- this.state.setCallingState(CallingState.RECONNECTING_FAILED);
9418
- });
9419
- }
9420
- };
9421
- window.addEventListener('offline', handleOnOffline);
9422
- window.addEventListener('online', handleOnOnline);
9423
- // register cleanup hooks
9424
- this.leaveCallHooks.push(() => window.removeEventListener('offline', handleOnOffline), () => window.removeEventListener('online', handleOnOnline));
9425
- }
9403
+ const unsubscribeOnlineEvent = this.streamClient.on('connection.changed', (e) => {
9404
+ if (e.type !== 'connection.changed')
9405
+ return;
9406
+ if (!e.online)
9407
+ return;
9408
+ unsubscribeOnlineEvent();
9409
+ const currentCallingState = this.state.callingState;
9410
+ if (currentCallingState === CallingState.OFFLINE ||
9411
+ currentCallingState === CallingState.RECONNECTING_FAILED) {
9412
+ this.logger('info', '[Rejoin]: Going online...');
9413
+ rejoin().catch((err) => {
9414
+ this.logger('error', `[Rejoin]: Rejoin failed for ${this.reconnectAttempts} times. Giving up.`, err);
9415
+ this.state.setCallingState(CallingState.RECONNECTING_FAILED);
9416
+ });
9417
+ }
9418
+ });
9419
+ const unsubscribeOfflineEvent = this.streamClient.on('connection.changed', (e) => {
9420
+ if (e.type !== 'connection.changed')
9421
+ return;
9422
+ if (e.online)
9423
+ return;
9424
+ unsubscribeOfflineEvent();
9425
+ this.state.setCallingState(CallingState.OFFLINE);
9426
+ });
9427
+ this.leaveCallHooks.push(() => {
9428
+ unsubscribeOnlineEvent();
9429
+ unsubscribeOfflineEvent();
9430
+ });
9426
9431
  if (!this.subscriber) {
9427
9432
  this.subscriber = new Subscriber({
9428
9433
  sfuClient,
@@ -10271,6 +10276,9 @@ const isErrorEvent = (res) => res.error !== undefined;
10271
10276
  */
10272
10277
  class StableWSConnection {
10273
10278
  constructor(client) {
10279
+ this._log = (msg, extra = {}, level = 'info') => {
10280
+ this.client.logger(level, 'connection:' + msg, Object.assign({}, extra));
10281
+ };
10274
10282
  this.setClient = (client) => {
10275
10283
  this.client = client;
10276
10284
  };
@@ -10299,7 +10307,8 @@ class StableWSConnection {
10299
10307
  if (event.type === 'offline') {
10300
10308
  // mark the connection as down
10301
10309
  this._log('onlineStatusChanged() - Status changing to offline');
10302
- this._setHealth(false);
10310
+ // we know that the app is offline so dispatch the unhealthy connection event immediately
10311
+ this._setHealth(false, true);
10303
10312
  }
10304
10313
  else if (event.type === 'online') {
10305
10314
  // retry right now...
@@ -10427,13 +10436,14 @@ class StableWSConnection {
10427
10436
  * Broadcasts an event in case the connection status changed.
10428
10437
  *
10429
10438
  * @param {boolean} healthy boolean indicating if the connection is healthy or not
10439
+ * @param {boolean} dispatchImmediately boolean indicating to dispatch event immediately even if the connection is unhealthy
10430
10440
  *
10431
10441
  */
10432
- this._setHealth = (healthy) => {
10442
+ this._setHealth = (healthy, dispatchImmediately = false) => {
10433
10443
  if (healthy === this.isHealthy)
10434
10444
  return;
10435
10445
  this.isHealthy = healthy;
10436
- if (this.isHealthy) {
10446
+ if (this.isHealthy || dispatchImmediately) {
10437
10447
  this.client.dispatchEvent({
10438
10448
  type: 'connection.changed',
10439
10449
  online: this.isHealthy,
@@ -10555,9 +10565,6 @@ class StableWSConnection {
10555
10565
  this.connectionCheckTimeout = this.pingInterval + 10 * 1000;
10556
10566
  addConnectionEventListeners(this.onlineStatusChanged);
10557
10567
  }
10558
- _log(msg, extra = {}, level = 'info') {
10559
- this.client.logger(level, 'connection:' + msg, Object.assign({}, extra));
10560
- }
10561
10568
  /**
10562
10569
  * connect - Connect to the WS URL
10563
10570
  * the default 15s timeout allows between 2~3 tries
@@ -11309,6 +11316,18 @@ class StreamClient {
11309
11316
  constructor(key, options) {
11310
11317
  var _a;
11311
11318
  this.nextRequestAbortController = null;
11319
+ this.devToken = (userID) => {
11320
+ return DevToken(userID);
11321
+ };
11322
+ this.getAuthType = () => {
11323
+ return this.anonymous ? 'anonymous' : 'jwt';
11324
+ };
11325
+ this.setBaseURL = (baseURL) => {
11326
+ this.baseURL = baseURL;
11327
+ this.wsBaseURL = this.baseURL
11328
+ .replace('http', 'ws')
11329
+ .replace(':3030', ':8800');
11330
+ };
11312
11331
  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); };
11313
11332
  this._hasConnectionID = () => Boolean(this._getConnectionID());
11314
11333
  /**
@@ -11373,6 +11392,16 @@ class StreamClient {
11373
11392
  }
11374
11393
  });
11375
11394
  this._setToken = (user, userTokenOrProvider, isAnonymous) => this.tokenManager.setTokenOrProvider(userTokenOrProvider, user, isAnonymous);
11395
+ this._setUser = (user) => {
11396
+ /**
11397
+ * This one is used by the frontend. This is a copy of the current user object stored on backend.
11398
+ * It contains reserved properties and own user properties which are not present in `this._user`.
11399
+ */
11400
+ this.user = user;
11401
+ this.userID = user.id;
11402
+ // this one is actually used for requests. This is a copy of current user provided to `connectUser` function.
11403
+ this._user = Object.assign({}, user);
11404
+ };
11376
11405
  /**
11377
11406
  * Disconnects the websocket connection, without removing the user set on client.
11378
11407
  * client.closeConnection will not trigger default auto-retry mechanism for reconnection. You need
@@ -11461,6 +11490,66 @@ class StreamClient {
11461
11490
  // resolve the connection_id here.
11462
11491
  this.resolveConnectionId();
11463
11492
  });
11493
+ /**
11494
+ * on - Listen to events on all channels and users your watching
11495
+ *
11496
+ * client.on('message.new', event => {console.log("my new message", event, channel.state.messages)})
11497
+ * or
11498
+ * client.on(event => {console.log(event.type)})
11499
+ *
11500
+ * @param {EventHandler | string} callbackOrEventName The event type to listen for (optional)
11501
+ * @param {EventHandler} [callbackOrNothing] The callback to call
11502
+ *
11503
+ * @return {Function} Returns a function which, when called, unsubscribes the event handler.
11504
+ */
11505
+ this.on = (callbackOrEventName, callbackOrNothing) => {
11506
+ const key = callbackOrNothing ? callbackOrEventName : 'all';
11507
+ const callback = callbackOrNothing
11508
+ ? callbackOrNothing
11509
+ : callbackOrEventName;
11510
+ if (!(key in this.listeners)) {
11511
+ this.listeners[key] = [];
11512
+ }
11513
+ this.listeners[key].push(callback);
11514
+ return () => {
11515
+ this.off(key, callback);
11516
+ };
11517
+ };
11518
+ /**
11519
+ * off - Remove the event handler
11520
+ *
11521
+ */
11522
+ this.off = (callbackOrEventName, callbackOrNothing) => {
11523
+ const key = callbackOrNothing ? callbackOrEventName : 'all';
11524
+ const callback = callbackOrNothing
11525
+ ? callbackOrNothing
11526
+ : callbackOrEventName;
11527
+ if (!(key in this.listeners)) {
11528
+ this.listeners[key] = [];
11529
+ }
11530
+ this.logger('debug', `Removing listener for ${key} event`);
11531
+ this.listeners[key] = this.listeners[key].filter((value) => value !== callback);
11532
+ };
11533
+ this._logApiRequest = (type, url, data, config) => {
11534
+ this.logger('trace', `client: ${type} - Request - ${url}`, {
11535
+ payload: data,
11536
+ config,
11537
+ });
11538
+ };
11539
+ this._logApiResponse = (type, url, response) => {
11540
+ this.logger('trace', `client:${type} - Response - url: ${url} > status ${response.status}`, {
11541
+ response,
11542
+ });
11543
+ this.logger('trace', `client:${type} - Response payload`, {
11544
+ response,
11545
+ });
11546
+ };
11547
+ this._logApiError = (type, url, error) => {
11548
+ this.logger('error', `client:${type} - Error - url: ${url}`, {
11549
+ url,
11550
+ error,
11551
+ });
11552
+ };
11464
11553
  this.doAxiosRequest = (type, url, data, options = {}) => __awaiter(this, void 0, void 0, function* () {
11465
11554
  var _g;
11466
11555
  if (!options.publicEndpoint || this.user) {
@@ -11525,6 +11614,43 @@ class StreamClient {
11525
11614
  }
11526
11615
  }
11527
11616
  });
11617
+ this.get = (url, params) => {
11618
+ return this.doAxiosRequest('get', url, null, {
11619
+ params,
11620
+ });
11621
+ };
11622
+ this.put = (url, data) => {
11623
+ return this.doAxiosRequest('put', url, data);
11624
+ };
11625
+ this.post = (url, data) => {
11626
+ return this.doAxiosRequest('post', url, data);
11627
+ };
11628
+ this.patch = (url, data) => {
11629
+ return this.doAxiosRequest('patch', url, data);
11630
+ };
11631
+ this.delete = (url, params) => {
11632
+ return this.doAxiosRequest('delete', url, null, {
11633
+ params,
11634
+ });
11635
+ };
11636
+ this.errorFromResponse = (response) => {
11637
+ let err;
11638
+ err = new ErrorFromResponse(`Stream error HTTP code: ${response.status}`);
11639
+ if (response.data && response.data.code) {
11640
+ err = new Error(`Stream error code ${response.data.code}: ${response.data.message}`);
11641
+ err.code = response.data.code;
11642
+ }
11643
+ err.response = response;
11644
+ err.status = response.status;
11645
+ return err;
11646
+ };
11647
+ this.handleResponse = (response) => {
11648
+ const data = response.data;
11649
+ if (isErrorResponse(response)) {
11650
+ throw this.errorFromResponse(response);
11651
+ }
11652
+ return data;
11653
+ };
11528
11654
  this.dispatchEvent = (event) => {
11529
11655
  if (!event.received_at)
11530
11656
  event.received_at = new Date();
@@ -11552,10 +11678,119 @@ class StreamClient {
11552
11678
  listener(event);
11553
11679
  }
11554
11680
  };
11681
+ /**
11682
+ * @private
11683
+ */
11684
+ this.connect = () => __awaiter(this, void 0, void 0, function* () {
11685
+ if (!this.userID || !this._user) {
11686
+ throw Error('Call connectUser or connectAnonymousUser before starting the connection');
11687
+ }
11688
+ if (!this.wsBaseURL) {
11689
+ throw Error('Websocket base url not set');
11690
+ }
11691
+ if (!this.clientID) {
11692
+ throw Error('clientID is not set');
11693
+ }
11694
+ if (!this.wsConnection &&
11695
+ (this.options.warmUp || this.options.enableInsights)) {
11696
+ this._sayHi();
11697
+ }
11698
+ // The StableWSConnection handles all the reconnection logic.
11699
+ if (this.options.wsConnection && this.node) {
11700
+ // Intentionally avoiding adding ts generics on wsConnection in options since its only useful for unit test purpose.
11701
+ this.options.wsConnection.setClient(this);
11702
+ this.wsConnection = this.options
11703
+ .wsConnection;
11704
+ }
11705
+ else {
11706
+ this.wsConnection = new StableWSConnection(this);
11707
+ }
11708
+ try {
11709
+ // if fallback is used before, continue using it instead of waiting for WS to fail
11710
+ if (this.wsFallback) {
11711
+ return yield this.wsFallback.connect();
11712
+ }
11713
+ this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
11714
+ // if WSFallback is enabled, ws connect should timeout faster so fallback can try
11715
+ return yield this.wsConnection.connect(this.options.enableWSFallback
11716
+ ? this.defaultWSTimeoutWithFallback
11717
+ : this.defaultWSTimeout);
11718
+ }
11719
+ catch (err) {
11720
+ // run fallback only if it's WS/Network error and not a normal API error
11721
+ // make sure browser is online before even trying the longpoll
11722
+ if (this.options.enableWSFallback &&
11723
+ // @ts-ignore
11724
+ isWSFailure(err) &&
11725
+ isOnline(this.logger)) {
11726
+ this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
11727
+ this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
11728
+ this.wsConnection._destroyCurrentWSConnection();
11729
+ this.wsConnection.disconnect().then(); // close WS so no retry
11730
+ this.wsFallback = new WSConnectionFallback(this);
11731
+ return yield this.wsFallback.connect();
11732
+ }
11733
+ throw err;
11734
+ }
11735
+ });
11736
+ /**
11737
+ * Check the connectivity with server for warmup purpose.
11738
+ *
11739
+ * @private
11740
+ */
11741
+ this._sayHi = () => {
11742
+ const client_request_id = randomId();
11743
+ const opts = {
11744
+ headers: AxiosHeaders.from({
11745
+ 'x-client-request-id': client_request_id,
11746
+ }),
11747
+ };
11748
+ this.doAxiosRequest('get', this.baseURL + '/hi', null, opts).catch((e) => {
11749
+ if (this.options.enableInsights) {
11750
+ postInsights('http_hi_failed', {
11751
+ api_key: this.key,
11752
+ err: e,
11753
+ client_request_id,
11754
+ });
11755
+ }
11756
+ });
11757
+ };
11758
+ this.getUserAgent = () => {
11759
+ return (this.userAgent ||
11760
+ `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.40"}`);
11761
+ };
11762
+ this.setUserAgent = (userAgent) => {
11763
+ this.userAgent = userAgent;
11764
+ };
11555
11765
  /**
11556
11766
  * _isUsingServerAuth - Returns true if we're using server side auth
11557
11767
  */
11558
11768
  this._isUsingServerAuth = () => !!this.secret;
11769
+ this._enrichAxiosOptions = (options = {
11770
+ params: {},
11771
+ headers: {},
11772
+ config: {},
11773
+ }) => {
11774
+ var _a;
11775
+ const token = options.publicEndpoint && !this.user ? undefined : this._getToken();
11776
+ const authorization = token ? { Authorization: token } : undefined;
11777
+ let signal = null;
11778
+ if (this.nextRequestAbortController !== null) {
11779
+ signal = this.nextRequestAbortController.signal;
11780
+ this.nextRequestAbortController = null;
11781
+ }
11782
+ if (!((_a = options.headers) === null || _a === void 0 ? void 0 : _a['x-client-request-id'])) {
11783
+ options.headers = Object.assign(Object.assign({}, options.headers), { 'x-client-request-id': randomId() });
11784
+ }
11785
+ 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
11786
+ ? 'anonymous'
11787
+ : this.getAuthType(), 'X-Stream-Client': this.getUserAgent() }), options.headers) }, (signal ? { signal } : {})), options.config), this.options.axiosRequestConfig);
11788
+ };
11789
+ this._getToken = () => {
11790
+ if (!this.tokenManager)
11791
+ return null;
11792
+ return this.tokenManager.getToken();
11793
+ };
11559
11794
  /**
11560
11795
  * encode ws url payload
11561
11796
  * @private
@@ -11568,6 +11803,38 @@ class StreamClient {
11568
11803
  client_request_id,
11569
11804
  });
11570
11805
  };
11806
+ /**
11807
+ * creates an abort controller that will be used by the next HTTP Request.
11808
+ */
11809
+ this.createAbortControllerForNextRequest = () => {
11810
+ return (this.nextRequestAbortController = new AbortController());
11811
+ };
11812
+ /**
11813
+ * createToken - Creates a token to authenticate this user. This function is used server side.
11814
+ * The resulting token should be passed to the client side when the users registers or logs in.
11815
+ *
11816
+ * @param {string} userID The UserWithId ID
11817
+ * @param {number} [exp] The expiration time for the token expressed in the number of seconds since the epoch
11818
+ * @param call_cids for anonymous tokens you have to provide the call cids the use can join
11819
+ *
11820
+ * @return {string} Returns a token
11821
+ */
11822
+ this.createToken = (userID, exp, iat, call_cids) => {
11823
+ if (this.secret == null) {
11824
+ throw Error(`tokens can only be created server-side using the API Secret`);
11825
+ }
11826
+ const extra = {};
11827
+ if (exp) {
11828
+ extra.exp = exp;
11829
+ }
11830
+ if (iat) {
11831
+ extra.iat = iat;
11832
+ }
11833
+ if (call_cids) {
11834
+ extra.call_cids = call_cids;
11835
+ }
11836
+ return JWTUserToken(this.secret, userID, extra, {});
11837
+ };
11571
11838
  // set the key
11572
11839
  this.key = key;
11573
11840
  this.listeners = {};
@@ -11619,268 +11886,6 @@ class StreamClient {
11619
11886
  ? inputOptions.logger
11620
11887
  : () => null;
11621
11888
  }
11622
- devToken(userID) {
11623
- return DevToken(userID);
11624
- }
11625
- getAuthType() {
11626
- return this.anonymous ? 'anonymous' : 'jwt';
11627
- }
11628
- setBaseURL(baseURL) {
11629
- this.baseURL = baseURL;
11630
- this.wsBaseURL = this.baseURL
11631
- .replace('http', 'ws')
11632
- .replace(':3030', ':8800');
11633
- }
11634
- _setUser(user) {
11635
- /**
11636
- * This one is used by the frontend. This is a copy of the current user object stored on backend.
11637
- * It contains reserved properties and own user properties which are not present in `this._user`.
11638
- */
11639
- this.user = user;
11640
- this.userID = user.id;
11641
- // this one is actually used for requests. This is a copy of current user provided to `connectUser` function.
11642
- this._user = Object.assign({}, user);
11643
- }
11644
- /**
11645
- * on - Listen to events on all channels and users your watching
11646
- *
11647
- * client.on('message.new', event => {console.log("my new message", event, channel.state.messages)})
11648
- * or
11649
- * client.on(event => {console.log(event.type)})
11650
- *
11651
- * @param {EventHandler | string} callbackOrEventName The event type to listen for (optional)
11652
- * @param {EventHandler} [callbackOrNothing] The callback to call
11653
- *
11654
- * @return {Function} Returns a function which, when called, unsubscribes the event handler.
11655
- */
11656
- on(callbackOrEventName, callbackOrNothing) {
11657
- const key = callbackOrNothing ? callbackOrEventName : 'all';
11658
- const callback = callbackOrNothing
11659
- ? callbackOrNothing
11660
- : callbackOrEventName;
11661
- if (!(key in this.listeners)) {
11662
- this.listeners[key] = [];
11663
- }
11664
- this.listeners[key].push(callback);
11665
- return () => {
11666
- this.off(key, callback);
11667
- };
11668
- }
11669
- /**
11670
- * off - Remove the event handler
11671
- *
11672
- */
11673
- off(callbackOrEventName, callbackOrNothing) {
11674
- const key = callbackOrNothing ? callbackOrEventName : 'all';
11675
- const callback = callbackOrNothing
11676
- ? callbackOrNothing
11677
- : callbackOrEventName;
11678
- if (!(key in this.listeners)) {
11679
- this.listeners[key] = [];
11680
- }
11681
- this.logger('debug', `Removing listener for ${key} event`);
11682
- this.listeners[key] = this.listeners[key].filter((value) => value !== callback);
11683
- }
11684
- _logApiRequest(type, url, data, config) {
11685
- this.logger('trace', `client: ${type} - Request - ${url}`, {
11686
- payload: data,
11687
- config,
11688
- });
11689
- }
11690
- _logApiResponse(type, url, response) {
11691
- this.logger('trace', `client:${type} - Response - url: ${url} > status ${response.status}`, {
11692
- response,
11693
- });
11694
- this.logger('trace', `client:${type} - Response payload`, {
11695
- response,
11696
- });
11697
- }
11698
- _logApiError(type, url, error) {
11699
- this.logger('error', `client:${type} - Error - url: ${url}`, {
11700
- url,
11701
- error,
11702
- });
11703
- }
11704
- get(url, params) {
11705
- return this.doAxiosRequest('get', url, null, {
11706
- params,
11707
- });
11708
- }
11709
- put(url, data) {
11710
- return this.doAxiosRequest('put', url, data);
11711
- }
11712
- post(url, data) {
11713
- return this.doAxiosRequest('post', url, data);
11714
- }
11715
- patch(url, data) {
11716
- return this.doAxiosRequest('patch', url, data);
11717
- }
11718
- delete(url, params) {
11719
- return this.doAxiosRequest('delete', url, null, {
11720
- params,
11721
- });
11722
- }
11723
- errorFromResponse(response) {
11724
- let err;
11725
- err = new ErrorFromResponse(`Stream error HTTP code: ${response.status}`);
11726
- if (response.data && response.data.code) {
11727
- err = new Error(`Stream error code ${response.data.code}: ${response.data.message}`);
11728
- err.code = response.data.code;
11729
- }
11730
- err.response = response;
11731
- err.status = response.status;
11732
- return err;
11733
- }
11734
- handleResponse(response) {
11735
- const data = response.data;
11736
- if (isErrorResponse(response)) {
11737
- throw this.errorFromResponse(response);
11738
- }
11739
- return data;
11740
- }
11741
- /**
11742
- * @private
11743
- */
11744
- connect() {
11745
- return __awaiter(this, void 0, void 0, function* () {
11746
- if (!this.userID || !this._user) {
11747
- throw Error('Call connectUser or connectAnonymousUser before starting the connection');
11748
- }
11749
- if (!this.wsBaseURL) {
11750
- throw Error('Websocket base url not set');
11751
- }
11752
- if (!this.clientID) {
11753
- throw Error('clientID is not set');
11754
- }
11755
- if (!this.wsConnection &&
11756
- (this.options.warmUp || this.options.enableInsights)) {
11757
- this._sayHi();
11758
- }
11759
- // The StableWSConnection handles all the reconnection logic.
11760
- if (this.options.wsConnection && this.node) {
11761
- // Intentionally avoiding adding ts generics on wsConnection in options since its only useful for unit test purpose.
11762
- this.options.wsConnection.setClient(this);
11763
- this.wsConnection = this.options
11764
- .wsConnection;
11765
- }
11766
- else {
11767
- this.wsConnection = new StableWSConnection(this);
11768
- }
11769
- try {
11770
- // if fallback is used before, continue using it instead of waiting for WS to fail
11771
- if (this.wsFallback) {
11772
- return yield this.wsFallback.connect();
11773
- }
11774
- this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
11775
- // if WSFallback is enabled, ws connect should timeout faster so fallback can try
11776
- return yield this.wsConnection.connect(this.options.enableWSFallback
11777
- ? this.defaultWSTimeoutWithFallback
11778
- : this.defaultWSTimeout);
11779
- }
11780
- catch (err) {
11781
- // run fallback only if it's WS/Network error and not a normal API error
11782
- // make sure browser is online before even trying the longpoll
11783
- if (this.options.enableWSFallback &&
11784
- // @ts-ignore
11785
- isWSFailure(err) &&
11786
- isOnline(this.logger)) {
11787
- this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
11788
- this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
11789
- this.wsConnection._destroyCurrentWSConnection();
11790
- this.wsConnection.disconnect().then(); // close WS so no retry
11791
- this.wsFallback = new WSConnectionFallback(this);
11792
- return yield this.wsFallback.connect();
11793
- }
11794
- throw err;
11795
- }
11796
- });
11797
- }
11798
- /**
11799
- * Check the connectivity with server for warmup purpose.
11800
- *
11801
- * @private
11802
- */
11803
- _sayHi() {
11804
- const client_request_id = randomId();
11805
- const opts = {
11806
- headers: AxiosHeaders.from({
11807
- 'x-client-request-id': client_request_id,
11808
- }),
11809
- };
11810
- this.doAxiosRequest('get', this.baseURL + '/hi', null, opts).catch((e) => {
11811
- if (this.options.enableInsights) {
11812
- postInsights('http_hi_failed', {
11813
- api_key: this.key,
11814
- err: e,
11815
- client_request_id,
11816
- });
11817
- }
11818
- });
11819
- }
11820
- getUserAgent() {
11821
- return (this.userAgent ||
11822
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.38"}`);
11823
- }
11824
- setUserAgent(userAgent) {
11825
- this.userAgent = userAgent;
11826
- }
11827
- _enrichAxiosOptions(options = {
11828
- params: {},
11829
- headers: {},
11830
- config: {},
11831
- }) {
11832
- var _a;
11833
- const token = options.publicEndpoint && !this.user ? undefined : this._getToken();
11834
- const authorization = token ? { Authorization: token } : undefined;
11835
- let signal = null;
11836
- if (this.nextRequestAbortController !== null) {
11837
- signal = this.nextRequestAbortController.signal;
11838
- this.nextRequestAbortController = null;
11839
- }
11840
- if (!((_a = options.headers) === null || _a === void 0 ? void 0 : _a['x-client-request-id'])) {
11841
- options.headers = Object.assign(Object.assign({}, options.headers), { 'x-client-request-id': randomId() });
11842
- }
11843
- 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
11844
- ? 'anonymous'
11845
- : this.getAuthType(), 'X-Stream-Client': this.getUserAgent() }), options.headers) }, (signal ? { signal } : {})), options.config), this.options.axiosRequestConfig);
11846
- }
11847
- _getToken() {
11848
- if (!this.tokenManager)
11849
- return null;
11850
- return this.tokenManager.getToken();
11851
- }
11852
- /**
11853
- * creates an abort controller that will be used by the next HTTP Request.
11854
- */
11855
- createAbortControllerForNextRequest() {
11856
- return (this.nextRequestAbortController = new AbortController());
11857
- }
11858
- /**
11859
- * createToken - Creates a token to authenticate this user. This function is used server side.
11860
- * The resulting token should be passed to the client side when the users registers or logs in.
11861
- *
11862
- * @param {string} userID The UserWithId ID
11863
- * @param {number} [exp] The expiration time for the token expressed in the number of seconds since the epoch
11864
- * @param call_cids for anonymous tokens you have to provide the call cids the use can join
11865
- *
11866
- * @return {string} Returns a token
11867
- */
11868
- createToken(userID, exp, iat, call_cids) {
11869
- if (this.secret == null) {
11870
- throw Error(`tokens can only be created server-side using the API Secret`);
11871
- }
11872
- const extra = {};
11873
- if (exp) {
11874
- extra.exp = exp;
11875
- }
11876
- if (iat) {
11877
- extra.iat = iat;
11878
- }
11879
- if (call_cids) {
11880
- extra.call_cids = call_cids;
11881
- }
11882
- return JWTUserToken(this.secret, userID, extra, {});
11883
- }
11884
11889
  }
11885
11890
 
11886
11891
  /**
@@ -12177,7 +12182,7 @@ class StreamVideoClient {
12177
12182
  return;
12178
12183
  const { call, members } = event;
12179
12184
  if (userToConnect.id === call.created_by.id) {
12180
- this.logger('warn', 'Received `call.ring` sent by the current user');
12185
+ this.logger('debug', 'Received `call.ring` sent by the current user so ignoring the event');
12181
12186
  return;
12182
12187
  }
12183
12188
  // The call might already be tracked by the client,