@stream-io/video-client 0.0.13 → 0.0.15

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 (45) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/index.browser.es.js +237 -130
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +239 -129
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.es.js +237 -130
  8. package/dist/index.es.js.map +1 -1
  9. package/dist/src/Call.d.ts +2 -1
  10. package/dist/src/StreamSfuClient.d.ts +1 -0
  11. package/dist/src/StreamVideoClient.d.ts +5 -1
  12. package/dist/src/coordinator/connection/types.d.ts +3 -2
  13. package/dist/src/coordinator/connection/utils.d.ts +2 -1
  14. package/dist/src/logger.d.ts +4 -0
  15. package/dist/src/rtc/Dispatcher.d.ts +2 -0
  16. package/dist/src/rtc/IceTrickleBuffer.d.ts +2 -0
  17. package/dist/src/rtc/publisher.d.ts +1 -0
  18. package/dist/src/store/CallState.d.ts +2 -0
  19. package/dist/src/types.d.ts +1 -1
  20. package/index.ts +1 -0
  21. package/package.json +1 -1
  22. package/src/Call.ts +69 -42
  23. package/src/StreamSfuClient.ts +70 -29
  24. package/src/StreamVideoClient.ts +46 -3
  25. package/src/coordinator/connection/client.ts +22 -29
  26. package/src/coordinator/connection/connection.ts +2 -3
  27. package/src/coordinator/connection/connection_fallback.ts +0 -1
  28. package/src/coordinator/connection/types.ts +4 -2
  29. package/src/coordinator/connection/utils.ts +5 -2
  30. package/src/devices/devices.ts +10 -3
  31. package/src/events/__tests__/call-permissions.test.ts +2 -2
  32. package/src/events/call.ts +11 -4
  33. package/src/events/sessions.ts +7 -2
  34. package/src/logger.ts +45 -0
  35. package/src/rtc/Dispatcher.ts +14 -4
  36. package/src/rtc/IceTrickleBuffer.ts +8 -1
  37. package/src/rtc/__tests__/publisher.test.ts +1 -1
  38. package/src/rtc/codecs.ts +7 -5
  39. package/src/rtc/flows/join.ts +4 -1
  40. package/src/rtc/publisher.ts +31 -12
  41. package/src/rtc/signal.ts +8 -7
  42. package/src/rtc/subscriber.ts +16 -10
  43. package/src/stats/state-store-stats-reporter.ts +12 -4
  44. package/src/store/CallState.ts +7 -2
  45. package/src/types.ts +3 -2
@@ -4246,7 +4246,7 @@ var DebounceType;
4246
4246
  DebounceType[DebounceType["SLOW"] = 1200] = "SLOW";
4247
4247
  })(DebounceType || (DebounceType = {}));
4248
4248
  const isStreamVideoLocalParticipant = (p) => {
4249
- return !!p.isLoggedInUser;
4249
+ return !!p.isLocalParticipant;
4250
4250
  };
4251
4251
 
4252
4252
  /******************************************************************************
@@ -5273,13 +5273,41 @@ const toggleDtx = (sdp, enable) => {
5273
5273
  return sdp;
5274
5274
  };
5275
5275
 
5276
+ let logger;
5277
+ const logToConsole = (logLevel, message, extraData, tags) => {
5278
+ let logMethod;
5279
+ if (logLevel === 'error') {
5280
+ logMethod = console.error;
5281
+ }
5282
+ else if (logLevel === 'warn') {
5283
+ logMethod = console.warn;
5284
+ }
5285
+ else {
5286
+ logMethod = console.log;
5287
+ }
5288
+ logMethod(logLevel, `${tags === null || tags === void 0 ? void 0 : tags.join(':')} - ${message}`, extraData ? extraData : '');
5289
+ };
5290
+ const setLogger = (l) => {
5291
+ logger = l;
5292
+ };
5293
+ const getLogger = (withTags) => {
5294
+ const loggerMethod = logger || (() => { });
5295
+ const result = (logLevel, messeage, extraData, tags) => {
5296
+ loggerMethod(logLevel, messeage, extraData, [
5297
+ ...(tags || []),
5298
+ ...(withTags || []),
5299
+ ]);
5300
+ };
5301
+ return result;
5302
+ };
5303
+
5276
5304
  const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
5305
+ const logger = getLogger(['codecs']);
5277
5306
  if (!('getCapabilities' in RTCRtpSender)) {
5278
- console.warn('RTCRtpSender.getCapabilities is not supported');
5307
+ logger === null || logger === void 0 ? void 0 : logger('warn', 'RTCRtpSender.getCapabilities is not supported');
5279
5308
  return;
5280
5309
  }
5281
5310
  const cap = RTCRtpSender.getCapabilities(kind);
5282
- console.log('s4e');
5283
5311
  if (!cap)
5284
5312
  return;
5285
5313
  const matched = [];
@@ -5287,7 +5315,7 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
5287
5315
  const unmatched = [];
5288
5316
  cap.codecs.forEach((c) => {
5289
5317
  const codec = c.mimeType.toLowerCase();
5290
- console.log(c);
5318
+ logger === null || logger === void 0 ? void 0 : logger('debug', `Found supported codec: ${codec}`);
5291
5319
  const shouldRemoveCodec = codecToRemove && codec === `${kind}/${codecToRemove}`;
5292
5320
  if (shouldRemoveCodec)
5293
5321
  return;
@@ -5307,10 +5335,11 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
5307
5335
  }
5308
5336
  return;
5309
5337
  }
5310
- console.log('matched', matched);
5311
5338
  matched.push(c);
5312
5339
  });
5313
- return [...matched, ...partialMatched, ...unmatched];
5340
+ const result = [...matched, ...partialMatched, ...unmatched];
5341
+ logger === null || logger === void 0 ? void 0 : logger('info', `Preffered codecs: `, result);
5342
+ return result;
5314
5343
  };
5315
5344
  const getGenericSdp = (direction, isRedEnabled, preferredVideoCodec) => __awaiter(void 0, void 0, void 0, function* () {
5316
5345
  var _a;
@@ -5376,17 +5405,19 @@ class Dispatcher {
5376
5405
  constructor() {
5377
5406
  this.subscribers = {};
5378
5407
  this.dispatch = (message) => {
5408
+ var _a, _b;
5379
5409
  const eventKind = message.eventPayload.oneofKind;
5380
5410
  if (eventKind) {
5381
- // @ts-ignore
5382
- console.log(`Dispatching`, eventKind, message.eventPayload[eventKind]);
5411
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'info', `Dispatching ${eventKind}`);
5412
+ (_b = this.logger) === null || _b === void 0 ? void 0 : _b.call(this, 'debug', `Event payload`, message.eventPayload[eventKind]);
5383
5413
  const listeners = this.subscribers[eventKind];
5384
5414
  listeners === null || listeners === void 0 ? void 0 : listeners.forEach((fn) => {
5415
+ var _a;
5385
5416
  try {
5386
5417
  fn(message);
5387
5418
  }
5388
5419
  catch (e) {
5389
- console.warn(`Listener failed with error`, e);
5420
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'warn', 'Listener failed with error', e);
5390
5421
  }
5391
5422
  });
5392
5423
  }
@@ -5410,6 +5441,7 @@ class Dispatcher {
5410
5441
  this.subscribers = {};
5411
5442
  }
5412
5443
  };
5444
+ this.logger = getLogger(['sfu-client']);
5413
5445
  }
5414
5446
  }
5415
5447
 
@@ -5422,6 +5454,7 @@ class IceTrickleBuffer {
5422
5454
  this.subscriberCandidates = new ReplaySubject();
5423
5455
  this.publisherCandidates = new ReplaySubject();
5424
5456
  this.push = (iceTrickle) => {
5457
+ var _a;
5425
5458
  if (iceTrickle.peerType === PeerType.SUBSCRIBER) {
5426
5459
  this.subscriberCandidates.next(iceTrickle);
5427
5460
  }
@@ -5429,9 +5462,10 @@ class IceTrickleBuffer {
5429
5462
  this.publisherCandidates.next(iceTrickle);
5430
5463
  }
5431
5464
  else {
5432
- console.warn(`ICETrickle, Unknown peer type`, iceTrickle);
5465
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'warn', `ICETrickle, Unknown peer type`, iceTrickle);
5433
5466
  }
5434
5467
  };
5468
+ this.logger = getLogger(['sfu-client']);
5435
5469
  }
5436
5470
  }
5437
5471
 
@@ -5622,6 +5656,7 @@ class Publisher {
5622
5656
  * @param opts
5623
5657
  */
