livekit-client 2.3.2 → 2.4.1

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 (60) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +8 -6
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +268 -45
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/api/SignalClient.d.ts +5 -2
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/connectionHelper/checks/reconnect.d.ts.map +1 -1
  12. package/dist/src/e2ee/errors.d.ts +2 -1
  13. package/dist/src/e2ee/errors.d.ts.map +1 -1
  14. package/dist/src/e2ee/index.d.ts +1 -0
  15. package/dist/src/e2ee/index.d.ts.map +1 -1
  16. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  17. package/dist/src/logger.d.ts.map +1 -1
  18. package/dist/src/room/RTCEngine.d.ts +2 -1
  19. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  20. package/dist/src/room/Room.d.ts +2 -0
  21. package/dist/src/room/Room.d.ts.map +1 -1
  22. package/dist/src/room/errors.d.ts +5 -0
  23. package/dist/src/room/errors.d.ts.map +1 -1
  24. package/dist/src/room/events.d.ts +15 -2
  25. package/dist/src/room/events.d.ts.map +1 -1
  26. package/dist/src/room/participant/LocalParticipant.d.ts +14 -6
  27. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  28. package/dist/src/room/participant/Participant.d.ts +8 -0
  29. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  30. package/dist/src/room/timers.d.ts +4 -4
  31. package/dist/src/room/timers.d.ts.map +1 -1
  32. package/dist/src/room/track/utils.d.ts +1 -0
  33. package/dist/src/room/track/utils.d.ts.map +1 -1
  34. package/dist/ts4.2/src/api/SignalClient.d.ts +5 -2
  35. package/dist/ts4.2/src/e2ee/errors.d.ts +2 -1
  36. package/dist/ts4.2/src/e2ee/index.d.ts +1 -0
  37. package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -1
  38. package/dist/ts4.2/src/room/Room.d.ts +2 -0
  39. package/dist/ts4.2/src/room/errors.d.ts +5 -0
  40. package/dist/ts4.2/src/room/events.d.ts +15 -2
  41. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +14 -6
  42. package/dist/ts4.2/src/room/participant/Participant.d.ts +8 -0
  43. package/dist/ts4.2/src/room/timers.d.ts +4 -4
  44. package/dist/ts4.2/src/room/track/utils.d.ts +1 -0
  45. package/package.json +2 -2
  46. package/src/api/SignalClient.ts +24 -2
  47. package/src/connectionHelper/checks/reconnect.ts +6 -3
  48. package/src/e2ee/errors.ts +8 -1
  49. package/src/e2ee/index.ts +1 -0
  50. package/src/e2ee/worker/FrameCryptor.ts +15 -3
  51. package/src/logger.ts +4 -3
  52. package/src/room/DeviceManager.ts +1 -1
  53. package/src/room/RTCEngine.ts +3 -0
  54. package/src/room/Room.ts +25 -3
  55. package/src/room/errors.ts +11 -0
  56. package/src/room/events.ts +15 -0
  57. package/src/room/participant/LocalParticipant.ts +92 -10
  58. package/src/room/participant/Participant.ts +23 -0
  59. package/src/room/track/utils.test.ts +35 -1
  60. package/src/room/track/utils.ts +22 -0
@@ -18,6 +18,7 @@ import type RemoteTrack from '../track/RemoteTrack';
18
18
  import type RemoteTrackPublication from '../track/RemoteTrackPublication';
19
19
  import { Track } from '../track/Track';
20
20
  import type { TrackPublication } from '../track/TrackPublication';
21
+ import { diffAttributes } from '../track/utils';
21
22
  import type { LoggerOptions, TranscriptionSegment } from '../types';
22
23
 
23
24
  export enum ConnectionQuality {
@@ -77,6 +78,8 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
77
78
  /** client metadata, opaque to livekit */
78
79
  metadata?: string;
79
80
 
81
+ private _attributes: Record<string, string>;
82
+
80
83
  lastSpokeAt?: Date | undefined;
81
84
 
82
85
  permissions?: ParticipantPermission;
@@ -112,6 +115,11 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
112
115
  return this._kind;
113
116
  }
114
117
 
118
+ /** participant attributes, similar to metadata, but as a key/value map */
119
+ get attributes(): Readonly<Record<string, string>> {
120
+ return Object.freeze({ ...this._attributes });
121
+ }
122
+
115
123
  /** @internal */
116
124
  constructor(
117
125
  sid: string,
@@ -135,6 +143,7 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
135
143
  this.videoTrackPublications = new Map();
136
144
  this.trackPublications = new Map();
137
145
  this._kind = kind;
146
+ this._attributes = {};
138
147
  }
139
148
 
