@stream-io/video-client 0.1.3 → 0.1.5

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 (34) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/index.browser.es.js +401 -106
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +400 -105
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.es.js +401 -106
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/src/Call.d.ts +1 -1
  9. package/dist/src/StreamSfuClient.d.ts +2 -1
  10. package/dist/src/StreamVideoClient.d.ts +3 -4
  11. package/dist/src/coordinator/connection/client.d.ts +0 -6
  12. package/dist/src/gen/video/sfu/event/events.d.ts +45 -2
  13. package/dist/src/gen/video/sfu/models/models.d.ts +12 -0
  14. package/dist/src/gen/video/sfu/signal_rpc/signal.client.d.ts +9 -1
  15. package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +42 -0
  16. package/dist/src/rtc/Publisher.d.ts +10 -2
  17. package/dist/src/rtc/Subscriber.d.ts +8 -3
  18. package/dist/version.d.ts +1 -1
  19. package/package.json +1 -1
  20. package/src/Call.ts +18 -9
  21. package/src/StreamSfuClient.ts +16 -5
  22. package/src/StreamVideoClient.ts +32 -30
  23. package/src/coordinator/connection/client.ts +0 -25
  24. package/src/gen/google/protobuf/struct.ts +1 -2
  25. package/src/gen/google/protobuf/timestamp.ts +1 -1
  26. package/src/gen/video/sfu/event/events.ts +165 -5
  27. package/src/gen/video/sfu/models/models.ts +13 -1
  28. package/src/gen/video/sfu/signal_rpc/signal.client.ts +27 -1
  29. package/src/gen/video/sfu/signal_rpc/signal.ts +194 -1
  30. package/src/rtc/Dispatcher.ts +1 -0
  31. package/src/rtc/Publisher.ts +69 -34
  32. package/src/rtc/Subscriber.ts +74 -7
  33. package/src/rtc/__tests__/Publisher.test.ts +82 -2
  34. package/src/rtc/__tests__/Subscriber.test.ts +84 -1
package/dist/index.es.js CHANGED
@@ -4,7 +4,7 @@ import { ServiceType, stackIntercept } from '@protobuf-ts/runtime-rpc';
4
4
  import axios, { AxiosHeaders } from 'axios';
5
5
  export { AxiosError } from 'axios';
6
6
  import { TwirpFetchTransport } from '@protobuf-ts/twirp-transport';
7
- import { ReplaySubject, BehaviorSubject, takeWhile, pairwise, tap, debounce, timer, map as map$2, Observable, debounceTime, concatMap, from, shareReplay, merge, combineLatest, filter } from 'rxjs';
7
+ import { ReplaySubject, BehaviorSubject, takeWhile, filter, pairwise, tap, debounce, timer, map as map$2, Observable, debounceTime, concatMap, from, shareReplay, merge, combineLatest } from 'rxjs';
8
8
  import * as SDP from 'sdp-transform';
9
9
  import WebSocket from 'isomorphic-ws';
10
10
  import { take, map as map$1, distinctUntilChanged } from 'rxjs/operators';
@@ -372,7 +372,6 @@ class Value$Type extends MessageType {
372
372
  };
373
373
  }
