@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
@@ -24,12 +24,15 @@ import type {
24
24
  ConnectionChangedEvent,
25
25
  EventHandler,
26
26
  EventTypes,
27
+ LogLevel,
28
+ Logger,
27
29
  StreamClientOptions,
28
30
  TokenOrProvider,
29
31
  TokenProvider,
30
32
  User,
31
33
  UserWithId,
32
34
  } from './coordinator/connection/types';
35
+ import { getLogger, logToConsole, setLogger } from './logger';
33
36
 
34
37
  /**
35
38
  * A `StreamVideoClient` instance lets you communicate with our API, and authenticate users.
@@ -41,12 +44,16 @@ export class StreamVideoClient {
41
44
  readonly readOnlyStateStore: StreamVideoReadOnlyStateStore;
42
45
  readonly user?: User;
43
46
  readonly token?: TokenOrProvider;
47
+ readonly logLevel: LogLevel = 'warn';
48
+ readonly logger: Logger;
49
+
44
50
  private readonly writeableStateStore: StreamVideoWriteableStateStore;
45
51
  streamClient: StreamClient;
46
52
 
47
53
  private eventHandlersToUnregister: Array<() => void> = [];
48
54
  private connectionPromise: Promise<void | ConnectedEvent> | undefined;
49
55
  private disconnectionPromise: Promise<void> | undefined;
56
+ private logLevels: LogLevel[] = ['debug', 'info', 'warn', 'error'];
50
57
 
51
58
  /**
52
59
  * You should create only one instance of `StreamVideoClient`.
@@ -71,15 +78,32 @@ export class StreamVideoClient {
71
78
  },
72
79
  opts?: StreamClientOptions,
73
80
  ) {
81
+ let defaultLogger: Logger = logToConsole;
82
+ if (typeof apiKeyOrArgs === 'string') {
83
+ this.logLevel = opts?.logLevel || this.logLevel;
84
+ this.logger = opts?.logger || defaultLogger;
85
+ } else {
86
+ this.logLevel = apiKeyOrArgs.options?.logLevel || this.logLevel;
87
+ this.logger = apiKeyOrArgs.options?.logger || defaultLogger;
88
+ }
89
+
90
+ setLogger(this.filterLogs(defaultLogger));
91
+
92
+ const clientLogger = getLogger(['client']);
93
+
74
94
  if (typeof apiKeyOrArgs === 'string') {
75
95
  this.streamClient = new StreamClient(apiKeyOrArgs, {
76
96
  persistUserOnConnectionFailure: true,
77
97
  ...opts,
98
+ logLevel: this.logLevel,
99
+ logger: clientLogger,
78
100
  });
79
101
  } else {
80
102
  this.streamClient = new StreamClient(apiKeyOrArgs.apiKey, {
81
103
  persistUserOnConnectionFailure: true,
82
104
  ...apiKeyOrArgs.options,
105
+ logLevel: this.logLevel,
106
+ logger: clientLogger,
83
107
  });
84
108
 
85
109
  this.user = apiKeyOrArgs.user;
@@ -155,7 +179,7 @@ export class StreamVideoClient {
155
179
  },
156
180
  sort: [{ field: 'cid', direction: 1 }],
157
181
  }).catch((err) => {
158
- console.warn('Failed to re-watch calls', err);
182
+ this.logger('error', 'Failed to re-watch calls', err);
159
183
  });
160
184
  }
161
185
  }
@@ -167,7 +191,10 @@ export class StreamVideoClient {
167
191
  if (event.type !== 'call.created') return;
168
192
  const { call, members } = event;
169
193
  if (userToConnect.id === call.created_by.id) {
170
- console.warn('Received `call.created` sent by the current user');
194
+ this.logger(
195
+ 'warn',
196
+ 'Received `call.created` sent by the current user',
197
+ );
171
198
  return;
172
199
  }
173
200
 
@@ -189,7 +216,7 @@ export class StreamVideoClient {
189
216
  if (event.type !== 'call.ring') return;
190
217
  const { call, members } = event;
191
218
  if (userToConnect.id === call.created_by.id) {
192
- console.warn('Received `call.ring` sent by the current user');
219
+ this.logger('warn', 'Received `call.ring` sent by the current user');
193
220
  return;
194
221
  }
195
222
 
@@ -465,4 +492,20 @@ export class StreamVideoClient {
465
492
  this.connectionPromise.finally(() => (this.connectionPromise = undefined));
466
493
  return this.connectionPromise;
467
494
  };
495
+
496
+ private filterLogs = (logMethod: Logger) => {
497
+ return (
498
+ logLevel: LogLevel,
499
+ messeage: string,
500
+ extraData?: Record<string, unknown>,
501
+ tags?: string[],
502
+ ) => {
503
+ if (
504
+ this.logLevels.indexOf(logLevel) >=
505
+ this.logLevels.indexOf(this.logLevel)
506
+ ) {
507
+ logMethod(logLevel, messeage, extraData, tags);
508
+ }
509
+ };
510
+ };
468
511
  }
@@ -212,7 +212,8 @@ export class StreamClient {
212
212
  * If the user id remains the same we don't throw error
213
213
  */
