@stream-io/video-client 1.18.7 → 1.18.8

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 (51) hide show
  1. package/CHANGELOG.md +97 -169
  2. package/dist/index.browser.es.js +89 -52
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +89 -52
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.es.js +89 -52
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/src/Call.d.ts +10 -1
  9. package/dist/src/devices/ScreenShareManager.d.ts +1 -3
  10. package/dist/src/gen/video/sfu/event/events.d.ts +1 -19
  11. package/dist/src/gen/video/sfu/signal_rpc/signal.client.d.ts +2 -21
  12. package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +1 -9
  13. package/dist/src/helpers/promise.d.ts +2 -2
  14. package/package.json +10 -11
  15. package/src/Call.ts +61 -10
  16. package/src/StreamSfuClient.ts +9 -3
  17. package/src/StreamVideoClient.ts +4 -5
  18. package/src/__tests__/Call.test.ts +1 -1
  19. package/src/coordinator/connection/client.ts +2 -3
  20. package/src/coordinator/connection/connection.ts +14 -14
  21. package/src/coordinator/connection/signing.ts +1 -1
  22. package/src/devices/BrowserPermission.ts +3 -2
  23. package/src/devices/ScreenShareManager.ts +1 -3
  24. package/src/devices/__tests__/InputMediaDeviceManager.test.ts +1 -1
  25. package/src/devices/__tests__/MicrophoneManager.test.ts +4 -4
  26. package/src/devices/__tests__/MicrophoneManagerRN.test.ts +4 -4
  27. package/src/devices/devices.ts +3 -1
  28. package/src/events/__tests__/call.test.ts +42 -57
  29. package/src/events/__tests__/internal.test.ts +8 -13
  30. package/src/events/__tests__/mutes.test.ts +7 -3
  31. package/src/events/__tests__/participant.test.ts +16 -20
  32. package/src/events/__tests__/speaker.test.ts +6 -6
  33. package/src/gen/coordinator/index.ts +1 -1
  34. package/src/gen/video/sfu/event/events.ts +22 -20
  35. package/src/gen/video/sfu/models/models.ts +0 -1
  36. package/src/gen/video/sfu/signal_rpc/signal.client.ts +27 -23
  37. package/src/gen/video/sfu/signal_rpc/signal.ts +13 -11
  38. package/src/helpers/RNSpeechDetector.ts +3 -4
  39. package/src/helpers/__tests__/DynascaleManager.test.ts +27 -26
  40. package/src/helpers/__tests__/clientUtils.test.ts +0 -1
  41. package/src/helpers/client-details.ts +1 -1
  42. package/src/helpers/promise.ts +4 -4
  43. package/src/rtc/Dispatcher.ts +1 -1
  44. package/src/rtc/Publisher.ts +2 -2
  45. package/src/rtc/__tests__/Publisher.test.ts +8 -8
  46. package/src/rtc/__tests__/Subscriber.test.ts +9 -9
  47. package/src/rtc/__tests__/mocks/webrtc.mocks.ts +2 -2
  48. package/src/rtc/helpers/__tests__/sdp.test.ts +3 -3
  49. package/src/stats/CallStateStatsReporter.ts +2 -3
  50. package/src/store/__tests__/CallState.test.ts +59 -115
  51. package/src/timers/worker.ts +0 -4
@@ -1,31 +1,35 @@
1
- /* eslint-disable */
2
1
  // @generated by protobuf-ts 2.9.4 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
3
2
  // @generated from protobuf file "video/sfu/signal_rpc/signal.proto" (package "stream.video.sfu.signal", syntax proto3)
4
3
  // tslint:disable
5
- import type { RpcTransport } from '@protobuf-ts/runtime-rpc';
6
- import type { ServiceInfo } from '@protobuf-ts/runtime-rpc';
4
+ import type {
5
+ RpcOptions,
6
+ RpcTransport,
7
+ ServiceInfo,
8
+ UnaryCall,
9
+ } from '@protobuf-ts/runtime-rpc';
10
+ import { stackIntercept } from '@protobuf-ts/runtime-rpc';
11
+ import type {
12
+ ICERestartRequest,
13
+ ICERestartResponse,
14
+ ICETrickleResponse,
15
+ SendAnswerRequest,
16
+ SendAnswerResponse,
17
+ SendStatsRequest,
18
+ SendStatsResponse,
19
+ SetPublisherRequest,
20
+ SetPublisherResponse,
21
+ StartNoiseCancellationRequest,
22
+ StartNoiseCancellationResponse,
23
+ StopNoiseCancellationRequest,
24
+ StopNoiseCancellationResponse,
25
+ UpdateMuteStatesRequest,
26
+ UpdateMuteStatesResponse,
27
+ UpdateSubscriptionsRequest,
28
+ UpdateSubscriptionsResponse,
29
+ } from './signal';
7
30
  import { SignalServer } from './signal';