374
374
  else {
375
- Struct.fromJson(json);
376
375
  target.kind = {
377
376
  oneofKind: 'structValue',
378
377
  structValue: Struct.fromJson(json),
@@ -828,6 +827,18 @@ var ErrorCode;
828
827
  * @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MIGRATION_FAILED = 202;
829
828
  */
830
829
  ErrorCode[ErrorCode["PARTICIPANT_MIGRATION_FAILED"] = 202] = "PARTICIPANT_MIGRATION_FAILED";
830
+ /**
831
+ * @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MIGRATING = 203;
832
+ */
833
+ ErrorCode[ErrorCode["PARTICIPANT_MIGRATING"] = 203] = "PARTICIPANT_MIGRATING";
834
+ /**
835
+ * @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_RECONNECT_FAILED = 204;
836
+ */
837
+ ErrorCode[ErrorCode["PARTICIPANT_RECONNECT_FAILED"] = 204] = "PARTICIPANT_RECONNECT_FAILED";
838
+ /**
839
+ * @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MEDIA_TRANSPORT_FAILURE = 205;
840
+ */
841
+ ErrorCode[ErrorCode["PARTICIPANT_MEDIA_TRANSPORT_FAILURE"] = 205] = "PARTICIPANT_MEDIA_TRANSPORT_FAILURE";
831
842
  /**
832
843
  * @generated from protobuf enum value: ERROR_CODE_CALL_NOT_FOUND = 300;
833
844
  */
@@ -2404,10 +2415,122 @@ var models = /*#__PURE__*/Object.freeze({
2404
2415
  });
2405
2416
 
2406
2417
  /* eslint-disable */
2407
- // @generated by protobuf-ts 2.8.1 with parameter long_type_string,client_generic,server_none,eslint_disable
2418
+ // @generated by protobuf-ts 2.9.0 with parameter long_type_string,client_generic,server_none,eslint_disable
2408
2419
  // @generated from protobuf file "video/sfu/signal_rpc/signal.proto" (package "stream.video.sfu.signal", syntax proto3)
2409
2420
  // tslint:disable
2410
2421
  // @generated message type with reflection information, may provide speed optimized methods
2422
+ class ICERestartRequest$Type extends MessageType {
2423
+ constructor() {
2424
+ super('stream.video.sfu.signal.ICERestartRequest', [
2425
+ { no: 1, name: 'session_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
2426
+ {
2427
+ no: 2,
2428
+ name: 'peer_type',
2429
+ kind: 'enum',
2430
+ T: () => ['stream.video.sfu.models.PeerType', PeerType, 'PEER_TYPE_'],
2431
+ },
2432
+ ]);
2433
+ }
2434
+ create(value) {
2435
+ const message = { sessionId: '', peerType: 0 };
2436
+ globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
2437
+ enumerable: false,
2438
+ value: this,
2439
+ });
2440
+ if (value !== undefined)
2441
+ reflectionMergePartial(this, message, value);
2442
+ return message;
2443
+ }
2444
+ internalBinaryRead(reader, length, options, target) {
2445
+ let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
2446
+ while (reader.pos < end) {
2447
+ let [fieldNo, wireType] = reader.tag();
2448
+ switch (fieldNo) {
2449
+ case /* string session_id */ 1:
2450
+ message.sessionId = reader.string();
2451
+ break;
2452
+ case /* stream.video.sfu.models.PeerType peer_type */ 2:
2453
+ message.peerType = reader.int32();
2454
+ break;
2455
+ default:
2456
+ let u = options.readUnknownField;
2457
+ if (u === 'throw')
2458
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
2459
+ let d = reader.skip(wireType);
2460
+ if (u !== false)
2461
+ (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
2462
+ }
2463
+ }
2464
+ return message;
2465
+ }
2466
+ internalBinaryWrite(message, writer, options) {
2467
+ /* string session_id = 1; */
2468
+ if (message.sessionId !== '')
2469
+ writer.tag(1, WireType.LengthDelimited).string(message.sessionId);
2470
+ /* stream.video.sfu.models.PeerType peer_type = 2; */
2471
+ if (message.peerType !== 0)
2472
+ writer.tag(2, WireType.Varint).int32(message.peerType);
2473
+ let u = options.writeUnknownFields;
2474
+ if (u !== false)
2475
+ (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
2476
+ return writer;
2477
+ }
2478
+ }
2479
+ /**
2480
+ * @generated MessageType for protobuf message stream.video.sfu.signal.ICERestartRequest
2481
+ */
2482
+ const ICERestartRequest = new ICERestartRequest$Type();
2483
+ // @generated message type with reflection information, may provide speed optimized methods
2484
+ class ICERestartResponse$Type extends MessageType {
2485
+ constructor() {
2486
+ super('stream.video.sfu.signal.ICERestartResponse', [
2487
+ { no: 1, name: 'error', kind: 'message', T: () => Error$2 },
2488
+ ]);
2489
+ }
2490
+ create(value) {
2491
+ const message = {};
2492
+ globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
2493
+ enumerable: false,
2494
+ value: this,
2495
+ });
2496
+ if (value !== undefined)
2497
+ reflectionMergePartial(this, message, value);
2498
+ return message;
2499
+ }
2500
+ internalBinaryRead(reader, length, options, target) {
2501
+ let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
2502
+ while (reader.pos < end) {
2503
+ let [fieldNo, wireType] = reader.tag();
2504
+ switch (fieldNo) {
2505
+ case /* stream.video.sfu.models.Error error */ 1:
2506
+ message.error = Error$2.internalBinaryRead(reader, reader.uint32(), options, message.error);
2507
+ break;
2508
+ default:
2509
+ let u = options.readUnknownField;
2510
+ if (u === 'throw')
2511
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
2512
+ let d = reader.skip(wireType);
2513
+ if (u !== false)
2514
+ (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
2515
+ }
2516
+ }
2517
+ return message;
2518
+ }
2519
+ internalBinaryWrite(message, writer, options) {
2520
+ /* stream.video.sfu.models.Error error = 1; */
2521
+ if (message.error)
2522
+ Error$2.internalBinaryWrite(message.error, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
2523
+ let u = options.writeUnknownFields;
2524
+ if (u !== false)
2525
+ (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
2526
+ return writer;
2527
+ }
2528
+ }
2529
+ /**
2530
+ * @generated MessageType for protobuf message stream.video.sfu.signal.ICERestartResponse
2531
+ */
2532
+ const ICERestartResponse = new ICERestartResponse$Type();
2533
+ // @generated message type with reflection information, may provide speed optimized methods
2411
2534
  class UpdateMuteStatesRequest$Type extends MessageType {
2412
2535
  constructor() {
2413
2536
  super('stream.video.sfu.signal.UpdateMuteStatesRequest', [
@@ -3218,6 +3341,12 @@ const SignalServer = new ServiceType('stream.video.sfu.signal.SignalServer', [
3218
3341
  I: UpdateMuteStatesRequest,
3219
3342
  O: UpdateMuteStatesResponse,
3220
3343
  },
3344
+ {
3345
+ name: 'IceRestart',
3346
+ options: {},
3347
+ I: ICERestartRequest,
3348
+ O: ICERestartResponse,
3349
+ },
3221
3350
  ]);
3222
3351
 
3223
3352
  /**
@@ -3358,6 +3487,13 @@ class SfuEvent$Type extends MessageType {
3358
3487
  oneof: 'eventPayload',
3359
3488
  T: () => GoAway,
3360
3489
  },
3490
+ {
3491
+ no: 21,
3492
+ name: 'ice_restart',
3493
+ kind: 'message',
3494
+ oneof: 'eventPayload',
3495
+ T: () => ICERestart,
3496
+ },
3361
3497
  ]);
3362
3498
  }
3363
3499
  create(value) {
@@ -3471,6 +3607,12 @@ class SfuEvent$Type extends MessageType {
3471
3607
  goAway: GoAway.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.goAway),
3472
3608
  };
3473
3609
  break;
3610
+ case /* stream.video.sfu.event.ICERestart ice_restart */ 21:
3611
+ message.eventPayload = {
3612
+ oneofKind: 'iceRestart',
3613
+ iceRestart: ICERestart.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.iceRestart),
3614
+ };
3615
+ break;
3474
3616
  default:
3475
3617
  let u = options.readUnknownField;
3476
3618
  if (u === 'throw')
@@ -3531,6 +3673,9 @@ class SfuEvent$Type extends MessageType {
3531
3673
  /* stream.video.sfu.event.GoAway go_away = 20; */
3532
3674
  if (message.eventPayload.oneofKind === 'goAway')
3533
3675
  GoAway.internalBinaryWrite(message.eventPayload.goAway, writer.tag(20, WireType.LengthDelimited).fork(), options).join();
3676
+ /* stream.video.sfu.event.ICERestart ice_restart = 21; */
3677
+ if (message.eventPayload.oneofKind === 'iceRestart')
3678
+ ICERestart.internalBinaryWrite(message.eventPayload.iceRestart, writer.tag(21, WireType.LengthDelimited).fork(), options).join();
3534
3679
  let u = options.writeUnknownFields;
3535
3680
  if (u !== false)
3536
3681
  (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -3659,6 +3804,61 @@ class ICETrickle$Type extends MessageType {
3659
3804
  */
3660
3805
  const ICETrickle = new ICETrickle$Type();
3661
3806
  // @generated message type with reflection information, may provide speed optimized methods
3807
+ class ICERestart$Type extends MessageType {
3808
+ constructor() {
3809
+ super('stream.video.sfu.event.ICERestart', [
3810
+ {
3811
+ no: 1,
3812
+ name: 'peer_type',
3813
+ kind: 'enum',
3814
+ T: () => ['stream.video.sfu.models.PeerType', PeerType, 'PEER_TYPE_'],
3815
+ },
3816
+ ]);
3817
+ }
3818
+ create(value) {
3819
+ const message = { peerType: 0 };
3820
+ globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
3821
+ enumerable: false,
3822
+ value: this,
3823
+ });
3824
+ if (value !== undefined)
3825
+ reflectionMergePartial(this, message, value);
3826
+ return message;
3827
+ }
3828
+ internalBinaryRead(reader, length, options, target) {
3829
+ let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
3830
+ while (reader.pos < end) {
3831
+ let [fieldNo, wireType] = reader.tag();
3832
+ switch (fieldNo) {
3833
+ case /* stream.video.sfu.models.PeerType peer_type */ 1:
3834
+ message.peerType = reader.int32();
3835
+ break;
3836
+ default:
3837
+ let u = options.readUnknownField;
3838
+ if (u === 'throw')
3839
+ throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
3840
+ let d = reader.skip(wireType);
3841
+ if (u !== false)
3842
+ (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
3843
+ }
3844
+ }
3845
+ return message;
3846
+ }
3847
+ internalBinaryWrite(message, writer, options) {
3848
+ /* stream.video.sfu.models.PeerType peer_type = 1; */
3849
+ if (message.peerType !== 0)
3850
+ writer.tag(1, WireType.Varint).int32(message.peerType);
3851
+ let u = options.writeUnknownFields;
3852
+ if (u !== false)
3853
+ (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
3854
+ return writer;
3855
+ }
3856
+ }
3857
+ /**
3858
+ * @generated MessageType for protobuf message stream.video.sfu.event.ICERestart
3859
+ */
3860
+ const ICERestart = new ICERestart$Type();
3861
+ // @generated message type with reflection information, may provide speed optimized methods
3662
3862
  class SfuRequest$Type extends MessageType {
3663
3863
  constructor() {
3664
3864
  super('stream.video.sfu.event.SfuRequest', [
@@ -4012,10 +4212,21 @@ class JoinRequest$Type extends MessageType {
4012
4212
  T: () => ClientDetails,
4013
4213
  },
4014
4214
  { no: 5, name: 'migration', kind: 'message', T: () => Migration },
4215
+ {
4216
+ no: 6,
4217
+ name: 'fast_reconnect',
4218
+ kind: 'scalar',
4219
+ T: 8 /*ScalarType.BOOL*/,
4220
+ },
4015
4221
  ]);
4016
4222
  }
4017
4223
  create(value) {
4018
- const message = { token: '', sessionId: '', subscriberSdp: '' };
4224
+ const message = {
4225
+ token: '',
4226
+ sessionId: '',
4227
+ subscriberSdp: '',
4228
+ fastReconnect: false,
4229
+ };
4019
4230
  globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
4020
4231
  enumerable: false,
4021
4232
  value: this,
@@ -4044,6 +4255,9 @@ class JoinRequest$Type extends MessageType {
4044
4255
  case /* stream.video.sfu.event.Migration migration */ 5:
4045
4256
  message.migration = Migration.internalBinaryRead(reader, reader.uint32(), options, message.migration);
4046
4257
  break;
4258
+ case /* bool fast_reconnect */ 6:
4259
+ message.fastReconnect = reader.bool();
4260
+ break;
4047
4261
  default:
4048
4262
  let u = options.readUnknownField;
4049
4263
  if (u === 'throw')
@@ -4071,6 +4285,9 @@ class JoinRequest$Type extends MessageType {
4071
4285
  /* stream.video.sfu.event.Migration migration = 5; */
4072
4286
  if (message.migration)
4073
4287
  Migration.internalBinaryWrite(message.migration, writer.tag(5, WireType.LengthDelimited).fork(), options).join();
4288
+ /* bool fast_reconnect = 6; */
4289
+ if (message.fastReconnect !== false)
4290
+ writer.tag(6, WireType.Varint).bool(message.fastReconnect);
4074
4291
  let u = options.writeUnknownFields;
4075
4292
  if (u !== false)
4076
4293
  (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -4167,10 +4384,11 @@ class JoinResponse$Type extends MessageType {
4167
4384
  constructor() {
4168
4385
  super('stream.video.sfu.event.JoinResponse', [
4169
4386
  { no: 1, name: 'call_state', kind: 'message', T: () => CallState$1 },
4387
+ { no: 2, name: 'reconnected', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },
4170
4388
  ]);
4171
4389
  }
4172
4390
  create(value) {
4173
- const message = {};
4391
+ const message = { reconnected: false };
4174
4392
  globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
4175
4393
  enumerable: false,
4176
4394
  value: this,
@@ -4187,6 +4405,9 @@ class JoinResponse$Type extends MessageType {
4187
4405
  case /* stream.video.sfu.models.CallState call_state */ 1:
4188
4406
  message.callState = CallState$1.internalBinaryRead(reader, reader.uint32(), options, message.callState);
4189
4407
  break;
4408
+ case /* bool reconnected */ 2:
4409
+ message.reconnected = reader.bool();
4410
+ break;
4190
4411
  default:
4191
4412
  let u = options.readUnknownField;
4192
4413
  if (u === 'throw')
@@ -4202,6 +4423,9 @@ class JoinResponse$Type extends MessageType {
4202
4423
  /* stream.video.sfu.models.CallState call_state = 1; */
4203
4424
  if (message.callState)
4204
4425
  CallState$1.internalBinaryWrite(message.callState, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
4426
+ /* bool reconnected = 2; */
4427
+ if (message.reconnected !== false)
4428
+ writer.tag(2, WireType.Varint).bool(message.reconnected);
4205
4429
  let u = options.writeUnknownFields;
4206
4430
  if (u !== false)
4207
4431
  (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -5318,6 +5542,7 @@ var events = /*#__PURE__*/Object.freeze({
5318
5542
  GoAway: GoAway,
5319
5543
  HealthCheckRequest: HealthCheckRequest,
5320
5544
  HealthCheckResponse: HealthCheckResponse,
5545
+ ICERestart: ICERestart,
5321
5546
  ICETrickle: ICETrickle,
5322
5547
  JoinRequest: JoinRequest,
5323
5548
  JoinResponse: JoinResponse,
@@ -5434,6 +5659,13 @@ class SignalServerClient {
5434
5659
  const method = this.methods[4], opt = this._transport.mergeOptions(options);
5435
5660
  return stackIntercept('unary', this._transport, method, opt, input);
5436
5661
  }
5662
+ /**
5663
+ * @generated from protobuf rpc: IceRestart(stream.video.sfu.signal.ICERestartRequest) returns (stream.video.sfu.signal.ICERestartResponse);
5664
+ */
5665
+ iceRestart(input, options) {
5666
+ const method = this.methods[5], opt = this._transport.mergeOptions(options);
5667
+ return stackIntercept('unary', this._transport, method, opt, input);
5668
+ }
5437
5669
  }
5438
5670
 
5439
5671
  const defaultOptions = {
@@ -5668,7 +5900,7 @@ const logLevels = Object.freeze({
5668
5900
  warn: 3,
5669
5901
  error: 4,
5670
5902
  });
5671
- let logger$3;
5903
+ let logger$4;
5672
5904
  let level = 'info';
5673
5905
  const logToConsole = (logLevel, message, ...args) => {
5674
5906
  let logMethod;
@@ -5692,7 +5924,7 @@ const logToConsole = (logLevel, message, ...args) => {
5692
5924
  logMethod(message, ...args);
5693
5925
  };
5694
5926
  const setLogger = (l, lvl) => {
5695
- logger$3 = l;
5927
+ logger$4 = l;
5696
5928
  if (lvl) {
5697
5929
  setLogLevel(lvl);
5698
5930
  }
@@ -5701,7 +5933,7 @@ const setLogLevel = (l) => {
5701
5933
  level = l;
5702
5934
  };
5703
5935
  const getLogger = (withTags) => {
5704
- const loggerMethod = logger$3 || logToConsole;
5936
+ const loggerMethod = logger$4 || logToConsole;
5705
5937
  const tags = (withTags || []).join(':');
5706
5938
  const result = (logLevel, message, ...args) => {
5707
5939
  if (logLevels[logLevel] >= logLevels[level]) {
@@ -5808,6 +6040,7 @@ const sfuEventKinds = {
5808
6040
  error: undefined,
5809
6041
  callGrantsUpdated: undefined,
5810
6042
  goAway: undefined,
6043
+ iceRestart: undefined,
5811
6044
  };
5812
6045
  const isSfuEvent = (eventName) => {
5813
6046
  return Object.prototype.hasOwnProperty.call(sfuEventKinds, eventName);
@@ -6033,6 +6266,7 @@ const muteTypeToTrackType = (muteType) => {
6033
6266
  }
6034
6267
  };
6035
6268
 
6269
+ const logger$3 = getLogger(['Publisher']);
6036
6270
  /**
6037
6271
  * The `Publisher` is responsible for publishing/unpublishing media streams to/from the SFU
6038
6272
  * @internal
@@ -6044,11 +6278,13 @@ class Publisher {
6044
6278
  * @param connectionConfig the connection configuration to use.
6045
6279
  * @param sfuClient the SFU client to use.
6046
6280
  * @param state the call state to use.
6281
+ * @param dispatcher the dispatcher to use.
6047
6282
  * @param isDtxEnabled whether DTX is enabled.
6048
6283
  * @param isRedEnabled whether RED is enabled.
6049
6284
  * @param preferredVideoCodec the preferred video codec.
6285
+ * @param iceRestartDelay the delay in milliseconds to wait before restarting ICE once connection goes to `disconnected` state.
6050
6286
  */
6051
- constructor({ connectionConfig, sfuClient, state, isDtxEnabled, isRedEnabled, preferredVideoCodec, }) {
6287
+ constructor({ connectionConfig, sfuClient, dispatcher, state, isDtxEnabled, isRedEnabled, preferredVideoCodec, iceRestartDelay = 2500, }) {
6052
6288
  this.transceiverRegistry = {
6053
6289
  [TrackType.AUDIO]: undefined,
6054
6290
  [TrackType.VIDEO]: undefined,
@@ -6078,7 +6314,7 @@ class Publisher {
6078
6314
  [TrackType.SCREEN_SHARE_AUDIO]: undefined,
6079
6315
  [TrackType.UNSPECIFIED]: undefined,
6080
6316
  };
6081
- this.logger = getLogger(['Publisher']);
6317
+ this.isIceRestarting = false;
6082
6318
  this.createPeerConnection = (connectionConfig) => {
6083
6319
  const pc = new RTCPeerConnection(connectionConfig);
6084
6320
  pc.addEventListener('icecandidate', this.onIceCandidate);
@@ -6104,6 +6340,7 @@ class Publisher {
6104
6340
  this.trackLayersCache[trackType] = undefined;
6105
6341
  });
6106
6342
  }
6343
+ this.unsubscribeOnIceRestart();
6107
6344
  this.pc.removeEventListener('negotiationneeded', this.onNegotiationNeeded);
6108
6345
  this.pc.close();
6109
6346
  };
@@ -6134,7 +6371,7 @@ class Publisher {
6134
6371
  * Once the track has ended, it will notify the SFU and update the state.
6135
6372
  */
6136
6373
  const handleTrackEnded = () => __awaiter(this, void 0, void 0, function* () {
6137
- this.logger('info', `Track ${TrackType[trackType]} has ended, notifying the SFU`);
6374
+ logger$3('info', `Track ${TrackType[trackType]} has ended, notifying the SFU`);
6138
6375
  yield this.notifyTrackMuteStateChanged(mediaStream, track, trackType, true);
6139
6376
  // clean-up, this event listener needs to run only once.
6140
6377
  track.removeEventListener('ended', handleTrackEnded);
@@ -6157,11 +6394,11 @@ class Publisher {
6157
6394
  : undefined,
6158
6395
  sendEncodings: videoEncodings,
6159
6396
  });
6160
- this.logger('debug', `Added ${TrackType[trackType]} transceiver`);
6397
+ logger$3('debug', `Added ${TrackType[trackType]} transceiver`);
6161
6398
  this.transceiverInitOrder.push(trackType);
6162
6399
  this.transceiverRegistry[trackType] = transceiver;
6163
6400
  if ('setCodecPreferences' in transceiver && codecPreferences) {
6164
- this.logger('info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
6401
+ logger$3('info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
6165
6402
  transceiver.setCodecPreferences(codecPreferences);
6166
6403
  }
6167
6404
  }
@@ -6229,7 +6466,7 @@ class Publisher {
6229
6466
  * Stops publishing all tracks and stop all tracks.
6230
6467
  */
6231
6468
  this.stopPublishing = () => {
6232
- this.logger('debug', 'Stopping publishing all tracks');
6469
+ logger$3('debug', 'Stopping publishing all tracks');
6233
6470
  this.pc.getSenders().forEach((s) => {
6234
6471
  var _a;
6235
6472
  (_a = s.track) === null || _a === void 0 ? void 0 : _a.stop();
@@ -6240,15 +6477,15 @@ class Publisher {
6240
6477
  };
6241
6478
  this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
6242
6479
  var _a;
6243
- this.logger('info', 'Update publish quality, requested rids by SFU:', enabledRids);
6480
+ logger$3('info', 'Update publish quality, requested rids by SFU:', enabledRids);
6244
6481
  const videoSender = (_a = this.transceiverRegistry[TrackType.VIDEO]) === null || _a === void 0 ? void 0 : _a.sender;
6245
6482
  if (!videoSender) {
6246
- this.logger('warn', 'Update publish quality, no video sender found.');
6483
+ logger$3('warn', 'Update publish quality, no video sender found.');
6247
6484
  return;
6248
6485
  }
6249
6486
  const params = videoSender.getParameters();
6250
6487
  if (params.encodings.length === 0) {
6251
- this.logger('warn', 'Update publish quality, No suitable video encoding quality found');
6488
+ logger$3('warn', 'Update publish quality, No suitable video encoding quality found');
6252
6489
  return;
6253
6490
  }
6254
6491
  let changed = false;
@@ -6266,10 +6503,10 @@ class Publisher {
6266
6503
  .join(', ');
6267
6504
  if (changed) {
6268
6505
  yield videoSender.setParameters(params);
6269
- this.logger('info', `Update publish quality, enabled rids: ${activeRids}`);
6506
+ logger$3('info', `Update publish quality, enabled rids: ${activeRids}`);
6270
6507
  }
6271
6508
  else {
6272
- this.logger('info', `Update publish quality, no change: ${activeRids}`);
6509
+ logger$3('info', `Update publish quality, no change: ${activeRids}`);
6273
6510
  }
6274
6511
  });
6275
6512
  /**
@@ -6293,7 +6530,7 @@ class Publisher {
6293
6530
  this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
6294
6531
  const { candidate } = e;
6295
6532
  if (!candidate) {
6296
- this.logger('debug', 'null ice candidate');
6533
+ logger$3('debug', 'null ice candidate');
6297
6534
  return;
6298
6535
  }
6299
6536
  yield this.sfuClient.iceTrickle({
@@ -6322,7 +6559,12 @@ class Publisher {
6322
6559
  * Restarts the ICE connection and renegotiates with the SFU.
6323
6560
  */
6324
6561
  this.restartIce = () => __awaiter(this, void 0, void 0, function* () {
6325
- this.logger('debug', 'Restarting ICE connection');
6562
+ logger$3('debug', 'Restarting ICE connection');
6563
+ const signalingState = this.pc.signalingState;
6564
+ if (this.isIceRestarting || signalingState === 'have-local-offer') {
6565
+ logger$3('debug', 'ICE restart is already in progress');
6566
+ return;
6567
+ }
6326
6568
  yield this.negotiate({ iceRestart: true });
6327
6569
  });
6328
6570
  this.onNegotiationNeeded = () => __awaiter(this, void 0, void 0, function* () {
@@ -6334,6 +6576,8 @@ class Publisher {
6334
6576
  * @param options the optional offer options to use.
6335
6577
  */
6336
6578
  this.negotiate = (options) => __awaiter(this, void 0, void 0, function* () {
6579
+ var _b;
6580
+ this.isIceRestarting = (_b = options === null || options === void 0 ? void 0 : options.iceRestart) !== null && _b !== void 0 ? _b : false;
6337
6581
  const offer = yield this.pc.createOffer(options);
6338
6582
  offer.sdp = this.mungeCodecs(offer.sdp);
6339
6583
  const trackInfos = this.getCurrentTrackInfos(offer.sdp);
@@ -6352,21 +6596,19 @@ class Publisher {
6352
6596
  });
6353
6597
  }
6354
6598
  catch (e) {
6355
- this.logger('error', `setRemoteDescription error`, {
6599
+ logger$3('error', `setRemoteDescription error`, {
6356
6600
  sdp: response.sdp,
6357
6601
  error: e,
6358
6602
  });
6359
6603
  }
6604
+ this.isIceRestarting = false;
6360
6605
  this.sfuClient.iceTrickleBuffer.publisherCandidates.subscribe((candidate) => __awaiter(this, void 0, void 0, function* () {
6361
6606
  try {
6362
6607
  const iceCandidate = JSON.parse(candidate.iceCandidate);
6363
6608
  yield this.pc.addIceCandidate(iceCandidate);
6364
6609
  }
6365
6610
  catch (e) {
6366
- this.logger('error', `ICE candidate error`, {
6367
- error: e,
6368
- candidate,
6369
- });
6611
+ logger$3('warn', `ICE candidate error`, [e, candidate]);
6370
6612
  }
6371
6613
  }));
6372
6614
  });
@@ -6392,10 +6634,10 @@ class Publisher {
6392
6634
  if (defaultMid)
6393
6635
  return defaultMid;
6394
6636
  if (!sdp) {
6395
- this.logger('warn', 'No SDP found. Returning empty mid');
6637
+ logger$3('warn', 'No SDP found. Returning empty mid');
6396
6638
  return '';
6397
6639
  }
6398
- this.logger('debug', `No 'mid' found for track. Trying to find it from the Offer SDP`);
6640
+ logger$3('debug', `No 'mid' found for track. Trying to find it from the Offer SDP`);
6399
6641
  const parsedSdp = SDP.parse(sdp);
6400
6642
  const media = parsedSdp.media.find((m) => {
6401
6643
  var _a, _b;
@@ -6404,12 +6646,12 @@ class Publisher {
6404
6646
  ((_b = (_a = m.msid) === null || _a === void 0 ? void 0 : _a.includes(track.id)) !== null && _b !== void 0 ? _b : true));
6405
6647
  });
6406
6648
  if (typeof (media === null || media === void 0 ? void 0 : media.mid) === 'undefined') {
6407
- this.logger('debug', `No mid found in SDP for track type ${track.kind} and id ${track.id}. Attempting to find a heuristic mid`);
6649
+ logger$3('debug', `No mid found in SDP for track type ${track.kind} and id ${track.id}. Attempting to find a heuristic mid`);
6408
6650
  const heuristicMid = this.transceiverInitOrder.indexOf(trackType);
6409
6651
  if (heuristicMid !== -1) {
6410
6652
  return String(heuristicMid);
6411
6653
  }
6412
- this.logger('debug', 'No heuristic mid found. Returning empty mid');
6654
+ logger$3('debug', 'No heuristic mid found. Returning empty mid');
6413
6655
  return '';
6414
6656
  }
6415
6657
  return String(media.mid);
@@ -6435,7 +6677,7 @@ class Publisher {
6435
6677
  else {
6436
6678
  // we report the last known optimal layers for ended tracks
6437
6679
  optimalLayers = this.trackLayersCache[trackType] || [];
6438
- this.logger('debug', `Track ${TrackType[trackType]} is ended. Announcing last known optimal layers`, optimalLayers);
6680
+ logger$3('debug', `Track ${TrackType[trackType]} is ended. Announcing last known optimal layers`, optimalLayers);
6439
6681
  }
6440
6682
  const layers = optimalLayers.map((optimalLayer) => ({
6441
6683
  rid: optimalLayer.rid || '',
@@ -6462,38 +6704,41 @@ class Publisher {
6462
6704
  this.onIceCandidateError = (e) => {
6463
6705
  const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
6464
6706
  `${e.errorCode}: ${e.errorText}`;
6465
- this.logger('error', `ICE Candidate error`, errorMessage);
6707
+ logger$3('error', `ICE Candidate error`, errorMessage);
6466
6708
  };
6467
6709
  this.onIceConnectionStateChange = () => {
6468
6710
  const state = this.pc.iceConnectionState;
6469
- this.logger('debug', `ICE Connection state changed to`, state);
6711
+ logger$3('debug', `ICE Connection state changed to`, state);
6470
6712
  if (state === 'failed') {
6471
- this.logger('warn', `Attempting to restart ICE`);
6713
+ logger$3('warn', `Attempting to restart ICE`);
6472
6714
  this.restartIce().catch((e) => {
6473
- this.logger('error', `ICE restart error`, e);
6715
+ logger$3('error', `ICE restart error`, e);
6474
6716
  });
6475
6717
  }
6476
6718
  else if (state === 'disconnected') {
6477
6719
  // when in `disconnected` state, the browser may recover automatically,
6478
6720
  // hence, we delay the ICE restart
6479
- this.logger('warn', `Scheduling ICE restart in 5 seconds`);
6721
+ logger$3('warn', `Scheduling ICE restart in ${this.iceRestartDelay} ms.`);
6480
6722
  setTimeout(() => {
6481
6723
  // check if the state is still `disconnected` or `failed`
6482
6724
  // as the connection may have recovered (or failed) in the meantime
6483
6725
  if (this.pc.iceConnectionState === 'disconnected' ||
6484
6726
  this.pc.iceConnectionState === 'failed') {
6485
6727
  this.restartIce().catch((e) => {
6486
- this.logger('error', `ICE restart error`, e);
6728
+ logger$3('error', `ICE restart error`, e);
6487
6729
  });
6488
6730
  }
6489
- }, 5000);
6731
+ else {
6732
+ logger$3('debug', `Scheduled ICE restart: connection recovered, canceled.`);
6733
+ }
6734
+ }, this.iceRestartDelay);
6490
6735
  }
6491
6736
  };
6492
6737
  this.onIceGatheringStateChange = () => {
6493
- this.logger('debug', `ICE Gathering State`, this.pc.iceGatheringState);
6738
+ logger$3('debug', `ICE Gathering State`, this.pc.iceGatheringState);
6494
6739
  };
6495
6740
  this.onSignalingStateChange = () => {
6496
- this.logger('debug', `Signaling state changed`, this.pc.signalingState);
6741
+ logger$3('debug', `Signaling state changed`, this.pc.signalingState);
6497
6742
  };
6498
6743
  this.ridToVideoQuality = (rid) => {
6499
6744
  return rid === 'q'
@@ -6505,9 +6750,19 @@ class Publisher {
6505
6750
  this.pc = this.createPeerConnection(connectionConfig);
6506
6751
  this.sfuClient = sfuClient;
6507
6752
  this.state = state;
6753
+ this.dispatcher = dispatcher;
6508
6754
  this.isDtxEnabled = isDtxEnabled;
6509
6755
  this.isRedEnabled = isRedEnabled;
6510
6756
  this.preferredVideoCodec = preferredVideoCodec;
6757
+ this.iceRestartDelay = iceRestartDelay;
6758
+ this.unsubscribeOnIceRestart = dispatcher.on('iceRestart', (message) => __awaiter(this, void 0, void 0, function* () {
6759
+ if (message.eventPayload.oneofKind !== 'iceRestart')
6760
+ return;
6761
+ const { iceRestart } = message.eventPayload;
6762
+ if (iceRestart.peerType !== PeerType.PUBLISHER_UNSPECIFIED)
6763
+ return;
6764
+ yield this.restartIce();
6765
+ }));
6511
6766
  }
6512
6767
  }
6513
6768
 
@@ -6524,8 +6779,10 @@ class Subscriber {
6524
6779
  * @param dispatcher the dispatcher to use.
6525
6780
  * @param state the state of the call.
6526
6781
  * @param connectionConfig the connection configuration to use.
6782
+ * @param iceRestartDelay the delay in milliseconds to wait before restarting ICE when connection goes to `disconnected` state.
6527
6783
  */
6528
- constructor({ sfuClient, dispatcher, state, connectionConfig, }) {
6784
+ constructor({ sfuClient, dispatcher, state, connectionConfig, iceRestartDelay = 2500, }) {
6785
+ this.isIceRestarting = false;
6529
6786
  /**
6530
6787
  * Creates a new `RTCPeerConnection` instance with the given configuration.
6531
6788
  *
@@ -6545,6 +6802,7 @@ class Subscriber {
6545
6802
  */
6546
6803
  this.close = () => {
6547
6804
  this.unregisterOnSubscriberOffer();
6805
+ this.unregisterOnIceRestart();
6548
6806
  this.pc.close();
6549
6807
  };
6550
6808
  /**
@@ -6617,10 +6875,25 @@ class Subscriber {
6617
6875
  /**
6618
6876
  * Restarts the ICE connection and renegotiates with the SFU.
6619
6877
  */
6620
- this.restartIce = () => {
6878
+ this.restartIce = () => __awaiter(this, void 0, void 0, function* () {
6621
6879
  logger$2('debug', 'Restarting ICE connection');
6622
- this.pc.restartIce();
6623
- };
6880
+ if (this.pc.signalingState === 'have-remote-offer') {
6881
+ logger$2('debug', 'ICE restart is already in progress');
6882
+ return;
6883
+ }
6884
+ const previousIsIceRestarting = this.isIceRestarting;
6885
+ try {
6886
+ this.isIceRestarting = true;
6887
+ yield this.sfuClient.iceRestart({
6888
+ peerType: PeerType.SUBSCRIBER,
6889
+ });
6890
+ }
6891
+ catch (e) {
6892
+ // restore the previous state, as our intent for restarting ICE failed
6893
+ this.isIceRestarting = previousIsIceRestarting;
6894
+ throw e;
6895
+ }
6896
+ });
6624
6897
  this.handleOnTrack = (e) => {
6625
6898
  const [primaryStream] = e.streams;
6626
6899
  // example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
@@ -6684,22 +6957,50 @@ class Subscriber {
6684
6957
  yield this.pc.addIceCandidate(iceCandidate);
6685
6958
  }
6686
6959
  catch (e) {
6687
- logger$2('error', `ICE candidate error`, [e, candidate]);
6960
+ logger$2('warn', `ICE candidate error`, [e, candidate]);
6688
6961
  }
6689
6962
  }));
6690
- // apply ice candidates
6691
6963
  const answer = yield this.pc.createAnswer();
6692
6964
  yield this.pc.setLocalDescription(answer);
6693
6965
  yield this.sfuClient.sendAnswer({
6694
6966
  peerType: PeerType.SUBSCRIBER,
6695
6967
  sdp: answer.sdp || '',
6696
6968
  });
6969
+ this.isIceRestarting = false;
6697
6970
  });
6698
6971
  this.onIceConnectionStateChange = () => {
6699
- logger$2('info', `ICE connection state changed`, this.pc.iceConnectionState);
6972
+ const state = this.pc.iceConnectionState;
6973
+ logger$2('debug', `ICE connection state changed`, state);
6974
+ // do nothing when ICE is restarting
6975
+ if (this.isIceRestarting)
6976
+ return;
6977
+ if (state === 'failed') {
6978
+ logger$2('warn', `Attempting to restart ICE`);
6979
+ this.restartIce().catch((e) => {
6980
+ logger$2('error', `ICE restart failed`, e);
6981
+ });
6982
+ }
6983
+ else if (state === 'disconnected') {
6984
+ // when in `disconnected` state, the browser may recover automatically,
6985
+ // hence, we delay the ICE restart
6986
+ logger$2('warn', `Scheduling ICE restart in ${this.iceRestartDelay} ms.`);
6987
+ setTimeout(() => {
6988
+ // check if the state is still `disconnected` or `failed`
6989
+ // as the connection may have recovered (or failed) in the meantime
6990
+ if (this.pc.iceConnectionState === 'disconnected' ||
6991
+ this.pc.iceConnectionState === 'failed') {
6992
+ this.restartIce().catch((e) => {
6993
+ logger$2('error', `ICE restart failed`, e);
6994
+ });
6995
+ }
6996
+ else {
6997
+ logger$2('debug', `Scheduled ICE restart: connection recovered, canceled.`);
6998
+ }
6999
+ }, 5000);
7000
+ }
6700
7001
  };
6701
7002
  this.onIceGatheringStateChange = () => {
6702
- logger$2('info', `ICE gathering state changed`, this.pc.iceGatheringState);
7003
+ logger$2('debug', `ICE gathering state changed`, this.pc.iceGatheringState);
6703
7004
  };
6704
7005
  this.onIceCandidateError = (e) => {
6705
7006
  const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
@@ -6709,6 +7010,7 @@ class Subscriber {
6709
7010
  this.sfuClient = sfuClient;
6710
7011
  this.dispatcher = dispatcher;
6711
7012
  this.state = state;
7013
+ this.iceRestartDelay = iceRestartDelay;
6712
7014
  this.pc = this.createPeerConnection(connectionConfig);
6713
7015
  this.unregisterOnSubscriberOffer = dispatcher.on('subscriberOffer', (message) => __awaiter(this, void 0, void 0, function* () {
6714
7016
  if (message.eventPayload.oneofKind !== 'subscriberOffer')
@@ -6716,6 +7018,14 @@ class Subscriber {
6716
7018
  const { subscriberOffer } = message.eventPayload;
6717
7019
  yield this.negotiate(subscriberOffer);
6718
7020
  }));
7021
+ this.unregisterOnIceRestart = dispatcher.on('iceRestart', (message) => __awaiter(this, void 0, void 0, function* () {
7022
+ if (message.eventPayload.oneofKind !== 'iceRestart')
7023
+ return;
7024
+ const { iceRestart } = message.eventPayload;
7025
+ if (iceRestart.peerType !== PeerType.SUBSCRIBER)
7026
+ return;
7027
+ yield this.restartIce();
7028
+ }));
6719
7029
  }
6720
7030
  }
6721
7031
 
@@ -6902,6 +7212,7 @@ class StreamSfuClient {
6902
7212
  this.pingIntervalInMs = 10 * 1000;
6903
7213
  this.unhealthyTimeoutInMs = this.pingIntervalInMs + 5 * 1000;
6904
7214
  this.close = (code = 1000, reason = 'Requested signal connection close') => {
7215
+ this.logger('debug', 'Closing SFU WS connection', code, reason);
6905
7216
  this.signalWs.close(code, reason);
6906
7217
  this.unsubscribeIceTrickle();
6907
7218
  clearInterval(this.keepAliveInterval);
@@ -6922,6 +7233,9 @@ class StreamSfuClient {
6922
7233
  this.iceTrickle = (data) => __awaiter(this, void 0, void 0, function* () {
6923
7234
  return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
6924
7235
  });
7236
+ this.iceRestart = (data) => __awaiter(this, void 0, void 0, function* () {
7237
+ return retryable(() => this.rpc.iceRestart(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
7238
+ });
6925
7239
  this.updateMuteState = (trackType, muted) => __awaiter(this, void 0, void 0, function* () {
6926
7240
  return this.updateMuteStates({
6927
7241
  muteStates: [
@@ -6973,7 +7287,6 @@ class StreamSfuClient {
6973
7287
  if (this.lastMessageTimestamp) {
6974
7288
  const timeSinceLastMessage = new Date().getTime() - this.lastMessageTimestamp.getTime();
6975
7289
  if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
6976
- this.logger('debug', 'SFU connection unhealthy, closing');
6977
7290
  this.close(4001, `SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`);
6978
7291
  }
6979
7292
  }
@@ -6984,10 +7297,9 @@ class StreamSfuClient {
6984
7297
  this.edgeName = sfuServer.edge_name;
6985
7298
  this.token = token;
6986
7299
  this.logger = getLogger(['sfu-client']);
6987
- const logger = this.logger;
6988
7300
  const logInterceptor = {
6989
- interceptUnary(next, method, input, options) {
6990
- logger('trace', `Calling SFU RPC method ${method.name}`, {
7301
+ interceptUnary: (next, method, input, options) => {
7302
+ this.logger('trace', `Calling SFU RPC method ${method.name}`, {
6991
7303
  input,
6992
7304
  options,
6993
7305
  });
@@ -9156,11 +9468,13 @@ class Call {
9156
9468
  */
9157
9469
  this.leave = ({ reject = false } = {}) => __awaiter(this, void 0, void 0, function* () {
9158
9470
  var _a, _b, _c, _d;
9159
- // TODO: handle case when leave is called during JOINING
9160
9471
  const callingState = this.state.callingState;
9161
9472
  if (callingState === CallingState.LEFT) {
9162
9473
  throw new Error('Cannot leave call that has already been left.');
9163
9474
  }
9475
+ if (callingState === CallingState.JOINING) {
9476
+ yield this.assertCallJoined();
9477
+ }
9164
9478
  if (this.ringing) {
9165
9479
  // I'm the one who started the call, so I should cancel it.
9166
9480
  const hasOtherParticipants = this.state.remoteParticipants.length > 0;
@@ -9463,6 +9777,7 @@ class Call {
9463
9777
  if (!this.publisher) {
9464
9778
  this.publisher = new Publisher({
9465
9779
  sfuClient,
9780
+ dispatcher: this.dispatcher,
9466
9781
  state: this.state,
9467
9782
  connectionConfig,
9468
9783
  isDtxEnabled,
@@ -9499,6 +9814,7 @@ class Call {
9499
9814
  subscriberSdp: sdp || '',
9500
9815
  clientDetails: getClientDetails(),
9501
9816
  migration,
9817
+ fastReconnect: false,
9502
9818
  });
9503
9819
  });
9504
9820
  // 2. in parallel, wait for the SFU to send us the "joinResponse"
@@ -9564,13 +9880,6 @@ class Call {
9564
9880
  }, timeout);
9565
9881
  });
9566
9882
  };
9567
- this.assertCallJoined = () => {
9568
- return new Promise((resolve) => {
9569
- this.state.callingState$
9570
- .pipe(takeWhile((state) => state !== CallingState.JOINED, true))
9571
- .subscribe(() => resolve());
9572
- });
9573
- };
9574
9883
  /**
9575
9884
  * Starts publishing the given video stream to the call.
9576
9885
  * The stream will be stopped if the user changes an input device, or if the user leaves the call.
@@ -9801,6 +10110,13 @@ class Call {
9801
10110
  var _h;
9802
10111
  return (_h = this.publisher) === null || _h === void 0 ? void 0 : _h.updateVideoPublishQuality(enabledRids);
9803
10112
  });
10113
+ this.assertCallJoined = () => {
10114
+ return new Promise((resolve) => {
10115
+ this.state.callingState$
10116
+ .pipe(takeWhile((state) => state !== CallingState.JOINED, true), filter((s) => s === CallingState.JOINED))
10117
+ .subscribe(() => resolve());
10118
+ });
10119
+ };
9804
10120
  /**
9805
10121
  * Sends a reaction to the other call participants.
9806
10122
  *
@@ -11324,7 +11640,7 @@ class WSConnectionFallback {
11324
11640
  }
11325
11641
  }
11326
11642
 
11327
- const version = '0.1.3';
11643
+ const version = '0.1.5';
11328
11644
 
11329
11645
  const logger = getLogger(['location']);
11330
11646
  const HINT_URL = `https://hint.stream-io-video.com/`;
@@ -11387,14 +11703,6 @@ class StreamClient {
11387
11703
  });
11388
11704
  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); };
11389
11705
  this._hasConnectionID = () => Boolean(this._getConnectionID());
11390
- /**
11391
- * This will start a promise to hold API calls until `connectUser` is called, useful when user is set in `StreamVideoClient constructor`
11392
- */
11393
- this.startWaitingForConnection = () => {
11394
- this.waitForConnectPromise = new Promise((resolve) => {
11395
- this.resolveConnectPromise = resolve;
11396
- });
11397
- };
11398
11706
  /**
11399
11707
  * connectUser - Set the current user and open a WebSocket connection
11400
11708
  *
@@ -11429,11 +11737,6 @@ class StreamClient {
11429
11737
  this._setUser(user);
11430
11738
  const wsPromise = this.openConnection();
11431
11739
  this.setUserPromise = Promise.all([setTokenPromise, wsPromise]).then((result) => result[1]);
11432
- if (this.resolveConnectPromise) {
11433
- this.resolveConnectPromise();
11434
- this.waitForConnectPromise = undefined;
11435
- this.resolveConnectPromise = undefined;
11436
- }
11437
11740
  try {
11438
11741
  return yield this.setUserPromise;
11439
11742
  }
@@ -11548,11 +11851,6 @@ class StreamClient {
11548
11851
  });
11549
11852
  this.anonymous = true;
11550
11853
  yield this._setToken(user, tokenOrProvider, this.anonymous);
11551
- if (this.resolveConnectPromise) {
11552
- this.resolveConnectPromise();
11553
- this.waitForConnectPromise = undefined;
11554
- this.resolveConnectPromise = undefined;
11555
- }
11556
11854
  this._setUser(user);
11557
11855
  // some endpoints require a connection_id to be resolved.
11558
11856
  // as anonymous users aren't allowed to open WS connections, we just
@@ -11622,9 +11920,6 @@ class StreamClient {
11622
11920
  this.doAxiosRequest = (type, url, data, options = {}) => __awaiter(this, void 0, void 0, function* () {
11623
11921
  var _h;
11624
11922
  if (!options.publicEndpoint) {
11625
- if (this.waitForConnectPromise) {
11626
- yield this.waitForConnectPromise;
11627
- }
11628
11923
  yield Promise.all([
11629
11924
  this.tokenManager.tokenReady(),
11630
11925
  this.connectionIdPromise,
@@ -11962,6 +12257,7 @@ class StreamClient {
11962
12257
  class StreamVideoClient {
11963
12258
  constructor(apiKeyOrArgs, opts) {
11964
12259
  var _a, _b;
12260
+ this.logLevel = 'warn';
11965
12261
  this.eventHandlersToUnregister = [];
11966
12262
  /**
11967
12263
  * Disconnects the currently connected user from the client.
@@ -11972,7 +12268,7 @@ class StreamVideoClient {
11972
12268
  * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
11973
12269
  */
11974
12270
  this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
11975
- if (!this.streamClient.user) {
12271
+ if (!this.streamClient.user && !this.connectionPromise) {
11976
12272
  return;
11977
12273
  }
11978
12274
  const disconnectUser = () => this.streamClient.disconnectUser(timeout);
@@ -12149,14 +12445,16 @@ class StreamVideoClient {
12149
12445
  this.streamClient.setUserAgent(this.streamClient.getUserAgent() +
12150
12446
  `-video-${SdkType[sdkInfo.type].toLowerCase()}-sdk-${sdkInfo.major}.${sdkInfo.minor}.${sdkInfo.patch}`);
12151
12447
  }
12152
- this.user = apiKeyOrArgs.user;
12153
- this.token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
12154
- if (this.user) {
12155
- this.streamClient.startWaitingForConnection();
12156
- }
12157
12448
  }
12158
12449
  this.writeableStateStore = new StreamVideoWriteableStateStore();
12159
12450
  this.readOnlyStateStore = new StreamVideoReadOnlyStateStore(this.writeableStateStore);
12451
+ if (typeof apiKeyOrArgs !== 'string') {
12452
+ const user = apiKeyOrArgs.user;
12453
+ const token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
12454
+ if (user) {
12455
+ this.connectUser(user, token);
12456
+ }
12457
+ }
12160
12458
  }
12161
12459
  /**
12162
12460
  * Connects the given user to the client.
@@ -12169,24 +12467,21 @@ class StreamVideoClient {
12169
12467
  connectUser(user, token) {
12170
12468
  var _a;
12171
12469
  return __awaiter(this, void 0, void 0, function* () {
12172
- const userToConnect = user || this.user;
12173
- const tokenToUse = token || this.token;
12174
- if (!userToConnect) {
12175
- throw new Error('Connect user is called without user');
12176
- }
12177
- if (userToConnect.type === 'anonymous') {
12178
- userToConnect.id = '!anon';
12179
- return this.connectAnonymousUser(userToConnect, tokenToUse);
12180
- }
12181
- if (userToConnect.type === 'guest') {
12182
- const response = yield this.createGuestUser({
12183
- user: Object.assign(Object.assign({}, userToConnect), { role: 'guest' }),
12184
- });
12185
- return this.connectUser(response.user, response.access_token);
12470
+ if (user.type === 'anonymous') {
12471
+ user.id = '!anon';
12472
+ return this.connectAnonymousUser(user, token);
12186
12473
  }
12187
- const connectUser = () => {
12188
- return this.streamClient.connectUser(userToConnect, tokenToUse);
12474
+ let connectUser = () => {
12475
+ return this.streamClient.connectUser(user, token);
12189
12476
  };
12477
+ if (user.type === 'guest') {
12478
+ connectUser = () => __awaiter(this, void 0, void 0, function* () {
12479
+ const response = yield this.createGuestUser({
12480
+ user: Object.assign(Object.assign({}, user), { role: 'guest' }),
12481
+ });
12482
+ return this.streamClient.connectUser(response.user, response.access_token);
12483
+ });
12484
+ }
12190
12485
  this.connectionPromise = this.disconnectionPromise
12191
12486
  ? this.disconnectionPromise.then(() => connectUser())
12192
12487
  : connectUser();
@@ -12220,7 +12515,7 @@ class StreamVideoClient {
12220
12515
  if (event.type !== 'call.created')
12221
12516
  return;
12222
12517
  const { call, members } = event;
12223
- if (userToConnect.id === call.created_by.id) {
12518
+ if (user.id === call.created_by.id) {
12224
12519
  this.logger('warn', 'Received `call.created` sent by the current user');
12225
12520
  return;
12226
12521
  }
@@ -12238,7 +12533,7 @@ class StreamVideoClient {
12238
12533
  if (event.type !== 'call.ring')
12239
12534
  return;
12240
12535
  const { call, members } = event;
12241
- if (userToConnect.id === call.created_by.id) {
12536
+ if (user.id === call.created_by.id) {
12242
12537
  this.logger('debug', 'Received `call.ring` sent by the current user so ignoring the event');
12243
12538
  return;
12244
12539
  }