5624
5658
  this.publishStream = (mediaStream, track, trackType, opts = {}) => __awaiter(this, void 0, void 0, function* () {
5659
+ var _a;
5625
5660
  let transceiver = this.publisher
5626
5661
  .getTransceivers()
5627
5662
  .find((t) => {
@@ -5635,7 +5670,8 @@ class Publisher {
5635
5670
  * Once the track has ended, it will notify the SFU and update the state.
5636
5671
  */
5637
5672
  const handleTrackEnded = () => __awaiter(this, void 0, void 0, function* () {
5638
- console.log(`Track ${TrackType[trackType]} has ended, notifying the SFU`);
5673
+ var _b;
5674
+ (_b = this.logger) === null || _b === void 0 ? void 0 : _b.call(this, 'info', `Track ${TrackType[trackType]} has ended, notifying the SFU`);
5639
5675
  yield this.notifyTrackMuteStateChanged(mediaStream, track, trackType, true);
5640
5676
  // clean-up, this event listener needs to run only once.
5641
5677
  track.removeEventListener('ended', handleTrackEnded);
@@ -5660,7 +5696,7 @@ class Publisher {
5660
5696
  });
5661
5697
  this.transceiverRegistry[trackType] = transceiver;
5662
5698
  if ('setCodecPreferences' in transceiver && codecPreferences) {
5663
- console.log(`Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
5699
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
5664
5700
  transceiver.setCodecPreferences(codecPreferences);
5665
5701
  }
5666
5702
  }
@@ -5744,9 +5780,9 @@ class Publisher {
5744
5780
  this.publisher.close();
5745
5781
  };
5746
5782
  this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
5747
- var _a;
5748
- console.log('Update publish quality, requested rids by SFU:', enabledRids);
5749
- const videoSender = (_a = this.transceiverRegistry[TrackType.VIDEO]) === null || _a === void 0 ? void 0 : _a.sender;
5783
+ var _c, _d, _e, _f;
5784
+ (_c = this.logger) === null || _c === void 0 ? void 0 : _c.call(this, 'info', 'Update publish quality, requested rids by SFU:', enabledRids);
5785
+ const videoSender = (_d = this.transceiverRegistry[TrackType.VIDEO]) === null || _d === void 0 ? void 0 : _d.sender;
5750
5786
  if (!videoSender)
5751
5787
  return;
5752
5788
  const params = videoSender.getParameters();
@@ -5761,10 +5797,10 @@ class Publisher {
5761
5797
  });
5762
5798
  if (changed) {
5763
5799
  if (params.encodings.length === 0) {
5764
- console.warn('No suitable video encoding quality found');
5800
+ (_e = this.logger) === null || _e === void 0 ? void 0 : _e.call(this, 'warn', 'No suitable video encoding quality found');
5765
5801
  }
5766
5802
  yield videoSender.setParameters(params);
5767
- console.log(`Update publish quality, enabled rids: ${params.encodings
5803
+ (_f = this.logger) === null || _f === void 0 ? void 0 : _f.call(this, 'info', `Update publish quality, enabled rids: ${params.encodings
5768
5804
  .filter((e) => e.active)
5769
5805
  .map((e) => e.rid)
5770
5806
  .join(', ')}`);
@@ -5781,9 +5817,10 @@ class Publisher {
5781
5817
  }
5782
5818
  };
5783
5819
  this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
5820
+ var _g;
5784
5821
  const { candidate } = e;
5785
5822
  if (!candidate) {
5786
- console.log('null ice candidate');
5823
+ (_g = this.logger) === null || _g === void 0 ? void 0 : _g.call(this, 'warn', 'null ice candidate');
5787
5824
  return;
5788
5825
  }
5789
5826
  yield this.sfuClient.iceTrickle({
@@ -5792,7 +5829,8 @@ class Publisher {
5792
5829
  });
5793
5830
  });
5794
5831
  this.onNegotiationNeeded = () => __awaiter(this, void 0, void 0, function* () {
5795
- console.log('AAA onNegotiationNeeded');
5832
+ var _h, _j;
5833
+ (_h = this.logger) === null || _h === void 0 ? void 0 : _h.call(this, 'info', 'AAA onNegotiationNeeded');
5796
5834
  const offer = yield this.publisher.createOffer();
5797
5835
  let sdp = offer.sdp;
5798
5836
  if (sdp) {
@@ -5855,28 +5893,38 @@ class Publisher {
5855
5893
  });
5856
5894
  }
5857
5895
  catch (e) {
5858
- console.error(`Publisher: setRemoteDescription error`, response.sdp, e);
5896
+ (_j = this.logger) === null || _j === void 0 ? void 0 : _j.call(this, 'error', `Publisher: setRemoteDescription error`, {
5897
+ sdp: response.sdp,
5898
+ error: e,
5899
+ });
5859
5900
  }
5860
5901
  this.sfuClient.iceTrickleBuffer.publisherCandidates.subscribe((candidate) => __awaiter(this, void 0, void 0, function* () {
5902
+ var _k;
5861
5903
  try {
5862
5904
  const iceCandidate = JSON.parse(candidate.iceCandidate);
5863
5905
  yield this.publisher.addIceCandidate(iceCandidate);
5864
5906
  }
5865
5907
  catch (e) {
5866
- console.error(`Publisher: ICE candidate error`, e, candidate);
5908
+ (_k = this.logger) === null || _k === void 0 ? void 0 : _k.call(this, 'error', `Publisher: ICE candidate error`, {
5909
+ error: e,
5910
+ candidate,
5911
+ });
5867
5912
  }
5868
5913
  }));
5869
5914
  });
5870
5915
  this.onIceCandidateError = (e) => {
5916
+ var _a;
5871
5917
  const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
5872
5918
  `${e.errorCode}: ${e.errorText}`;
5873
- console.error(`Publisher: ICE Candidate error`, errorMessage);
5919
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Candidate error`, errorMessage);
5874
5920
  };
5875
5921
  this.onIceConnectionStateChange = () => {
5876
- console.log(`Publisher: ICE Connection state changed`, this.publisher.iceConnectionState);
5922
+ var _a;
5923
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Connection state changed`, this.publisher.iceConnectionState);
5877
5924
  };
5878
5925
  this.onIceGatheringStateChange = () => {
5879
- console.log(`Publisher: ICE Gathering State`, this.publisher.iceGatheringState);
5926
+ var _a;
5927
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Gathering State`, this.publisher.iceGatheringState);
5880
5928
  };
5881
5929
  this.ridToVideoQuality = (rid) => {
5882
5930
  return rid === 'q'
@@ -5909,12 +5957,13 @@ class Publisher {
5909
5957
  }
5910
5958
 
5911
5959
  const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, }) => {
5960
+ const logger = getLogger(['sfu-client']);
5912
5961
  const subscriber = new RTCPeerConnection(connectionConfig);
5913
5962
  attachDebugEventListeners(subscriber);
5914
5963
  subscriber.addEventListener('icecandidate', (e) => __awaiter(void 0, void 0, void 0, function* () {
5915
5964
  const { candidate } = e;
5916
5965
  if (!candidate) {
5917
- console.log('null ice candidate');
5966
+ logger === null || logger === void 0 ? void 0 : logger('warn', 'null ice candidate');
5918
5967
  return;
5919
5968
  }
5920
5969
  yield sfuClient.iceTrickle({
@@ -5930,7 +5979,7 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
5930
5979
  if (message.eventPayload.oneofKind !== 'subscriberOffer')
5931
5980
  return;
5932
5981
  const { subscriberOffer } = message.eventPayload;
5933
- console.log(`Received subscriberOffer`, subscriberOffer);
5982
+ logger === null || logger === void 0 ? void 0 : logger('info', 'Received subscriberOffer', subscriberOffer);
5934
5983
  yield subscriber.setRemoteDescription({
5935
5984
  type: 'offer',
5936
5985
  sdp: subscriberOffer.sdp,
@@ -5941,7 +5990,10 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
5941
5990
  yield subscriber.addIceCandidate(iceCandidate);
5942
5991
  }
5943
5992
  catch (e) {
5944
- console.error(`Subscriber: ICE candidate error`, e, candidate);
5993
+ logger === null || logger === void 0 ? void 0 : logger('error', `Subscriber: ICE candidate error`, {
5994
+ error: e,
5995
+ candidate,
5996
+ });
5945
5997
  }
5946
5998
  }));
5947
5999
  // apply ice candidates
@@ -5964,31 +6016,33 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
5964
6016
  return subscriber;
5965
6017
  };
5966
6018
  const attachDebugEventListeners = (subscriber) => {
6019
+ const logger = getLogger(['sfu-client']);
5967
6020
  subscriber.addEventListener('icecandidateerror', (e) => {
5968
6021
  const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
5969
6022
  `${e.errorCode}: ${e.errorText}`;
5970
- console.error(`Subscriber: ICE Candidate error`, errorMessage);
6023
+ logger === null || logger === void 0 ? void 0 : logger('error', `Subscriber: ICE Candidate error: ${errorMessage}`);
5971
6024
  });
5972
6025
  subscriber.addEventListener('iceconnectionstatechange', () => {
5973
- console.log(`Subscriber: ICE Connection state changed`, subscriber.iceConnectionState);
6026
+ logger === null || logger === void 0 ? void 0 : logger('info', `Subscriber: ICE Connection state changed: ${subscriber.iceConnectionState}`);
5974
6027
  });
5975
6028
  subscriber.addEventListener('icegatheringstatechange', () => {
5976
- console.log(`Subscriber: ICE Gathering State`, subscriber.iceGatheringState);
6029
+ logger === null || logger === void 0 ? void 0 : logger('info', `Subscriber: ICE Gathering State: ${subscriber.iceGatheringState}`);
5977
6030
  });
5978
6031
  };
5979
6032
 
5980
6033
  const createWebSocketSignalChannel = (opts) => {
6034
+ const logger = getLogger(['sfu-client']);
5981
6035
  const { endpoint, onMessage } = opts;
5982
6036
  const ws = new WebSocket(endpoint);
5983
6037
  ws.binaryType = 'arraybuffer'; // do we need this?
5984
6038
  ws.addEventListener('error', (e) => {
5985
- console.log('Signaling WS channel error', e);
6039
+ logger === null || logger === void 0 ? void 0 : logger('error', 'Signaling WS channel error', e);
5986
6040
  });
5987
6041
  ws.addEventListener('close', (e) => {
5988
- console.log('Signaling WS channel is closed', e);
6042
+ logger === null || logger === void 0 ? void 0 : logger('info', 'Signaling WS channel is closed', e);
5989
6043
  });
5990
6044
  ws.addEventListener('open', (e) => {
5991
- console.log('Signaling WS channel is open', e);
6045
+ logger === null || logger === void 0 ? void 0 : logger('info', 'Signaling WS channel is open', e);
5992
6046
  });
5993
6047
  if (onMessage) {
5994
6048
  ws.addEventListener('message', (e) => {
@@ -5999,7 +6053,7 @@ const createWebSocketSignalChannel = (opts) => {
5999
6053
  onMessage(message);
6000
6054
  }
6001
6055
  catch (err) {
6002
- console.error('Failed to decode a message. Check whether the Proto models match.', e.data, e, err);
6056
+ logger === null || logger === void 0 ? void 0 : logger('error', 'Failed to decode a message. Check whether the Proto models match.', { event: e, error: err });
6003
6057
  }
6004
6058
  });
6005
6059
  }
@@ -6100,14 +6154,14 @@ function convertErrorToJson(err) {
6100
6154
  * isOnline safely return the navigator.online value for browser env
6101
6155
  * if navigator is not in global object, it always return true
6102
6156
  */
6103
- function isOnline() {
6157
+ function isOnline(logger) {
6104
6158
  const nav = typeof navigator !== 'undefined'
6105
6159
  ? navigator
6106
6160
  : typeof window !== 'undefined' && window.navigator
6107
6161
  ? window.navigator
6108
6162
  : undefined;
6109
6163
  if (!nav) {
6110
- console.warn('isOnline failed to access window.navigator and assume browser is online');
6164
+ logger('warn', 'isOnline failed to access window.navigator and assume browser is online');
6111
6165
  return true;
6112
6166
  }
6113
6167
  // RN navigator has undefined for onLine
@@ -6163,16 +6217,16 @@ class StreamSfuClient {
6163
6217
  return retryable(() => this.rpc.updateSubscriptions({
6164
6218
  sessionId: this.sessionId,
6165
6219
  tracks: subscriptions,
6166
- }));
6220
+ }), this.logger);
6167
6221
  });
6168
6222
  this.setPublisher = (data) => __awaiter(this, void 0, void 0, function* () {
6169
- return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
6223
+ return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6170
6224
  });
6171
6225
  this.sendAnswer = (data) => __awaiter(this, void 0, void 0, function* () {
6172
- return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
6226
+ return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6173
6227
  });
6174
6228
  this.iceTrickle = (data) => __awaiter(this, void 0, void 0, function* () {
6175
- return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
6229
+ return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6176
6230
  });
6177
6231
  this.updateMuteState = (trackType, muted) => __awaiter(this, void 0, void 0, function* () {
6178
6232
  return this.updateMuteStates({
@@ -6185,7 +6239,7 @@ class StreamSfuClient {
6185
6239
  });
6186
6240
  });
6187
6241
  this.updateMuteStates = (data) => __awaiter(this, void 0, void 0, function* () {
6188
- return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
6242
+ return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6189
6243
  });
6190
6244
  this.join = (data) => __awaiter(this, void 0, void 0, function* () {
6191
6245
  const joinRequest = JoinRequest.create(Object.assign(Object.assign({}, data), { sessionId: this.sessionId, token: this.token }));
@@ -6206,7 +6260,7 @@ class StreamSfuClient {
6206
6260
  clearInterval(this.keepAliveInterval);
6207
6261
  }
6208
6262
  this.keepAliveInterval = setInterval(() => {
6209
- console.log('Sending healthCheckRequest to SFU');
6263
+ this.logger('info', 'Sending healthCheckRequest to SFU');
6210
6264
  const message = SfuRequest.create({
6211
6265
  requestPayload: {
6212
6266
  oneofKind: 'healthCheckRequest',
@@ -6224,7 +6278,7 @@ class StreamSfuClient {
6224
6278
  if (this.lastMessageTimestamp) {
6225
6279
  const timeSinceLastMessage = new Date().getTime() - this.lastMessageTimestamp.getTime();
6226
6280
  if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
6227
- console.log('SFU connection unhealthy, closing');
6281
+ this.logger('error', 'SFU connection unhealthy, closing');
6228
6282
  this.close(4001, `SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`);
6229
6283
  }
6230
6284
  }
@@ -6232,12 +6286,22 @@ class StreamSfuClient {
6232
6286
  };
6233
6287
  this.sessionId = sessionId || generateUUIDv4();
6234
6288
  this.token = token;
6289
+ this.logger = getLogger(['sfu-client']);
6290
+ const logger = this.logger;
6291
+ const logInterceptor = {
6292
+ interceptUnary(next, method, input, options) {
6293
+ logger('info', `Calling SFU RPC method ${method.name}`);
6294
+ logger('debug', `Method call payload`, { input, options });
6295
+ return next(method, input, options);
6296
+ },
6297
+ };
6235
6298
  this.rpc = createSignalClient({
6236
6299
  baseUrl: url,
6237
6300
  interceptors: [
6238
6301
  withHeaders({
6239
6302
  Authorization: `Bearer ${token}`,
6240
6303
  }),
6304
+ logInterceptor,
6241
6305
  ],
6242
6306
  });
6243
6307
  // Special handling for the ICETrickle kind of events.
@@ -6279,7 +6343,7 @@ const MAX_RETRIES = 5;
6279
6343
  * @param <I> the type of the request object.
6280
6344
  * @param <O> the type of the response object.
6281
6345
  */
6282
- const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
6346
+ const retryable = (rpc, logger) => __awaiter(void 0, void 0, void 0, function* () {
6283
6347
  var _a;
6284
6348
  let retryAttempt = 0;
6285
6349
  let rpcCallResult;
@@ -6289,9 +6353,11 @@ const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
6289
6353
  yield sleep(retryInterval(retryAttempt));
6290
6354
  }
6291
6355
  rpcCallResult = yield rpc();
6356
+ logger('info', `SFU RPC response received for ${rpcCallResult.method.name}`);
6357
+ logger('debug', `Response payload`, rpcCallResult);
6292
6358
  // if the RPC call failed, log the error and retry
6293
6359
  if (rpcCallResult.response.error) {
6294
- console.error('SFU Error:', rpcCallResult.response.error);
6360
+ logger('error', 'SFU RPC Error:', rpcCallResult.response.error);
6295
6361
  }
6296
6362
  retryAttempt++;
6297
6363
  } while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
@@ -6974,7 +7040,7 @@ class CallState {
6974
7040
  this.updateParticipant = (sessionId, patch) => {
6975
7041
  const participant = this.findParticipantBySessionId(sessionId);
6976
7042
  if (!participant) {
6977
- console.warn(`Participant with sessionId ${sessionId} not found`);
7043
+ this.logger('warn', `Participant with sessionId ${sessionId} not found`);
6978
7044
  return;
6979
7045
  }
6980
7046
  const thePatch = typeof patch === 'function' ? patch(participant) : patch;
@@ -7023,9 +7089,10 @@ class CallState {
7023
7089
  return p;
7024
7090
  }));
7025
7091
  };
7092
+ this.logger = getLogger(['call-state']);
7026
7093
  this.participants$ = this.participantsSubject.pipe(map$1((ps) => ps.sort(this.sortParticipantsBy)));
7027
7094
  this.localParticipant$ = this.participants$.pipe(map$1((participants) => participants.find(isStreamVideoLocalParticipant)));
7028
- this.remoteParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !p.isLoggedInUser)));
7095
+ this.remoteParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !p.isLocalParticipant)));
7029
7096
  this.pinnedParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => p.pinnedAt)));
7030
7097
  this.dominantSpeaker$ = this.participants$.pipe(map$1((participants) => participants.find((p) => p.isDominantSpeaker)));
7031
7098
  this.hasOngoingScreenShare$ = this.participants$.pipe(map$1((participants) => {
@@ -7179,13 +7246,13 @@ const watchCallRejected = (call) => {
7179
7246
  const { call: eventCall } = event;
7180
7247
  const { session: callSession } = eventCall;
7181
7248
  if (!callSession) {
7182
- console.log('No call session provided. Ignoring call.rejected event.');
7249
+ call.logger('warn', 'No call session provided. Ignoring call.rejected event.', event);
7183
7250
  return;
7184
7251
  }
7185
7252
  const rejectedBy = callSession.rejected_by;
7186
7253
  const { members, callingState } = call.state;
7187
7254
  if (callingState !== CallingState.RINGING) {
7188
- console.log('Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.');
7255
+ call.logger('warn', 'Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.', event);
7189
7256
  return;
7190
7257
  }
7191
7258
  if (call.isCreatedByMe) {
@@ -7193,13 +7260,13 @@ const watchCallRejected = (call) => {
7193
7260
  .filter((m) => m.user_id !== call.currentUserId)
7194
7261
  .every((m) => rejectedBy[m.user_id]);
7195
7262
  if (everyoneElseRejected) {
7196
- console.log('everyone rejected, leaving the call');
7263
+ call.logger('info', 'everyone rejected, leaving the call');
7197
7264
  yield call.leave();
7198
7265
  }
7199
7266
  }
7200
7267
  else {
7201
7268
  if (rejectedBy[eventCall.created_by.id]) {
7202
- console.log('call creator rejected, leaving call');
7269
+ call.logger('info', 'call creator rejected, leaving call');
7203
7270
  yield call.leave();
7204
7271
  }
7205
7272
  }
@@ -7607,7 +7674,7 @@ const watchCallSessionParticipantJoined = (state) => {
7607
7674
  const { user } = event;
7608
7675
  state.setMetadata((metadata) => {
7609
7676
  if (!metadata || !metadata.session) {
7610
- console.warn(`Received call.session_participant_joined event but the metadata structure is invalid.`);
7677
+ state.logger('warn', `Received call.session_participant_joined event but the metadata structure is invalid.`, event);
7611
7678
  return metadata;
7612
7679
  }
7613
7680
  const { session } = metadata;
@@ -7635,7 +7702,7 @@ const watchCallSessionParticipantLeft = (state) => {
7635
7702
  const { user } = event;
7636
7703
  state.setMetadata((metadata) => {
7637
7704
  if (!metadata || !metadata.session) {
7638
- console.warn(`Received call.session_participant_left event but the metadata structure is invalid.`);
7705
+ state.logger('warn', `Received call.session_participant_left event but the metadata structure is invalid.`, event);
7639
7706
  return metadata;
7640
7707
  }
7641
7708
  const { session } = metadata;
@@ -7780,16 +7847,18 @@ const getLocationHint = () => __awaiter(void 0, void 0, void 0, function* () {
7780
7847
  const hintURL = `https://hint.stream-io-video.com/`;
7781
7848
  const abortController = new AbortController();
7782
7849
  const timeoutId = setTimeout(() => abortController.abort(), 1000);
7850
+ const logger = getLogger(['call']);
7783
7851
  try {
7784
7852
  const response = yield fetch(hintURL, {
7785
7853
  method: 'HEAD',
7786
7854
  signal: abortController.signal,
7787
7855
  });
7788
7856
  const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
7857
+ logger === null || logger === void 0 ? void 0 : logger('info', `Location header: ${awsPop}`);
7789
7858
  return awsPop.substring(0, 3); // AMS1-P2 -> AMS
7790
7859
  }
7791
7860
  catch (e) {
7792
- console.error(`Failed to get location hint from ${hintURL}`, e);
7861
+ logger === null || logger === void 0 ? void 0 : logger('error', `Failed to get location hint from ${hintURL}`, e);
7793
7862
  return 'ERR';
7794
7863
  }
7795
7864
  finally {
@@ -7828,6 +7897,7 @@ const getCascadingModeParams = () => {
7828
7897
  * Creates a new StatsReporter instance that collects metrics about the ongoing call and reports them to the state store
7829
7898
  */
7830
7899
  const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIntervalInMs = 2000, }) => {
7900
+ const logger = getLogger(['stats']);
7831
7901
  const getRawStatsForTrack = (kind, selector) => __awaiter(void 0, void 0, void 0, function* () {
7832
7902
  if (kind === 'subscriber' && subscriber) {
7833
7903
  return subscriber.getStats(selector);
@@ -7836,7 +7906,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
7836
7906
  return publisher.getStats(selector);
7837
7907
  }
7838
7908
  else {
7839
- console.warn(`Can't retrieve RTC stats for`, kind);
7909
+ logger('warn', `Can't retrieve RTC stats for ${kind}`);
7840
7910
  return undefined;
7841
7911
  }
7842
7912
  });
@@ -7874,7 +7944,9 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
7874
7944
  for (let participant of state.participants) {
7875
7945
  if (!sessionIds.has(participant.sessionId))
7876
7946
  continue;
7877
- const kind = participant.isLoggedInUser ? 'publisher' : 'subscriber';
7947
+ const kind = participant.isLocalParticipant
7948
+ ? 'publisher'
7949
+ : 'subscriber';
7878
7950
  try {
7879
7951
  const mergedStream = new MediaStream([
7880
7952
  ...(((_a = participant.videoStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()) || []),
@@ -7886,7 +7958,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
7886
7958
  });
7887
7959
  }
7888
7960
  catch (e) {
7889
- console.error(`Failed to collect stats for ${kind}`, participant, e);
7961
+ logger('error', `Failed to collect stats for ${kind} if ${participant.userId}`, e);
7890
7962
  }
7891
7963
  }
7892
7964
  }
@@ -7924,7 +7996,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
7924
7996
  if (pollingIntervalInMs > 0) {
7925
7997
  const loop = () => __awaiter(void 0, void 0, void 0, function* () {
7926
7998
  yield run().catch((e) => {
7927
- console.log('Failed to collect stats', e);
7999
+ logger('warn', 'Failed to collect stats', e);
7928
8000
  });
7929
8001
  timeoutId = setTimeout(loop, pollingIntervalInMs);
7930
8002
  });
@@ -8467,6 +8539,9 @@ class Call {
8467
8539
  if ([CallingState.JOINED, CallingState.JOINING].includes(this.state.callingState)) {
8468
8540
  throw new Error(`Illegal State: Already joined.`);
8469
8541
  }
8542
+ if (this.state.callingState === CallingState.LEFT) {
8543
+ throw new Error('Illegal State: Cannot join already left call. Create a new Call instance to join a call.');
8544
+ }
8470
8545
  const previousCallingState = this.state.callingState;
8471
8546
  this.state.setCallingState(CallingState.JOINING);
8472
8547
  if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
@@ -8522,7 +8597,7 @@ class Call {
8522
8597
  */
8523
8598
  const rejoin = () => __awaiter(this, void 0, void 0, function* () {
8524
8599
  var _g, _h, _j;
8525
- console.log(`Rejoining call ${this.cid} (${this.reconnectAttempts})...`);
8600
+ this.logger('debug', `Rejoining call ${this.cid} (${this.reconnectAttempts})...`);
8526
8601
  this.reconnectAttempts++;
8527
8602
  this.state.setCallingState(CallingState.RECONNECTING);
8528
8603
  // take a snapshot of the current "local participant" state
@@ -8534,7 +8609,7 @@ class Call {
8534
8609
  sfuClient.close(); // clean up previous connection
8535
8610
  yield sleep(retryInterval(this.reconnectAttempts));
8536
8611
  yield this.join(data);
8537
- console.log(`Rejoin: ${this.reconnectAttempts} successful!`);
8612
+ this.logger('info', `Rejoin: ${this.reconnectAttempts} successful!`);
8538
8613
  if (localParticipant && !isReactNative()) {
8539
8614
  const { audioStream, videoStream, screenShareStream: screenShare, } = localParticipant;
8540
8615
  // restore previous publishing state
@@ -8545,7 +8620,7 @@ class Call {
8545
8620
  if (screenShare)
8546
8621
  yield this.publishScreenShareStream(screenShare);
8547
8622
  }
8548
- console.log(`Rejoin: state restored ${this.reconnectAttempts}`);
8623
+ this.logger('info', `Rejoin: state restored ${this.reconnectAttempts}`);
8549
8624
  });
8550
8625
  this.rejoinPromise = rejoin;
8551
8626
  // reconnect if the connection was closed unexpectedly. example:
@@ -8565,12 +8640,12 @@ class Call {
8565
8640
  return;
8566
8641
  if (this.reconnectAttempts < this.maxReconnectAttempts) {
8567
8642
  rejoin().catch(() => {
8568
- console.log(`Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8643
+ this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8569
8644
  this.state.setCallingState(CallingState.RECONNECTING_FAILED);
8570
8645
  });
8571
8646
  }
8572
8647
  else {
8573
- console.log('Reconnect attempts exceeded. Giving up...');
8648
+ this.logger('error', 'Reconnect attempts exceeded. Giving up...');
8574
8649
  this.state.setCallingState(CallingState.RECONNECTING_FAILED);
8575
8650
  }
8576
8651
  });
@@ -8580,15 +8655,15 @@ class Call {
8580
8655
  if (typeof window !== 'undefined' && window.addEventListener) {
8581
8656
  const handleOnOffline = () => {
8582
8657
  window.removeEventListener('offline', handleOnOffline);
8583
- console.log('Join: Going offline...');
8658
+ this.logger('warn', 'Join: Going offline...');
8584
8659
  this.state.setCallingState(CallingState.OFFLINE);
8585
8660
  };
8586
8661
  const handleOnOnline = () => {
8587
8662
  window.removeEventListener('online', handleOnOnline);
8588
8663
  if (this.state.callingState === CallingState.OFFLINE) {
8589
- console.log('Join: Going online...');
8664
+ this.logger('info', 'Join: Going online...');
8590
8665
  rejoin().catch(() => {
8591
- console.log(`Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8666
+ this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8592
8667
  this.state.setCallingState(CallingState.RECONNECTING_FAILED);
8593
8668
  });
8594
8669
  }
@@ -8645,15 +8720,20 @@ class Call {
8645
8720
  clientDetails.sdk = getSdkInfo();
8646
8721
  // 1. wait for the signal server to be ready before sending "joinRequest"
8647
8722
  sfuClient.signalReady
8648
- .catch((err) => console.warn('Signal ready failed', err))
8723
+ .catch((err) => this.logger('error', 'Signal ready failed', err))
8649
8724
  // prepare a generic SDP and send it to the SFU.
8650
8725
  // this is a throw-away SDP that the SFU will use to determine
8651
8726
  // the capabilities of the client (codec support, etc.)
8652
8727
  .then(() => getGenericSdp('recvonly', isRedEnabled, this.streamClient.options.preferredVideoCodec))
8653
- .then((sdp) => sfuClient.join({
8654
- subscriberSdp: sdp || '',
8655
- clientDetails,
8656
- }));
8728
+ .then((sdp) => {
8729
+ const joinRequest = {
8730
+ subscriberSdp: sdp || '',
8731
+ clientDetails,
8732
+ };
8733
+ this.logger('info', 'Sending join request to SFU');
8734
+ this.logger('debug', 'Join request payload', joinRequest);
8735
+ sfuClient.join(joinRequest);
8736
+ });
8657
8737
  // 2. in parallel, wait for the SFU to send us the "joinResponse"
8658
8738
  // this will throw an error if the SFU rejects the join request or
8659
8739
  // fails to respond in time
@@ -8663,22 +8743,22 @@ class Call {
8663
8743
  const startedAt = (callState === null || callState === void 0 ? void 0 : callState.startedAt)
8664
8744
  ? Timestamp.toDate(callState.startedAt)
8665
8745
  : new Date();
8666
- this.state.setParticipants(currentParticipants.map((participant) => (Object.assign(Object.assign({}, participant), { isLoggedInUser: participant.sessionId === sfuClient.sessionId, viewportVisibilityState: VisibilityState.UNKNOWN }))));
8746
+ this.state.setParticipants(currentParticipants.map((participant) => (Object.assign(Object.assign({}, participant), { isLocalParticipant: participant.sessionId === sfuClient.sessionId, viewportVisibilityState: VisibilityState.UNKNOWN }))));
8667
8747
  this.state.setParticipantCount((participantCount === null || participantCount === void 0 ? void 0 : participantCount.total) || 0);
8668
8748
  this.state.setAnonymousParticipantCount((participantCount === null || participantCount === void 0 ? void 0 : participantCount.anonymous) || 0);
8669
8749
  this.state.setStartedAt(startedAt);
8670
8750
  this.reconnectAttempts = 0; // reset the reconnect attempts counter
8671
8751
  this.state.setCallingState(CallingState.JOINED);
8672
- console.log(`Joined call ${this.cid}`);
8752
+ this.logger('info', `Joined call ${this.cid}`);
8673
8753
  }
8674
8754
  catch (err) {
8675
8755
  // join failed, try to rejoin
8676
8756
  if (this.reconnectAttempts < this.maxReconnectAttempts) {
8677
8757
  yield rejoin();
8678
- console.log(`Rejoin ${this.reconnectAttempts} successful!`);
8758
+ this.logger('info', `Rejoin ${this.reconnectAttempts} successful!`);
8679
8759
  }
8680
8760
  else {
8681
- console.log(`Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8761
+ this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
8682
8762
  this.state.setCallingState(CallingState.RECONNECTING_FAILED);
8683
8763
  throw new Error('Join failed');
8684
8764
  }
@@ -8703,7 +8783,8 @@ class Call {
8703
8783
  }
8704
8784
  const [videoTrack] = videoStream.getVideoTracks();
8705
8785
  if (!videoTrack) {
8706
- return console.error(`There is no video track in the stream.`);
8786
+ this.logger('error', `There is no video track to publish in the stream.`);
8787
+ return;
8707
8788
  }
8708
8789
  yield this.publisher.publishStream(videoStream, videoTrack, TrackType.VIDEO, opts);
8709
8790
  });
@@ -8726,7 +8807,8 @@ class Call {
8726
8807
  }
8727
8808
  const [audioTrack] = audioStream.getAudioTracks();
8728
8809
  if (!audioTrack) {
8729
- return console.error(`There is no audio track in the stream`);
8810
+ this.logger('error', `There is no audio track in the stream to publish`);
8811
+ return;
8730
8812
  }
8731
8813
  yield this.publisher.publishStream(audioStream, audioTrack, TrackType.AUDIO);
8732
8814
  });
@@ -8748,7 +8830,8 @@ class Call {
8748
8830
  }
8749
8831
  const [screenShareTrack] = screenShareStream.getVideoTracks();
8750
8832
  if (!screenShareTrack) {
8751
- return console.error(`There is no video track in the stream`);
8833
+ this.logger('error', `There is no video track in the screen share stream to publish`);
8834
+ return;
8752
8835
  }
8753
8836
  yield this.publisher.publishStream(screenShareStream, screenShareTrack, TrackType.SCREEN_SHARE);
8754
8837
  });
@@ -8763,7 +8846,7 @@ class Call {
8763
8846
  */
8764
8847
  this.stopPublish = (trackType) => __awaiter(this, void 0, void 0, function* () {
8765
8848
  var _k;
8766
- console.log(`stopPublish`, TrackType[trackType]);
8849
+ this.logger('info', `stopPublish ${TrackType[trackType]}`);
8767
8850
  yield ((_k = this.publisher) === null || _k === void 0 ? void 0 : _k.unpublishStream(trackType));
8768
8851
  });
8769
8852
  /**
@@ -8797,7 +8880,7 @@ class Call {
8797
8880
  const subscriptions = [];
8798
8881
  participants.forEach((p) => {
8799
8882
  // we don't want to subscribe to our own tracks
8800
- if (p.isLoggedInUser)
8883
+ if (p.isLocalParticipant)
8801
8884
  return;
8802
8885
  // NOTE: audio tracks don't have to be requested explicitly
8803
8886
  // as the SFU will implicitly subscribe us to all of them,
@@ -8912,20 +8995,21 @@ class Call {
8912
8995
  const [primaryStream] = e.streams;
8913
8996
  // example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
8914
8997
  const [trackId, trackType] = primaryStream.id.split(':');
8915
- console.log(`Got remote ${trackType} track:`, e.track);
8998
+ this.logger('info', `Got remote ${trackType} track:`);
8999
+ this.logger('debug', `Track: `, e.track);
8916
9000
  const participantToUpdate = this.state.participants.find((p) => p.trackLookupPrefix === trackId);
8917
9001
  if (!participantToUpdate) {
8918
- console.error('Received track for unknown participant', trackId, e);
9002
+ this.logger('error', `'Received track for unknown participant: ${trackId}'`, e);
8919
9003
  return;
8920
9004
  }
8921
9005
  e.track.addEventListener('mute', () => {
8922
- console.log(`Track muted:`, participantToUpdate.userId, `${trackType}:${trackId}`, e.track);
9006
+ this.logger('info', `Track muted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
8923
9007
  });
8924
9008
  e.track.addEventListener('unmute', () => {
8925
- console.log(`Track unmuted:`, participantToUpdate.userId, `${trackType}:${trackId}`, e.track);
9009
+ this.logger('info', `Track unmuted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
8926
9010
  });
8927
9011
  e.track.addEventListener('ended', () => {
8928
- console.log(`Track ended:`, participantToUpdate.userId, `${trackType}:${trackId}`, e.track);
9012
+ this.logger('info', `Track ended: ${participantToUpdate.userId} ${trackType}:${trackId}`);
8929
9013
  });
8930
9014
  const streamKindProp = {
8931
9015
  TRACK_TYPE_AUDIO: 'audioStream',
@@ -8933,12 +9017,12 @@ class Call {
8933
9017
  TRACK_TYPE_SCREEN_SHARE: 'screenShareStream',
8934
9018
  }[trackType];
8935
9019
  if (!streamKindProp) {
8936
- console.error('Unknown track type', trackType);
9020
+ this.logger('error', `Unknown track type: ${trackType}`);
8937
9021
  return;
8938
9022
  }
8939
9023
  const previousStream = participantToUpdate[streamKindProp];
8940
9024
  if (previousStream) {
8941
- console.log(`Cleaning up previous remote tracks`, e.track.kind);
9025
+ this.logger('info', `Cleaning up previous remote tracks: ${e.track.kind}`);
8942
9026
  previousStream.getTracks().forEach((t) => {
8943
9027
  t.stop();
8944
9028
  previousStream.removeTrack(t);
@@ -9238,6 +9322,7 @@ class Call {
9238
9322
  this.streamClient = streamClient;
9239
9323
  this.clientStore = clientStore;
9240
9324
  this.streamClientBasePath = `/call/${this.type}/${this.id}`;
9325
+ this.logger = getLogger(['call']);
9241
9326
  const callTypeConfig = CallTypes.get(type);
9242
9327
  const participantSorter = sortParticipantsBy || callTypeConfig.options.sortParticipantsBy;
9243
9328
  if (participantSorter) {
@@ -9275,7 +9360,7 @@ class Call {
9275
9360
  const hasPermission = this.permissionsContext.hasPermission(permission);
9276
9361
  if (!hasPermission && this.publisher.isPublishing(trackType)) {
9277
9362
  this.stopPublish(trackType).catch((err) => {
9278
- console.error('Error stopping publish', trackType, err);
9363
+ this.logger('error', `Error stopping publish ${trackType}`, err);
9279
9364
  });
9280
9365
  }
9281
9366
  }
@@ -9496,12 +9581,12 @@ class StableWSConnection {
9496
9581
  return;
9497
9582
  const user = this.client.user;
9498
9583
  if (!user) {
9499
- console.error(`User not set, can't connect to WS`);
9584
+ this.client.logger('error', `User not set, can't connect to WS`);
9500
9585
  return;
9501
9586
  }
9502
9587
  const token = this.client._getToken();
9503
9588
  if (!token) {
9504
- console.error(`Token not set, can't connect authenticate`);
9589
+ this.client.logger('error', `Token not set, can't connect authenticate`);
9505
9590
  return;
9506
9591
  }
9507
9592
  const authMessage = {
@@ -9734,7 +9819,7 @@ class StableWSConnection {
9734
9819
  addConnectionEventListeners(this.onlineStatusChanged);
9735
9820
  }
9736
9821
  _log(msg, extra = {}, level = 'info') {
9737
- this.client.logger(level, 'connection:' + msg, Object.assign({ tags: ['connection'] }, extra));
9822
+ this.client.logger(level, 'connection:' + msg, Object.assign({}, extra));
9738
9823
  }
9739
9824
  /**
9740
9825
  * connect - Connect to the WS URL
@@ -10451,7 +10536,7 @@ class WSConnectionFallback {
10451
10536
  addConnectionEventListeners(this._onlineStatusChanged);
10452
10537
  }
10453
10538
  _log(msg, extra = {}, level = 'info') {
10454
- this.client.logger(level, 'WSConnectionFallback:' + msg, Object.assign({ tags: ['connection_fallback', 'connection'] }, extra));
10539
+ this.client.logger(level, 'WSConnectionFallback:' + msg, Object.assign({}, extra));
10455
10540
  }
10456
10541
  _setState(state) {
10457
10542
  this._log(`_setState() - ${state}`);
@@ -10511,7 +10596,7 @@ class StreamClient {
10511
10596
  * If the user id remains the same we don't throw error
10512
10597
  */
10513
10598
  if (this.userID === user.id && this.setUserPromise) {
10514
- console.warn('Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.');
10599
+ this.logger('warn', 'Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.');
10515
10600
  return this.setUserPromise;
10516
10601
  }
10517
10602
  if (this.userID) {
@@ -10519,7 +10604,7 @@ class StreamClient {
10519
10604
  }
10520
10605
  if ((this._isUsingServerAuth() || this.node) &&
10521
10606
  !this.options.allowServerSideConnect) {
10522
- console.warn('Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.');
10607
+ this.logger('warn', 'Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.');
10523
10608
  }
10524
10609
  // we generate the client id client side
10525
10610
  this.userID = user.id;
@@ -10582,16 +10667,12 @@ class StreamClient {
10582
10667
  throw Error('UserWithId is not set on client, use client.connectUser or client.connectAnonymousUser instead');
10583
10668
  }
10584
10669
  if (((_d = this.wsConnection) === null || _d === void 0 ? void 0 : _d.isConnecting) && this.wsPromise) {
10585
- this.logger('info', 'client:openConnection() - connection already in progress', {
10586
- tags: ['connection', 'client'],
10587
- });
10670
+ this.logger('info', 'client:openConnection() - connection already in progress');
10588
10671
  return this.wsPromise;
10589
10672
  }
10590
10673
  if ((((_e = this.wsConnection) === null || _e === void 0 ? void 0 : _e.isHealthy) || ((_f = this.wsFallback) === null || _f === void 0 ? void 0 : _f.isHealthy())) &&
10591
10674
  this._hasConnectionID()) {
10592
- this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists', {
10593
- tags: ['connection', 'client'],
10594
- });
10675
+ this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists');
10595
10676
  return Promise.resolve();
10596
10677
  }
10597
10678
  this.clientID = `${this.userID}--${randomId()}`;
@@ -10614,9 +10695,7 @@ class StreamClient {
10614
10695
  * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
10615
10696
  */
10616
10697
  this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
10617
- this.logger('info', 'client:disconnect() - Disconnecting the client', {
10618
- tags: ['connection', 'client'],
10619
- });
10698
+ this.logger('info', 'client:disconnect() - Disconnecting the client');
10620
10699
  // remove the user specific fields
10621
10700
  delete this.user;
10622
10701
  delete this._user;
@@ -10706,7 +10785,8 @@ class StreamClient {
10706
10785
  this.dispatchEvent = (event) => {
10707
10786
  if (!event.received_at)
10708
10787
  event.received_at = new Date();
10709
- console.log(`Dispatching event: ${event.type}`, event);
10788
+ this.logger('info', `Dispatching event: ${event.type}`);
10789
+ this.logger('debug', 'Event payload:', event);
10710
10790
  this._callClientListeners(event);
10711
10791
  };
10712
10792
  this.handleEvent = (messageEvent) => {
@@ -10839,9 +10919,7 @@ class StreamClient {
10839
10919
  if (!(key in this.listeners)) {
10840
10920
  this.listeners[key] = [];
10841
10921
  }
10842
- this.logger('info', `Attaching listener for ${key} event`, {
10843
- tags: ['event', 'client'],
10844
- });
10922
+ this.logger('info', `Attaching listener for ${key} event`);
10845
10923
  this.listeners[key].push(callback);
10846
10924
  return () => {
10847
10925
  this.off(key, callback);
@@ -10859,29 +10937,26 @@ class StreamClient {
10859
10937
  if (!(key in this.listeners)) {
10860
10938
  this.listeners[key] = [];
10861
10939
  }
10862
- this.logger('info', `Removing listener for ${key} event`, {
10863
- tags: ['event', 'client'],
10864
- });
10940
+ this.logger('info', `Removing listener for ${key} event`);
10865
10941
  this.listeners[key] = this.listeners[key].filter((value) => value !== callback);
10866
10942
  }
10867
10943
  _logApiRequest(type, url, data, config) {
10868
- this.logger('info', `client: ${type} - Request - ${url}`, {
10869
- tags: ['api', 'api_request', 'client'],
10870
- url,
10944
+ this.logger('info', `client: ${type} - Request - ${url}`);
10945
+ this.logger('debug', `client: ${type} - Request payload`, {
10871
10946
  payload: data,
10872
10947
  config,
10873
10948
  });
10874
10949
  }
10875
10950
  _logApiResponse(type, url, response) {
10876
10951
  this.logger('info', `client:${type} - Response - url: ${url} > status ${response.status}`, {
10877
- tags: ['api', 'api_response', 'client'],
10878
- url,
10952
+ response,
10953
+ });
10954
+ this.logger('debug', `client:${type} - Response payload`, {
10879
10955
  response,
10880
10956
  });
10881
10957
  }
10882
10958
  _logApiError(type, url, error) {
10883
10959
  this.logger('error', `client:${type} - Error - url: ${url}`, {
10884
- tags: ['api', 'api_response', 'client'],
10885
10960
  url,
10886
10961
  error,
10887
10962
  });
@@ -10956,7 +11031,7 @@ class StreamClient {
10956
11031
  if (this.wsFallback) {
10957
11032
  return yield this.wsFallback.connect();
10958
11033
  }
10959
- console.log('StreamClient.connect: this.wsConnection.connect()');
11034
+ this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
10960
11035
  // if WSFallback is enabled, ws connect should timeout faster so fallback can try
10961
11036
  return yield this.wsConnection.connect(this.options.enableWSFallback
10962
11037
  ? this.defaultWSTimeoutWithFallback
@@ -10965,9 +11040,11 @@ class StreamClient {
10965
11040
  catch (err) {
10966
11041
  // run fallback only if it's WS/Network error and not a normal API error
10967
11042
  // make sure browser is online before even trying the longpoll
10968
- // @ts-ignore
10969
- if (this.options.enableWSFallback && isWSFailure(err) && isOnline()) {
10970
- this.logger('info', 'client:connect() - WS failed, fallback to longpoll', { tags: ['connection', 'client'] });
11043
+ if (this.options.enableWSFallback &&
11044
+ // @ts-ignore
11045
+ isWSFailure(err) &&
11046
+ isOnline(this.logger)) {
11047
+ this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
10971
11048
  this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
10972
11049
  this.wsConnection._destroyCurrentWSConnection();
10973
11050
  this.wsConnection.disconnect().then(); // close WS so no retry
@@ -11002,7 +11079,7 @@ class StreamClient {
11002
11079
  }
11003
11080
  getUserAgent() {
11004
11081
  return (this.userAgent ||
11005
- `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.12"}`);
11082
+ `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.14"}`);
11006
11083
  }
11007
11084
  setUserAgent(userAgent) {
11008
11085
  this.userAgent = userAgent;
@@ -11071,7 +11148,10 @@ class StreamClient {
11071
11148
  */
11072
11149
  class StreamVideoClient {
11073
11150
  constructor(apiKeyOrArgs, opts) {
11151
+ var _a, _b;
11152
+ this.logLevel = 'warn';
11074
11153
  this.eventHandlersToUnregister = [];
11154
+ this.logLevels = ['debug', 'info', 'warn', 'error'];
11075
11155
  /**
11076
11156
  * Disconnects the currently connected user from the client.
11077
11157
  *
@@ -11230,11 +11310,30 @@ class StreamVideoClient {
11230
11310
  this.connectionPromise.finally(() => (this.connectionPromise = undefined));
11231
11311
  return this.connectionPromise;
11232
11312
  });
11313
+ this.filterLogs = (logMethod) => {
11314
+ return (logLevel, messeage, extraData, tags) => {
11315
+ if (this.logLevels.indexOf(logLevel) >=
11316
+ this.logLevels.indexOf(this.logLevel)) {
11317
+ logMethod(logLevel, messeage, extraData, tags);
11318
+ }
11319
+ };
11320
+ };
11321
+ let defaultLogger = logToConsole;
11233
11322
  if (typeof apiKeyOrArgs === 'string') {
11234
- this.streamClient = new StreamClient(apiKeyOrArgs, Object.assign({ persistUserOnConnectionFailure: true }, opts));
11323
+ this.logLevel = (opts === null || opts === void 0 ? void 0 : opts.logLevel) || this.logLevel;
11324
+ this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || defaultLogger;
11235
11325
  }
11236
11326
  else {
11237
- this.streamClient = new StreamClient(apiKeyOrArgs.apiKey, Object.assign({ persistUserOnConnectionFailure: true }, apiKeyOrArgs.options));
11327
+ this.logLevel = ((_a = apiKeyOrArgs.options) === null || _a === void 0 ? void 0 : _a.logLevel) || this.logLevel;
11328
+ this.logger = ((_b = apiKeyOrArgs.options) === null || _b === void 0 ? void 0 : _b.logger) || defaultLogger;
11329
+ }
11330
+ setLogger(this.filterLogs(defaultLogger));
11331
+ const clientLogger = getLogger(['client']);
11332
+ if (typeof apiKeyOrArgs === 'string') {
11333
+ this.streamClient = new StreamClient(apiKeyOrArgs, Object.assign(Object.assign({ persistUserOnConnectionFailure: true }, opts), { logLevel: this.logLevel, logger: clientLogger }));
11334
+ }
11335
+ else {
11336
+ this.streamClient = new StreamClient(apiKeyOrArgs.apiKey, Object.assign(Object.assign({ persistUserOnConnectionFailure: true }, apiKeyOrArgs.options), { logLevel: this.logLevel, logger: clientLogger }));
11238
11337
  this.user = apiKeyOrArgs.user;
11239
11338
  this.token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
11240
11339
  if (this.user) {
@@ -11296,7 +11395,7 @@ class StreamVideoClient {
11296
11395
  },
11297
11396
  sort: [{ field: 'cid', direction: 1 }],
11298
11397
  }).catch((err) => {
11299
- console.warn('Failed to re-watch calls', err);
11398
+ this.logger('error', 'Failed to re-watch calls', err);
11300
11399
  });
11301
11400
  }
11302
11401
  }
@@ -11306,7 +11405,7 @@ class StreamVideoClient {
11306
11405
  return;
11307
11406
  const { call, members } = event;
11308
11407
  if (userToConnect.id === call.created_by.id) {
11309
- console.warn('Received `call.created` sent by the current user');
11408
+ this.logger('warn', 'Received `call.created` sent by the current user');
11310
11409
  return;
11311
11410
  }
11312
11411
  this.writeableStateStore.registerCall(new Call({
@@ -11323,7 +11422,7 @@ class StreamVideoClient {
11323
11422
  return;
11324
11423
  const { call, members } = event;
11325
11424
  if (userToConnect.id === call.created_by.id) {
11326
- console.warn('Received `call.ring` sent by the current user');
11425
+ this.logger('warn', 'Received `call.ring` sent by the current user');
11327
11426
  return;
11328
11427
  }
11329
11428
  // The call might already be tracked by the client,
@@ -11390,7 +11489,10 @@ const getDevices = (constraints) => {
11390
11489
  });
11391
11490
  })
11392
11491
  .catch((error) => {
11393
- console.error('Failed to get devices', error);
11492
+ const logger = getLogger(['devices']);
11493
+ if (logger) {
11494
+ logger('error', 'Failed to get devices', error);
11495
+ }
11394
11496
  subscriber.error(error);
11395
11497
  });
11396
11498
  });
@@ -11461,11 +11563,15 @@ const getAudioOutputDevices = () => {
11461
11563
  return audioDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'audiooutput')));
11462
11564
  };
11463
11565
  const getStream = (constraints) => __awaiter(void 0, void 0, void 0, function* () {
11566
+ var _a;
11464
11567
  try {
11465
11568
  return yield navigator.mediaDevices.getUserMedia(constraints);
11466
11569
  }
11467
11570
  catch (e) {
11468
- console.error(`Failed get user media`, constraints, e);
11571
+ (_a = getLogger(['devices'])) === null || _a === void 0 ? void 0 : _a('error', `Failed get user media`, {
11572
+ error: e,
11573
+ constraints: constraints,
11574
+ });
11469
11575
  throw e;
11470
11576
  }
11471
11577
  });
@@ -11508,11 +11614,12 @@ const getVideoStream = (trackConstraints) => __awaiter(void 0, void 0, void 0, f
11508
11614
  * @param options any additional options to pass to the [`getDisplayMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) API.
11509
11615
  */
11510
11616
  const getScreenShareStream = (options) => __awaiter(void 0, void 0, void 0, function* () {
11617
+ var _b;
11511
11618
  try {
11512
11619
  return yield navigator.mediaDevices.getDisplayMedia(Object.assign({ video: true, audio: false }, options));
11513
11620
  }
11514
11621
  catch (e) {
11515
- console.error('Failed to get screen share stream', e);
11622
+ (_b = getLogger(['devices'])) === null || _b === void 0 ? void 0 : _b('error', 'Failed to get screen share stream', e);
11516
11623
  throw e;
11517
11624
  }
11518
11625
  });
@@ -11695,5 +11802,5 @@ var browsers = /*#__PURE__*/Object.freeze({
11695
11802
  isSafari: isSafari
11696
11803
  });
11697
11804
 
11698
- export { APIErrorCodeEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CreateDeviceRequestPushProviderEnum, DebounceType, ErrorFromResponse, OwnCapability, RecordSettingsModeEnum, RecordSettingsQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, events as SfuEvents, models as SfuModels, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, name, noopComparator, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
11805
+ export { APIErrorCodeEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CreateDeviceRequestPushProviderEnum, DebounceType, ErrorFromResponse, OwnCapability, RecordSettingsModeEnum, RecordSettingsQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, events as SfuEvents, models as SfuModels, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getLogger, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, logToConsole, name, noopComparator, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setLogger, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
11699
11806
  //# sourceMappingURL=index.browser.es.js.map