8
- import type { StopNoiseCancellationResponse } from './signal';
9
- import type { StopNoiseCancellationRequest } from './signal';
10
- import type { StartNoiseCancellationResponse } from './signal';
11
- import type { StartNoiseCancellationRequest } from './signal';
12
- import type { SendStatsResponse } from './signal';
13
- import type { SendStatsRequest } from './signal';
14
- import type { ICERestartResponse } from './signal';
15
- import type { ICERestartRequest } from './signal';
16
- import type { UpdateMuteStatesResponse } from './signal';
17
- import type { UpdateMuteStatesRequest } from './signal';
18
- import type { UpdateSubscriptionsResponse } from './signal';
19
- import type { UpdateSubscriptionsRequest } from './signal';
20
- import type { ICETrickleResponse } from './signal';
21
31
  import type { ICETrickle } from '../models/models';
22
- import type { SendAnswerResponse } from './signal';
23
- import type { SendAnswerRequest } from './signal';
24
- import { stackIntercept } from '@protobuf-ts/runtime-rpc';
25
- import type { SetPublisherResponse } from './signal';
26
- import type { SetPublisherRequest } from './signal';
27
- import type { UnaryCall } from '@protobuf-ts/runtime-rpc';
28
- import type { RpcOptions } from '@protobuf-ts/runtime-rpc';
32
+
29
33
  /**
30
34
  * @generated from protobuf service stream.video.sfu.signal.SignalServer
31
35
  */
@@ -1,19 +1,21 @@
1
- /* eslint-disable */
2
1
  // @generated by protobuf-ts 2.9.4 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
3
2
  // @generated from protobuf file "video/sfu/signal_rpc/signal.proto" (package "stream.video.sfu.signal", syntax proto3)
4
3
  // tslint:disable
5
- import { ICETrickle } from '../models/models';
4
+ import {
5
+ AndroidState,
6
+ AppleState,
7
+ Error,
8
+ ICETrickle,
9
+ InputDevices,
10
+ PeerType,
11
+ TrackInfo,
12
+ TrackType,
13
+ VideoDimension,
14
+ WebsocketReconnectStrategy,
15
+ } from '../models/models';
6
16
  import { ServiceType } from '@protobuf-ts/runtime-rpc';
7
17
  import { MessageType } from '@protobuf-ts/runtime';
8
- import { TrackInfo } from '../models/models';
9
- import { VideoDimension } from '../models/models';
10
- import { TrackType } from '../models/models';
11
- import { PeerType } from '../models/models';
12
- import { AppleState } from '../models/models';
13
- import { AndroidState } from '../models/models';
14
- import { InputDevices } from '../models/models';
15
- import { WebsocketReconnectStrategy } from '../models/models';
16
- import { Error } from '../models/models';
18
+
17
19
  /**
18
20
  * @generated from protobuf message stream.video.sfu.signal.StartNoiseCancellationRequest
19
21
  */
@@ -33,7 +33,7 @@ export class RNSpeechDetector {
33
33
  e.streams[0].getTracks().forEach((track) => {
34
34
  // In RN, the remote track is automatically added to the audio output device
35
35
  // so we need to mute it to avoid hearing the audio back
36
- // @ts-ignore _setVolume is a private method in react-native-webrtc
36
+ // @ts-expect-error _setVolume is a private method in react-native-webrtc
37
37
  track._setVolume(0);
38
38
  });
39
39
  });