140
149
  getTrackPublications(): TrackPublication[] {
@@ -214,6 +223,7 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
214
223
  this.sid = info.sid;
215
224
  this._setName(info.name);
216
225
  this._setMetadata(info.metadata);
226
+ this._setAttributes(info.attributes);
217
227
  if (info.permission) {
218
228
  this.setPermissions(info.permission);
219
229
  }
@@ -245,6 +255,18 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
245
255
  }
246
256
  }
247
257
 
258
+ /**
259
+ * Updates metadata from server
260
+ **/
261
+ private _setAttributes(attributes: Record<string, string>) {
262
+ const diff = diffAttributes(attributes, this.attributes);
263
+ this._attributes = attributes;
264
+
265
+ if (Object.keys(diff).length > 0) {
266
+ this.emit(ParticipantEvent.AttributesChanged, diff);
267
+ }
268
+ }
269
+
248
270
  /** @internal */
249
271
  setPermissions(permissions: ParticipantPermission): boolean {
250
272
  const prevPermissions = this.permissions;
@@ -363,4 +385,5 @@ export type ParticipantEventCallbacks = {
363
385
  publication: RemoteTrackPublication,
364
386
  status: TrackPublication.SubscriptionStatus,
365
387
  ) => void;
388
+ attributesChanged: (changedAttributes: Record<string, string>) => void;
366
389
  };
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
  import { AudioCaptureOptions, VideoCaptureOptions, VideoPresets } from './options';
3
- import { constraintsForOptions, mergeDefaultOptions } from './utils';
3
+ import { constraintsForOptions, diffAttributes, mergeDefaultOptions } from './utils';
4
4
 
5
5
  describe('mergeDefaultOptions', () => {
6
6
  const audioDefaults: AudioCaptureOptions = {
@@ -109,3 +109,37 @@ describe('constraintsForOptions', () => {
109
109
  expect(videoOpts.aspectRatio).toEqual(VideoPresets.h720.resolution.aspectRatio);
110
110
  });
111
111
  });
112
+
113
+ describe('diffAttributes', () => {
114
+ it('detects changed values', () => {
115
+ const oldValues: Record<string, string> = { a: 'value', b: 'initial', c: 'value' };
116
+ const newValues: Record<string, string> = { a: 'value', b: 'updated', c: 'value' };
117
+
118
+ const diff = diffAttributes(oldValues, newValues);
119
+ expect(Object.keys(diff).length).toBe(1);
120
+ expect(diff.b).toBe('updated');
121
+ });
122
+ it('detects new values', () => {
123
+ const newValues: Record<string, string> = { a: 'value', b: 'value', c: 'value' };
124
+ const oldValues: Record<string, string> = { a: 'value', b: 'value' };
125
+
126
+ const diff = diffAttributes(oldValues, newValues);
127
+ expect(Object.keys(diff).length).toBe(1);
128
+ expect(diff.c).toBe('value');
129
+ });
130
+ it('detects deleted values as empty strings', () => {
131
+ const newValues: Record<string, string> = { a: 'value', b: 'value' };
132
+ const oldValues: Record<string, string> = { a: 'value', b: 'value', c: 'value' };
133
+
134
+ const diff = diffAttributes(oldValues, newValues);
135
+ expect(Object.keys(diff).length).toBe(1);
136
+ expect(diff.c).toBe('');
137
+ });
138
+ it('compares with undefined values', () => {
139
+ const newValues: Record<string, string> = { a: 'value', b: 'value' };
140
+
141
+ const diff = diffAttributes(undefined, newValues);
142
+ expect(Object.keys(diff).length).toBe(2);
143
+ expect(diff.a).toBe('value');
144
+ });
145
+ });
@@ -243,3 +243,25 @@ export function getLogContextFromTrack(track: Track | TrackPublication): Record<
243
243
  export function supportsSynchronizationSources(): boolean {
244
244
  return typeof RTCRtpReceiver !== 'undefined' && 'getSynchronizationSources' in RTCRtpReceiver;
245
245
  }
246
+
247
+ export function diffAttributes(
248
+ oldValues: Record<string, string> | undefined,
249
+ newValues: Record<string, string> | undefined,
250
+ ) {
251
+ if (oldValues === undefined) {
252
+ oldValues = {};
253
+ }
254
+ if (newValues === undefined) {
255
+ newValues = {};
256
+ }
257
+ const allKeys = [...Object.keys(newValues), ...Object.keys(oldValues)];
258
+ const diff: Record<string, string> = {};
259
+
260
+ for (const key of allKeys) {
261
+ if (oldValues[key] !== newValues[key]) {
262
+ diff[key] = newValues[key] ?? '';
263
+ }
264
+ }
265
+
266
+ return diff;
267
+ }