214
214
  if (this.userID === user.id && this.setUserPromise) {
215
- console.warn(
215
+ this.logger(
216
+ 'warn',
216
217
  'Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.',
217
218
  );
218
219
  return this.setUserPromise;
@@ -228,7 +229,8 @@ export class StreamClient {
228
229
  (this._isUsingServerAuth() || this.node) &&
229
230
  !this.options.allowServerSideConnect
230
231
  ) {
231
- console.warn(
232
+ this.logger(
233
+ 'warn',
232
234
  '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.',
233
235
  );
234
236
  }
@@ -331,9 +333,6 @@ export class StreamClient {
331
333
  this.logger(
332
334
  'info',
333
335
  'client:openConnection() - connection already in progress',
334
- {
335
- tags: ['connection', 'client'],
336
- },
337
336
  );
338
337
  return this.wsPromise;
339
338
  }
@@ -345,9 +344,6 @@ export class StreamClient {
345
344
  this.logger(
346
345
  'info',
347
346
  'client:openConnection() - openConnection called twice, healthy connection already exists',
348
- {
349
- tags: ['connection', 'client'],
350
- },
351
347
  );
352
348
 
353
349
  return Promise.resolve();
@@ -379,9 +375,7 @@ export class StreamClient {
379
375
  * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
380
376
  */
381
377
  disconnectUser = async (timeout?: number) => {
382
- this.logger('info', 'client:disconnect() - Disconnecting the client', {
383
- tags: ['connection', 'client'],
384
- });
378
+ this.logger('info', 'client:disconnect() - Disconnecting the client');
385
379
 
386
380
  // remove the user specific fields
387
381
  delete this.user;
@@ -440,9 +434,7 @@ export class StreamClient {
440
434
  if (!(key in this.listeners)) {
441
435
  this.listeners[key] = [];
442
436
  }
443
- this.logger('info', `Attaching listener for ${key} event`, {
444
- tags: ['event', 'client'],
445
- });
437
+ this.logger('info', `Attaching listener for ${key} event`);
446
438
  this.listeners[key].push(callback);
447
439
 
448
440
  return () => {
@@ -466,9 +458,7 @@ export class StreamClient {
466
458
  this.listeners[key] = [];
467
459
  }
468
460
 
469
- this.logger('info', `Removing listener for ${key} event`, {
470
- tags: ['event', 'client'],
471
- });
461
+ this.logger('info', `Removing listener for ${key} event`);
472
462
  this.listeners[key] = this.listeners[key].filter(
473
463
  (value) => value !== callback,
474
464
  );
@@ -482,9 +472,8 @@ export class StreamClient {
482
472
  config?: AxiosRequestConfig & { maxBodyLength?: number };
483
473
  },
484
474
  ) {
485
- this.logger('info', `client: ${type} - Request - ${url}`, {
486
- tags: ['api', 'api_request', 'client'],
487
- url,
475
+ this.logger('info', `client: ${type} - Request - ${url}`);
476
+ this.logger('debug', `client: ${type} - Request payload`, {
488
477
  payload: data,
489
478
  config,
490
479
  });
@@ -495,16 +484,16 @@ export class StreamClient {
495
484
  'info',
496
485
  `client:${type} - Response - url: ${url} > status ${response.status}`,
497
486
  {
498
- tags: ['api', 'api_response', 'client'],
499
- url,
500
487
  response,
501
488
  },
502
489
  );
490
+ this.logger('debug', `client:${type} - Response payload`, {
491
+ response,
492
+ });
503
493
  }
504
494
 
505
495
  _logApiError(type: string, url: string, error: unknown) {
506
496
  this.logger('error', `client:${type} - Error - url: ${url}`, {
507
- tags: ['api', 'api_response', 'client'],
508
497
  url,
509
498
  error,
510
499
  });
@@ -629,7 +618,8 @@ export class StreamClient {
629
618
  dispatchEvent = (event: StreamVideoEvent) => {
630
619
  if (!event.received_at) event.received_at = new Date();
631
620
 
632
- console.log(`Dispatching event: ${event.type}`, event);
621
+ this.logger('info', `Dispatching event: ${event.type}`);
622
+ this.logger('debug', 'Event payload:', event);
633
623
  this._callClientListeners(event);
634
624
  };
635
625
 
@@ -696,7 +686,7 @@ export class StreamClient {
696
686
  if (this.wsFallback) {
697
687
  return await this.wsFallback.connect();
698
688
  }
699
- console.log('StreamClient.connect: this.wsConnection.connect()');
689
+ this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
700
690
  // if WSFallback is enabled, ws connect should timeout faster so fallback can try
701
691
  return await this.wsConnection.connect(
702
692
  this.options.enableWSFallback
@@ -706,12 +696,15 @@ export class StreamClient {
706
696
  } catch (err) {
707
697
  // run fallback only if it's WS/Network error and not a normal API error
708
698
  // make sure browser is online before even trying the longpoll
709
- // @ts-ignore
710
- if (this.options.enableWSFallback && isWSFailure(err) && isOnline()) {
699
+ if (
700
+ this.options.enableWSFallback &&
701
+ // @ts-ignore
702
+ isWSFailure(err) &&
703
+ isOnline(this.logger)
704
+ ) {
711
705
  this.logger(
712
- 'info',
706
+ 'warn',
713
707
  'client:connect() - WS failed, fallback to longpoll',
714
- { tags: ['connection', 'client'] },
715
708
  );
716
709
  this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
717
710
 
@@ -107,7 +107,6 @@ export class StableWSConnection {
107
107
 
108
108
  _log(msg: string, extra: UR = {}, level: LogLevel = 'info') {
109
109
  this.client.logger(level, 'connection:' + msg, {
110
- tags: ['connection'],
111
110
  ...extra,
112
111
  });
113
112
  }
@@ -496,13 +495,13 @@ export class StableWSConnection {
496
495
 
497
496
  const user = this.client.user;
498
497
  if (!user) {
499
- console.error(`User not set, can't connect to WS`);
498
+ this.client.logger('error', `User not set, can't connect to WS`);
500
499
  return;
501
500
  }
502
501
 
503
502
  const token = this.client._getToken();
504
503
  if (!token) {
505
- console.error(`Token not set, can't connect authenticate`);
504
+ this.client.logger('error', `Token not set, can't connect authenticate`);
506
505
  return;
507
506
  }
508
507
 
@@ -35,7 +35,6 @@ export class WSConnectionFallback {
35
35
 
36
36
  _log(msg: string, extra: UR = {}, level: LogLevel = 'info') {
37
37
  this.client.logger(level, 'WSConnectionFallback:' + msg, {
38
- tags: ['connection_fallback', 'connection'],
39
38
  ...extra,
40
39
  });
41
40
  }
@@ -24,7 +24,7 @@ export type { OwnUserResponse } from '../../gen/coordinator';
24
24
 
25
25
  export type ConnectAPIResponse = Promise<void | ConnectedEvent>;
26
26
 
27
- export type LogLevel = 'info' | 'error' | 'warn';
27
+ export type LogLevel = 'debug' | 'info' | 'error' | 'warn';
28
28
 
29
29
  type ErrorResponseDetails = {
30
30
  code: number;
@@ -81,7 +81,8 @@ export type CallEventTypes = StreamCallEvent['type'];
81
81
  export type Logger = (
82
82
  logLevel: LogLevel,
83
83
  message: string,
84
- extraData?: Record<string, unknown>,
84
+ extraData?: any,
85
+ tags?: string[],
85
86
  ) => void;
86
87
 
87
88
  export type StreamClientOptions = Partial<AxiosRequestConfig> & {
@@ -101,6 +102,7 @@ export type StreamClientOptions = Partial<AxiosRequestConfig> & {
101
102
  /** experimental feature, please contact support if you want this feature enabled for you */
102
103
  enableWSFallback?: boolean;
103
104
  logger?: Logger;
105
+ logLevel?: LogLevel;
104
106
  /**
105
107
  * When true, user will be persisted on client. Otherwise if `connectUser` call fails, then you need to
106
108
  * call `connectUser` again to retry.
@@ -1,3 +1,5 @@
1
+ import { Logger } from './types';
2
+
1
3
  export const sleep = (m: number): Promise<void> =>
2
4
  new Promise((r) => setTimeout(r, m));
3
5
 
@@ -111,7 +113,7 @@ export function convertErrorToJson(err: Error) {
111
113
  * isOnline safely return the navigator.online value for browser env
112
114
  * if navigator is not in global object, it always return true
113
115
  */
114
- export function isOnline() {
116
+ export function isOnline(logger: Logger) {
115
117
  const nav =
116
118
  typeof navigator !== 'undefined'
117
119
  ? navigator
@@ -120,7 +122,8 @@ export function isOnline() {
120
122
  : undefined;
121
123
 
122
124
  if (!nav) {
123
- console.warn(
125
+ logger(
126
+ 'warn',
124
127
  'isOnline failed to access window.navigator and assume browser is online',
125
128
  );
126
129
  return true;
@@ -10,6 +10,7 @@ import {
10
10
  pairwise,
11
11
  shareReplay,
12
12
  } from 'rxjs';
13
+ import { getLogger } from '../logger';
13
14
 
14
15
  const getDevices = (constraints?: MediaStreamConstraints) => {
15
16
  return new Observable<MediaDeviceInfo[]>((subscriber) => {
@@ -26,7 +27,10 @@ const getDevices = (constraints?: MediaStreamConstraints) => {
26
27
  });
27
28
  })
28
29
  .catch((error) => {
29
- console.error('Failed to get devices', error);
30
+ const logger = getLogger(['devices']);
31
+ if (logger) {
32
+ logger('error', 'Failed to get devices', error);
33
+ }
30
34
  subscriber.error(error);
31
35
  });
32
36
  });
@@ -134,7 +138,10 @@ const getStream = async (constraints: MediaStreamConstraints) => {
134
138
  try {
135
139
  return await navigator.mediaDevices.getUserMedia(constraints);
136
140
  } catch (e) {
137
- console.error(`Failed get user media`, constraints, e);
141
+ getLogger(['devices'])?.('error', `Failed get user media`, {
142
+ error: e,
143
+ constraints: constraints,
144
+ });
138
145
  throw e;
139
146
  }
140
147
  };
@@ -199,7 +206,7 @@ export const getScreenShareStream = async (
199
206
  ...options,
200
207
  });
201
208
  } catch (e) {
202
- console.error('Failed to get screen share stream', e);
209
+ getLogger(['devices'])?.('error', 'Failed to get screen share stream', e);
203
210
  throw e;
204
211
  }
205
212
  };
@@ -14,7 +14,7 @@ describe('Call Permission Events', () => {
14
14
  // @ts-expect-error
15
15
  state.updateOrAddParticipant('session-id', {
16
16
  userId: 'test',
17
- isLoggedInUser: true,
17
+ isLocalParticipant: true,
18
18
  });
19
19
  const handler = watchCallPermissionRequest(state);
20
20
  handler({
@@ -59,7 +59,7 @@ describe('Call Permission Events', () => {
59
59
  connectionQuality: ConnectionQuality.EXCELLENT,
60
60
  roles: [],
61
61
  trackLookupPrefix: '',
62
- isLoggedInUser: true,
62
+ isLocalParticipant: true,
63
63
  },
64
64
  ]);
65
65
  const handler = watchCallPermissionsUpdated(state);
@@ -1,6 +1,7 @@
1
1
  import { CallingState, CallState } from '../store';
2
2
  import { StreamVideoEvent } from '../coordinator/connection/types';
3
3
  import { Call } from '../Call';
4
+ import { getLogger } from '../logger';
4
5
 
5
6
  /**
6
7
  * Event handler that watched the delivery of `call.accepted`.
@@ -35,15 +36,21 @@ export const watchCallRejected = (call: Call) => {
35
36
  const { session: callSession } = eventCall;
36
37
 
37
38
  if (!callSession) {
38
- console.log('No call session provided. Ignoring call.rejected event.');
39
+ call.logger(
40
+ 'warn',
41
+ 'No call session provided. Ignoring call.rejected event.',
42
+ event,
43
+ );
39
44
  return;
40
45
  }
41
46
 
42
47
  const rejectedBy = callSession.rejected_by;
43
48
  const { members, callingState } = call.state;
44
49
  if (callingState !== CallingState.RINGING) {
45
- console.log(
50
+ call.logger(
51
+ 'warn',
46
52
  'Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.',
53
+ event,
47
54
  );
48
55
  return;
49
56
  }
@@ -52,12 +59,12 @@ export const watchCallRejected = (call: Call) => {
52
59
  .filter((m) => m.user_id !== call.currentUserId)
53
60
  .every((m) => rejectedBy[m.user_id]);
54
61
  if (everyoneElseRejected) {
55
- console.log('everyone rejected, leaving the call');
62
+ call.logger('info', 'everyone rejected, leaving the call');
56
63
  await call.leave();
57
64
  }
58
65
  } else {
59
66
  if (rejectedBy[eventCall.created_by.id]) {
60
- console.log('call creator rejected, leaving call');
67
+ call.logger('info', 'call creator rejected, leaving call');
61
68
  await call.leave();
62
69
  }
63
70
  }
@@ -1,5 +1,6 @@
1
1
  import { CallState } from '../store';
2
2
  import { StreamVideoEvent } from '../coordinator/connection/types';
3
+ import { getLogger } from '../logger';
3
4
 
4
5
  /**
5
6
  * Watch for call.session_started events and update the call metadata.
@@ -36,8 +37,10 @@ export const watchCallSessionParticipantJoined = (state: CallState) => {
36
37
  const { user } = event;
37
38
  state.setMetadata((metadata) => {
38
39
  if (!metadata || !metadata.session) {
39
- console.warn(
40
+ state.logger(
41
+ 'warn',
40
42
  `Received call.session_participant_joined event but the metadata structure is invalid.`,
43
+ event,
41
44
  );
42
45
  return metadata;
43
46
  }
@@ -76,8 +79,10 @@ export const watchCallSessionParticipantLeft = (state: CallState) => {
76
79
  const { user } = event;
77
80
  state.setMetadata((metadata) => {
78
81
  if (!metadata || !metadata.session) {
79
- console.warn(
82
+ state.logger(
83
+ 'warn',
80
84
  `Received call.session_participant_left event but the metadata structure is invalid.`,
85
+ event,
81
86
  );
82
87
  return metadata;
83
88
  }
package/src/logger.ts ADDED
@@ -0,0 +1,45 @@
1
+ import { LogLevel, Logger } from './coordinator/connection/types';
2
+
3
+ let logger: Logger | undefined;
4
+
5
+ export const logToConsole: Logger = (
6
+ logLevel: LogLevel,
7
+ message: string,
8
+ extraData?: Record<string, unknown>,
9
+ tags?: string[],
10
+ ) => {
11
+ let logMethod;
12
+ if (logLevel === 'error') {
13
+ logMethod = console.error;
14
+ } else if (logLevel === 'warn') {
15
+ logMethod = console.warn;
16
+ } else {
17
+ logMethod = console.log;
18
+ }
19
+
20
+ logMethod(
21
+ logLevel,
22
+ `${tags?.join(':')} - ${message}`,
23
+ extraData ? extraData : '',
24
+ );
25
+ };
26
+
27
+ export const setLogger = (l: Logger) => {
28
+ logger = l;
29
+ };
30
+
31
+ export const getLogger = (withTags?: string[]) => {
32
+ const loggerMethod = logger || (() => {});
33
+ const result: Logger = (
34
+ logLevel: LogLevel,
35
+ messeage: string,
36
+ extraData?: Record<string, unknown>,
37
+ tags?: string[],
38
+ ) => {
39
+ loggerMethod(logLevel, messeage, extraData, [
40
+ ...(tags || []),
41
+ ...(withTags || []),
42
+ ]);
43
+ };
44
+ return result;
45
+ };
@@ -1,5 +1,6 @@
1
- import { CallEventTypes } from '../coordinator/connection/types';
1
+ import { CallEventTypes, Logger } from '../coordinator/connection/types';
2
2
  import type { SfuEvent } from '../gen/video/sfu/event/events';
3
+ import { getLogger } from '../logger';
3
4
 
4
5
  export type SfuEventKinds = NonNullable<SfuEvent['eventPayload']['oneofKind']>;
5
6
 
@@ -33,18 +34,27 @@ export class Dispatcher {
33
34
  private subscribers: {
34
35
  [eventName: string]: SfuEventListener[] | undefined;
35
36
  } = {};
37
+ private logger?: Logger;
38
+
39
+ constructor() {
40
+ this.logger = getLogger(['sfu-client']);
41
+ }
36
42
 
37
43
  dispatch = (message: SfuEvent) => {
38
44
  const eventKind = message.eventPayload.oneofKind;
39
45
  if (eventKind) {
40
- // @ts-ignore
41
- console.log(`Dispatching`, eventKind, message.eventPayload[eventKind]);
46
+ this.logger?.('info', `Dispatching ${eventKind}`);
47
+ this.logger?.(
48
+ 'debug',
49
+ `Event payload`,
50
+ (message.eventPayload as any)[eventKind],
51
+ );
42
52
  const listeners = this.subscribers[eventKind];
43
53
  listeners?.forEach((fn) => {
44
54
  try {
45
55
  fn(message);
46
56
  } catch (e) {
47
- console.warn(`Listener failed with error`, e);
57
+ this.logger?.('warn', 'Listener failed with error', e);
48
58
  }
49
59
  });
50
60
  }
@@ -1,5 +1,7 @@
1
1
  import { ReplaySubject } from 'rxjs';
2
2
  import { ICETrickle, PeerType } from '../gen/video/sfu/models/models';
3
+ import { getLogger } from '../logger';
4
+ import { Logger } from '../coordinator/connection/types';
3
5
 
4
6
  /**
5
7
  * A buffer for ICE Candidates. Used for ICE Trickle:
@@ -8,6 +10,11 @@ import { ICETrickle, PeerType } from '../gen/video/sfu/models/models';
8
10
  export class IceTrickleBuffer {
9
11
  readonly subscriberCandidates = new ReplaySubject<ICETrickle>();
10
12
  readonly publisherCandidates = new ReplaySubject<ICETrickle>();
13
+ private logger?: Logger;
14
+
15
+ constructor() {
16
+ this.logger = getLogger(['sfu-client']);
17
+ }
11
18
 
12
19
  push = (iceTrickle: ICETrickle) => {
13
20
  if (iceTrickle.peerType === PeerType.SUBSCRIBER) {
@@ -15,7 +22,7 @@ export class IceTrickleBuffer {
15
22
  } else if (iceTrickle.peerType === PeerType.PUBLISHER_UNSPECIFIED) {
16
23
  this.publisherCandidates.next(iceTrickle);
17
24
  } else {
18
- console.warn(`ICETrickle, Unknown peer type`, iceTrickle);
25
+ this.logger?.('warn', `ICETrickle, Unknown peer type`, iceTrickle);
19
26
  }
20
27
  };
21
28
  }
@@ -67,7 +67,7 @@ describe('Publisher', () => {
67
67
  state.setParticipants([
68
68
  // @ts-ignore
69
69
  {
70
- isLoggedInUser: true,
70
+ isLocalParticipant: true,
71
71
  userId: 'test-user-id',
72
72
  sessionId: sessionId,
73
73
  publishedTracks: [],
package/src/rtc/codecs.ts CHANGED
@@ -1,24 +1,25 @@
1
1
  import { isReactNative } from '../helpers/platforms';
2
2
  import { removeCodec, setPreferredCodec } from '../helpers/sdp-munging';
3
+ import { getLogger } from '../logger';
3
4
 
4
5
  export const getPreferredCodecs = (
5
6
  kind: 'audio' | 'video',
6
7
  preferredCodec: string,
7
8
  codecToRemove?: string,
8
9
  ): RTCRtpCodecCapability[] | undefined => {
10
+ const logger = getLogger(['codecs']);
9
11
  if (!('getCapabilities' in RTCRtpSender)) {
10
- console.warn('RTCRtpSender.getCapabilities is not supported');
12
+ logger?.('warn', 'RTCRtpSender.getCapabilities is not supported');
11
13
  return;
12
14
  }
13
15
  const cap = RTCRtpSender.getCapabilities(kind);
14
- console.log('s4e');
15
16
  if (!cap) return;
16
17
  const matched: RTCRtpCodecCapability[] = [];
17
18
  const partialMatched: RTCRtpCodecCapability[] = [];
18
19
  const unmatched: RTCRtpCodecCapability[] = [];
19
20
  cap.codecs.forEach((c) => {
20
21
  const codec = c.mimeType.toLowerCase();
21
- console.log(c);
22
+ logger?.('debug', `Found supported codec: ${codec}`);
22
23
  const shouldRemoveCodec =
23
24
  codecToRemove && codec === `${kind}/${codecToRemove}`;
24
25
  if (shouldRemoveCodec) return;
@@ -37,11 +38,12 @@ export const getPreferredCodecs = (
37
38
  }
38
39
  return;
39
40
  }
40
- console.log('matched', matched);
41
41
  matched.push(c);
42
42
  });
43
43
 
44
- return [...matched, ...partialMatched, ...unmatched];
44
+ const result = [...matched, ...partialMatched, ...unmatched];
45
+ logger?.('info', `Preffered codecs: `, result);
46
+ return result;
45
47
  };
46
48
 
47
49
  export const getGenericSdp = async (
@@ -5,6 +5,7 @@ import {
5
5
  } from '../../gen/coordinator';
6
6
  import { JoinCallData } from '../../types';
7
7
  import { StreamClient } from '../../coordinator/connection/client';
8
+ import { getLogger } from '../../logger';
8
9
 
9
10
  /**
10
11
  * Collects all necessary information to join a call, talks to the coordinator
@@ -71,15 +72,17 @@ const getLocationHint = async () => {
71
72
  const hintURL = `https://hint.stream-io-video.com/`;
72
73
  const abortController = new AbortController();
73
74
  const timeoutId = setTimeout(() => abortController.abort(), 1000);
75
+ const logger = getLogger(['call']);
74
76
  try {
75
77
  const response = await fetch(hintURL, {
76
78
  method: 'HEAD',
77
79
  signal: abortController.signal,
78
80
  });
79
81
  const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
82
+ logger?.('info', `Location header: ${awsPop}`);
80
83
  return awsPop.substring(0, 3); // AMS1-P2 -> AMS
81
84
  } catch (e) {
82
- console.error(`Failed to get location hint from ${hintURL}`, e);
85
+ logger?.('error', `Failed to get location hint from ${hintURL}`, e);
83
86
  return 'ERR';
84
87
  } finally {
85
88
  clearTimeout(timeoutId);