@@ -79,10 +79,9 @@ export class RNSpeechDetector {
79
79
  const initialBaselineNoiseLevel = 0.13;
80
80
  let baselineNoiseLevel = initialBaselineNoiseLevel;
81
81
  let speechDetected = false;
82
- let intervalId: NodeJS.Timeout | undefined;
83
82
  let speechTimer: NodeJS.Timeout | undefined;
84
83
  let silenceTimer: NodeJS.Timeout | undefined;
85
- let audioLevelHistory = []; // Store recent audio levels for smoother detection
84
+ const audioLevelHistory: number[] = []; // Store recent audio levels for smoother detection
86
85
  const historyLength = 10;
87
86
  const silenceThreshold = 1.1;
88
87
  const resetThreshold = 0.9;
@@ -157,7 +156,7 @@ export class RNSpeechDetector {
157
156
  };
158
157
 
159
158
  // Call checkAudioLevel periodically (every 100ms)
160
- intervalId = setInterval(checkAudioLevel, 100);
159
+ const intervalId = setInterval(checkAudioLevel, 100);
161
160
 
162
161
  return () => {
163
162
  clearInterval(intervalId);
@@ -42,7 +42,7 @@ describe('DynascaleManager', () => {
42
42
  },
43
43
  );
44
44
 
45
- // @ts-ignore
45
+ // @ts-expect-error incomplete data
46
46
  call.state.updateOrAddParticipant('session-id', {
47
47
  userId: 'user-id',
48
48
  sessionId: 'session-id',
@@ -90,9 +90,9 @@ describe('DynascaleManager', () => {
90
90
 
91
91
  beforeEach(() => {
92
92
  videoElement = document.createElement('video');
93
- // @ts-ignore
93
+ // @ts-expect-error private property
94
94
  videoElement.clientWidth = 100;
95
- // @ts-ignore
95
+ // @ts-expect-error private property
96
96
  videoElement.clientHeight = 100;
97
97
  });
98
98
 
@@ -100,17 +100,16 @@ describe('DynascaleManager', () => {
100
100
  vi.useFakeTimers();
101
101
  const audioElement = document.createElement('audio');
102
102
  const play = vi.spyOn(audioElement, 'play').mockResolvedValue();
103
- // @ts-expect-error setSinkId is not defined in types
104
103
  audioElement.setSinkId = vi.fn();
105
104
 
106
- // @ts-ignore
105
+ // @ts-expect-error incomplete data
107
106
  call.state.updateOrAddParticipant('session-id', {
108
107
  userId: 'user-id',
109
108
  sessionId: 'session-id',
110
109
  publishedTracks: [],
111
110
  });
112
111
 
113
- // @ts-ignore
112
+ // @ts-expect-error incomplete data
114
113
  call.state.updateOrAddParticipant('session-id-local', {
115
114
  userId: 'user-id-local',
116
115
  sessionId: 'session-id-local',
@@ -134,15 +133,10 @@ describe('DynascaleManager', () => {
134
133
 
135
134
  expect(play).toHaveBeenCalled();
136
135
  expect(audioElement.srcObject).toBe(mediaStream);
137
-
138
136
  expect(audioElement.volume).toBe(1);
139
-
140
- // @ts-expect-error setSinkId is not defined in types
141
137
  expect(audioElement.setSinkId).not.toHaveBeenCalled();
142
138
 
143
139
  call.speaker.select('different-device-id');
144
-
145
- // @ts-expect-error setSinkId is not defined in types
146
140
  expect(audioElement.setSinkId).toHaveBeenCalledWith(
147
141
  'different-device-id',
148
142
  );
@@ -164,7 +158,7 @@ describe('DynascaleManager', () => {
164
158
  const audioElement = document.createElement('audio');
165
159
  const play = vi.spyOn(audioElement, 'play').mockResolvedValue();
166
160
 
167
- // @ts-ignore
161
+ // @ts-expect-error incomplete data
168
162
  call.state.updateOrAddParticipant('session-id', {
169
163
  userId: 'user-id',
170
164
  sessionId: 'session-id',
@@ -199,7 +193,7 @@ describe('DynascaleManager', () => {
199
193
  'updateParticipantTracks',
200
194
  );
201
195
 
202
- // @ts-ignore
196
+ // @ts-expect-error incomplete data
203
197
  call.state.updateOrAddParticipant('session-id', {
204
198
  userId: 'user-id',
205
199
  sessionId: 'session-id',
@@ -257,7 +251,7 @@ describe('DynascaleManager', () => {
257
251
  );
258
252
  const play = vi.spyOn(videoElement, 'play').mockResolvedValue();
259
253
 
260
- // @ts-ignore
254
+ // @ts-expect-error incomplete data
261
255
  call.state.updateOrAddParticipant('session-id', {
262
256
  userId: 'user-id',
263
257
  sessionId: 'session-id',
@@ -297,7 +291,7 @@ describe('DynascaleManager', () => {
297
291
  });
298
292
 
299
293
  it('video: should update subscription when element becomes visible', () => {
300
- // @ts-ignore
294
+ // @ts-expect-error incomplete data
301
295
  call.state.updateOrAddParticipant('session-id', {
302
296
  userId: 'user-id',
303
297
  sessionId: 'session-id',
@@ -374,7 +368,7 @@ describe('DynascaleManager', () => {
374
368
  });
375
369
 
376
370
  it('video: should update subscription when element resizes', () => {
377
- // @ts-ignore
371
+ // @ts-expect-error incomplete data
378
372
  call.state.updateOrAddParticipant('session-id', {
379
373
  userId: 'user-id',
380
374
  sessionId: 'session-id',
@@ -385,12 +379,16 @@ describe('DynascaleManager', () => {
385
379
  },
386
380
  });
387
381
 
388
- let updateSubscription = vi.spyOn(call.state, 'updateParticipantTracks');
382
+ const updateSubscription = vi.spyOn(
383
+ call.state,
384
+ 'updateParticipantTracks',
385
+ );
389
386
 
390
- let resizeObserverCallback: ResizeObserverCallback;
387
+ let resizeObserverCallback: ResizeObserverCallback | undefined =
388
+ undefined;
391
389
  window.ResizeObserver = class ResizeObserver {
392
390
  observe = vi.fn().mockImplementation(() => {
393
- // @ts-ignore simulate initial trigger
391
+ // @ts-expect-error simulate initial trigger
394
392
  resizeObserverCallback();
395
393
  });
396
394
  unobserve = vi.fn();
@@ -416,12 +414,12 @@ describe('DynascaleManager', () => {
416
414
  },
417
415
  });
418
416
 
419
- // @ts-ignore simulate resize
417
+ // @ts-expect-error simulate resize
420
418
  videoElement.clientHeight = 101;
421
- // @ts-ignore simulate resize
419
+ // @ts-expect-error simulate resize
422
420
  videoElement.clientWidth = 101;
423
421
 
424
- // @ts-ignore simulate resize
422
+ // @ts-expect-error simulate resize
425
423
  resizeObserverCallback();
426
424
 
427
425
  expect(updateSubscription).toHaveBeenCalledWith('videoTrack', {
@@ -436,7 +434,7 @@ describe('DynascaleManager', () => {
436
434
  });
437
435
 
438
436
  it('video: should unsubscribe when element dimensions are zero', () => {
439
- // @ts-ignore
437
+ // @ts-expect-error incomplete data
440
438
  call.state.updateOrAddParticipant('session-id', {
441
439
  userId: 'user-id',
442
440
  sessionId: 'session-id',
@@ -447,11 +445,14 @@ describe('DynascaleManager', () => {
447
445
  },
448
446
  });
449
447
 
450
- let updateSubscription = vi.spyOn(call.state, 'updateParticipantTracks');
448
+ const updateSubscription = vi.spyOn(
449
+ call.state,
450
+ 'updateParticipantTracks',
451
+ );
451
452
 
452
- // @ts-ignore simulate resize
453
+ // @ts-expect-error simulate resize
453
454
  videoElement.clientHeight = 0;
454
- // @ts-ignore simulate resize
455
+ // @ts-expect-error simulate resize
455
456
  videoElement.clientWidth = 0;
456
457
 
457
458
  const cleanup = dynascaleManager.bindVideoElement(
@@ -72,7 +72,6 @@ describe('clientUtils', () => {
72
72
 
73
73
  it('should use default x-stream-client header', () => {
74
74
  const sdk = getSdkInfo();
75
- // @ts-expect-error
76
75
  setSdkInfo(undefined);
77
76
  const client = createCoordinatorClient('apiKey', {});
78
77
  expect(client).toBeDefined();
@@ -151,7 +151,7 @@ export const getClientDetails = async (): Promise<ClientDetails> => {
151
151
  'platform',
152
152
  'platformVersion',
153
153
  ]);
154
- } catch (e) {
154
+ } catch {
155
155
  // Ignore the error
156
156
  }
157
157
  }
@@ -50,8 +50,8 @@ export type PromiseWithResolvers<T> = {
50
50
  promise: Promise<T>;
51
51
  resolve: (value: T | PromiseLike<T>) => void;
52
52
  reject: (reason: any) => void;
53
- isResolved: boolean;
54
- isRejected: boolean;
53
+ isResolved: () => boolean;
54
+ isRejected: () => boolean;
55
55
  };
56
56
 
57
57
  /**
@@ -85,7 +85,7 @@ export const promiseWithResolvers = <T = void>(): PromiseWithResolvers<T> => {
85
85
  promise,
86
86
  resolve: resolver,
87
87
  reject: rejecter,
88
- isResolved,
89
- isRejected,
88
+ isResolved: () => isResolved,
89
+ isRejected: () => isRejected,
90
90
  };
91
91
  };
@@ -20,7 +20,7 @@ export type DispatchableMessage<K extends SfuEventKinds> = {
20
20
  };
21
21
  };
22
22
 
23
- const sfuEventKinds: { [key in SfuEventKinds]: undefined } = {
23
+ const sfuEventKinds: Record<SfuEventKinds, undefined> = {
24
24
  subscriberOffer: undefined,
25
25
  publisherAnswer: undefined,
26
26
  connectionQualityChanged: undefined,
@@ -250,8 +250,8 @@ export class Publisher extends BasePeerConnection {
250
250
  ? // for SVC, we only have one layer (q) and often rid is omitted
251
251
  enabledLayers[0]
252
252
  : // for non-SVC, we need to find the layer by rid (simulcast)
253
- enabledLayers.find((l) => l.name === encoder.rid) ??
254
- (params.encodings.length === 1 ? enabledLayers[0] : undefined);
253
+ (enabledLayers.find((l) => l.name === encoder.rid) ??
254
+ (params.encodings.length === 1 ? enabledLayers[0] : undefined));
255
255
 
256
256
  // flip 'active' flag only when necessary
257
257
  const shouldActivate = !!layer?.active;
@@ -51,7 +51,7 @@ describe('Publisher', () => {
51
51
  // @ts-expect-error readonly field
52
52
  sfuClient.iceTrickleBuffer = new IceTrickleBuffer();
53
53
 
54
- // @ts-ignore
54
+ // @ts-expect-error private field
55
55
  sfuClient['sessionId'] = sessionId;
56
56
 
57
57
  state = new CallState();
@@ -84,7 +84,7 @@ describe('Publisher', () => {
84
84
  describe('Publishing', () => {
85
85
  it('should throw when publishing ended tracks', async () => {
86
86
  const track = new MediaStreamTrack();
87
- // @ts-ignore readonly field
87
+ // @ts-expect-error readonly field
88
88
  track.readyState = 'ended';
89
89
  await expect(publisher.publish(track, TrackType.VIDEO)).rejects.toThrow();
90
90
  });
@@ -128,7 +128,7 @@ describe('Publisher', () => {
128
128
  vi.spyOn(track, 'clone').mockReturnValue(clone);
129
129
 
130
130
  const transceiver = new RTCRtpTransceiver();
131
- // @ts-ignore test setup
131
+ // @ts-expect-error test setup
132
132
  transceiver.sender.track = track;
133
133
  publisher['transceiverCache'].add(
134
134
  publisher['publishOptions'][0],
@@ -218,9 +218,9 @@ describe('Publisher', () => {
218
218
  });
219
219
 
220
220
  it(`should drop consequent ICE restart requests`, async () => {
221
- // @ts-ignore
221
+ // @ts-expect-error private method
222
222
  publisher['pc'].signalingState = 'have-local-offer';
223
- // @ts-ignore
223
+ // @ts-expect-error private method
224
224
  vi.spyOn(publisher, 'negotiate').mockResolvedValue();
225
225
 
226
226
  await publisher.restartIce();
@@ -229,7 +229,7 @@ describe('Publisher', () => {
229
229
 
230
230
  it(`should perform ICE restart when connection state changes to 'failed'`, () => {
231
231
  vi.spyOn(publisher, 'restartIce').mockResolvedValue();
232
- // @ts-ignore
232
+ // @ts-expect-error private api
233
233
  publisher['pc'].iceConnectionState = 'failed';
234
234
  publisher['onIceConnectionStateChange']();
235
235
  expect(publisher.restartIce).toHaveBeenCalled();
@@ -237,7 +237,7 @@ describe('Publisher', () => {
237
237
 
238
238
  it(`should perform ICE restart when connection state changes to 'disconnected'`, () => {
239
239
  vi.spyOn(publisher, 'restartIce').mockResolvedValue();
240
- // @ts-ignore
240
+ // @ts-expect-error private api
241
241
  publisher['pc'].iceConnectionState = 'disconnected';
242
242
  publisher['onIceConnectionStateChange']();
243
243
  expect(publisher.restartIce).toHaveBeenCalled();
@@ -564,7 +564,7 @@ describe('Publisher', () => {
564
564
 
565
565
  const track = new MediaStreamTrack();
566
566
  const transceiver = new RTCRtpTransceiver();
567
- // @ts-ignore test setup
567
+ // @ts-expect-error test setup
568
568
  transceiver.sender.track = track;
569
569
 
570
570
  publisher['transceiverCache'].add(publishOptions[0], transceiver);
@@ -20,7 +20,7 @@ vi.mock('../../StreamSfuClient', () => {
20
20
  describe('Subscriber', () => {
21
21
  let sfuClient: StreamSfuClient;
22
22
  let subscriber: Subscriber;
23
- let state = new CallState();
23
+ const state = new CallState();
24
24
  let dispatcher: Dispatcher;
25
25
 
26
26
  beforeEach(() => {
@@ -61,7 +61,7 @@ describe('Subscriber', () => {
61
61
  describe('Subscriber ICE restart', () => {
62
62
  it(`should drop consequent ICE restart requests`, async () => {
63
63
  sfuClient.iceRestart = vi.fn();
64
- // @ts-ignore
64
+ // @ts-expect-error - private field
65
65
  subscriber['pc'].signalingState = 'have-remote-offer';
66
66
 
67
67
  await subscriber.restartIce();
@@ -70,7 +70,7 @@ describe('Subscriber', () => {
70
70
 
71
71
  it('should skip ICE restart when connection is still new', async () => {
72
72
  sfuClient.iceRestart = vi.fn();
73
- // @ts-ignore
73
+ // @ts-expect-error - private field
74
74
  subscriber['pc'].connectionState = 'new';
75
75
 
76
76
  await subscriber.restartIce();
@@ -79,7 +79,7 @@ describe('Subscriber', () => {
79
79
 
80
80
  it('should ask the SFU for ICE restart', async () => {
81
81
  sfuClient.iceRestart = vi.fn();
82
- // @ts-ignore
82
+ // @ts-expect-error - private field
83
83
  subscriber['pc'].connectionState = 'connected';
84
84
 
85
85
  await subscriber.restartIce();
@@ -90,7 +90,7 @@ describe('Subscriber', () => {
90
90
 
91
91
  it(`should perform ICE restart when connection state changes to 'failed'`, () => {
92
92
  vi.spyOn(subscriber, 'restartIce').mockResolvedValue();
93
- // @ts-ignore
93
+ // @ts-expect-error - private field
94
94
  subscriber['pc'].iceConnectionState = 'failed';
95
95
  subscriber['onIceConnectionStateChange']();
96
96
  expect(subscriber.restartIce).toHaveBeenCalled();
@@ -98,7 +98,7 @@ describe('Subscriber', () => {
98
98
 
99
99
  it(`should perform ICE restart when connection state changes to 'disconnected'`, () => {
100
100
  vi.spyOn(subscriber, 'restartIce').mockResolvedValue();
101
- // @ts-ignore
101
+ // @ts-expect-error - private field
102
102
  subscriber['pc'].iceConnectionState = 'disconnected';
103
103
  subscriber['onIceConnectionStateChange']();
104
104
  expect(subscriber.restartIce).toHaveBeenCalled();
@@ -109,7 +109,7 @@ describe('Subscriber', () => {
109
109
  it('should add unknown tracks to the to the call state', () => {
110
110
  const mediaStream = new MediaStream();
111
111
  const mediaStreamTrack = new MediaStreamTrack();
112
- // @ts-ignore - mock
112
+ // @ts-expect-error - mock
113
113
  mediaStream.id = '123:TRACK_TYPE_VIDEO';
114
114
 
115
115
  const registerOrphanedTrackSpy = vi.spyOn(state, 'registerOrphanedTrack');
@@ -131,7 +131,7 @@ describe('Subscriber', () => {
131
131
  it('should assign known tracks to the participant', () => {
132
132
  const mediaStream = new MediaStream();
133
133
  const mediaStreamTrack = new MediaStreamTrack();
134
- // @ts-ignore - mock
134
+ // @ts-expect-error - mock
135
135
  mediaStream.id = '123:TRACK_TYPE_VIDEO';
136
136
 
137
137
  const registerOrphanedTrackSpy = vi.spyOn(state, 'registerOrphanedTrack');
@@ -156,7 +156,7 @@ describe('Subscriber', () => {
156
156
  it('should replace participant stream when a new one arrives', () => {
157
157
  const mediaStream = new MediaStream();
158
158
  const mediaStreamTrack = new MediaStreamTrack();
159
- // @ts-ignore - mock
159
+ // @ts-expect-error - mock
160
160
  mediaStream.id = '123:TRACK_TYPE_VIDEO';
161
161
 
162
162
  const updateParticipantSpy = vi.spyOn(state, 'updateParticipant');
@@ -51,7 +51,7 @@ vi.stubGlobal('MediaStreamTrack', MediaStreamTrackMock);
51
51
 
52
52
  const RTCRtpTransceiverMock = vi.fn((): Partial<RTCRtpTransceiver> => {
53
53
  return {
54
- // @ts-ignore
54
+ // @ts-expect-error - incomplete mock
55
55
  sender: {
56
56
  track: null,
57
57
  replaceTrack: vi.fn(),
@@ -84,7 +84,7 @@ vi.stubGlobal('RTCRtpReceiver', RTCRtpReceiverMock);
84
84
  const RTCRtpSenderMock = vi.fn((): Partial<typeof RTCRtpSender> => {
85
85
  return {
86
86
  getCapabilities: vi.fn(),
87
- // @ts-ignore
87
+ // @ts-expect-error - incomplete mock
88
88
  track: vi.fn(),
89
89
  };
90
90
  });
@@ -29,7 +29,7 @@ a=rtcp-fb:96 nack pli
29
29
  describe('sdp', () => {
30
30
  it('should extract mid from transceiver', () => {
31
31
  const transceiver = new RTCRtpTransceiver();
32
- // @ts-ignore - mid is a readonly property
32
+ // @ts-expect-error - mid is a readonly property
33
33
  transceiver.mid = '10';
34
34
  expect(extractMid(transceiver, -1, '')).toBe('10');
35
35
  });
@@ -40,7 +40,7 @@ describe('sdp', () => {
40
40
 
41
41
  it('should extract mid from SDP', () => {
42
42
  const track = new MediaStreamTrack();
43
- // @ts-ignore - id is a readonly property
43
+ // @ts-expect-error - id is a readonly property
44
44
  track.id = '8d240fd6-26a1-40f6-a769-4d7d24cfd286';
45
45
  const transceiver = new RTCRtpTransceiver();
46
46
  vi.spyOn(transceiver.sender, 'track', 'get').mockReturnValue(track);
@@ -50,7 +50,7 @@ describe('sdp', () => {
50
50
 
51
51
  it('should fallback to transceiverInitIndex when mid can not be found in SDP', () => {
52
52
  const track = new MediaStreamTrack();
53
- // @ts-ignore - id is a readonly property
53
+ // @ts-expect-error - id is a readonly property
54
54
  track.id = 'not-known';
55
55
  const transceiver = new RTCRtpTransceiver();
56
56
  vi.spyOn(transceiver.sender, 'track', 'get').mockReturnValue(track);
@@ -98,9 +98,9 @@ export const createStatsReporter = ({
98
98
  for (const track of tracks) {
99
99
  const report = await pc.getStats(track);
100
100
  const stats = transform(report, {
101
- // @ts-ignore
102
- trackKind: track.kind,
101
+ trackKind: track.kind as 'audio' | 'video',
103
102
  kind,
103
+ publisher: undefined,
104
104
  });
105
105
  statsForStream.push(stats);
106
106
  }
@@ -298,7 +298,6 @@ const transform = (
298
298
  jitter: rtcStreamStats.jitter,
299
299
  kind: rtcStreamStats.kind,
300
300
  mediaSourceId: rtcStreamStats.mediaSourceId,
301
- // @ts-ignore: available in Chrome only, TS doesn't recognize this
302
301
  qualityLimitationReason: rtcStreamStats.qualityLimitationReason,
303
302
  rid: rtcStreamStats.rid,
304
303
  ssrc: rtcStreamStats.ssrc,