livekit-client 2.17.3 → 2.18.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 (183) 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 -7
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +7823 -5772
  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 +12 -4
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/e2ee/constants.d.ts.map +1 -1
  12. package/dist/src/e2ee/types.d.ts +6 -0
  13. package/dist/src/e2ee/types.d.ts.map +1 -1
  14. package/dist/src/e2ee/utils.d.ts +2 -1
  15. package/dist/src/e2ee/utils.d.ts.map +1 -1
  16. package/dist/src/e2ee/worker/DataCryptor.d.ts.map +1 -1
  17. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  18. package/dist/src/index.d.ts +5 -4
  19. package/dist/src/index.d.ts.map +1 -1
  20. package/dist/src/room/PCTransport.d.ts +5 -0
  21. package/dist/src/room/PCTransport.d.ts.map +1 -1
  22. package/dist/src/room/PCTransportManager.d.ts +1 -1
  23. package/dist/src/room/PCTransportManager.d.ts.map +1 -1
  24. package/dist/src/room/RTCEngine.d.ts +27 -9
  25. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  26. package/dist/src/room/Room.d.ts +13 -3
  27. package/dist/src/room/Room.d.ts.map +1 -1
  28. package/dist/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts.map +1 -1
  29. package/dist/src/room/data-track/LocalDataTrack.d.ts +48 -0
  30. package/dist/src/room/data-track/LocalDataTrack.d.ts.map +1 -0
  31. package/dist/src/room/data-track/RemoteDataTrack.d.ts +46 -0
  32. package/dist/src/room/data-track/RemoteDataTrack.d.ts.map +1 -0
  33. package/dist/src/room/data-track/depacketizer.d.ts +6 -6
  34. package/dist/src/room/data-track/depacketizer.d.ts.map +1 -1
  35. package/dist/src/room/data-track/frame.d.ts +14 -0
  36. package/dist/src/room/data-track/frame.d.ts.map +1 -1
  37. package/dist/src/room/data-track/handle.d.ts +2 -2
  38. package/dist/src/room/data-track/handle.d.ts.map +1 -1
  39. package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts +104 -0
  40. package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts.map +1 -0
  41. package/dist/src/room/data-track/incoming/errors.d.ts +24 -0
  42. package/dist/src/room/data-track/incoming/errors.d.ts.map +1 -0
  43. package/dist/src/room/data-track/incoming/pipeline.d.ts +38 -0
  44. package/dist/src/room/data-track/incoming/pipeline.d.ts.map +1 -0
  45. package/dist/src/room/data-track/incoming/types.d.ts +20 -0
  46. package/dist/src/room/data-track/incoming/types.d.ts.map +1 -0
  47. package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +63 -28
  48. package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts.map +1 -1
  49. package/dist/src/room/data-track/outgoing/errors.d.ts +20 -10
  50. package/dist/src/room/data-track/outgoing/errors.d.ts.map +1 -1
  51. package/dist/src/room/data-track/outgoing/pipeline.d.ts +9 -8
  52. package/dist/src/room/data-track/outgoing/pipeline.d.ts.map +1 -1
  53. package/dist/src/room/data-track/outgoing/types.d.ts +16 -7
  54. package/dist/src/room/data-track/outgoing/types.d.ts.map +1 -1
  55. package/dist/src/room/data-track/packet/errors.d.ts +2 -4
  56. package/dist/src/room/data-track/packet/errors.d.ts.map +1 -1
  57. package/dist/src/room/data-track/packet/extensions.d.ts +4 -4
  58. package/dist/src/room/data-track/packet/extensions.d.ts.map +1 -1
  59. package/dist/src/room/data-track/packet/index.d.ts +5 -5
  60. package/dist/src/room/data-track/packet/index.d.ts.map +1 -1
  61. package/dist/src/room/data-track/packet/serializable.d.ts +4 -4
  62. package/dist/src/room/data-track/packet/serializable.d.ts.map +1 -1
  63. package/dist/src/room/data-track/packetizer.d.ts +6 -6
  64. package/dist/src/room/data-track/packetizer.d.ts.map +1 -1
  65. package/dist/src/room/data-track/track-interfaces.d.ts +23 -0
  66. package/dist/src/room/data-track/track-interfaces.d.ts.map +1 -0
  67. package/dist/src/room/data-track/types.d.ts +15 -0
  68. package/dist/src/room/data-track/types.d.ts.map +1 -0
  69. package/dist/src/room/events.d.ts +24 -3
  70. package/dist/src/room/events.d.ts.map +1 -1
  71. package/dist/src/room/participant/LocalParticipant.d.ts +11 -1
  72. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  73. package/dist/src/room/participant/RemoteParticipant.d.ts +14 -1
  74. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  75. package/dist/src/room/token-source/TokenSource.d.ts +1 -1
  76. package/dist/src/room/token-source/TokenSource.d.ts.map +1 -1
  77. package/dist/src/room/token-source/types.d.ts +1 -0
  78. package/dist/src/room/token-source/types.d.ts.map +1 -1
  79. package/dist/src/room/utils.d.ts +2 -1
  80. package/dist/src/room/utils.d.ts.map +1 -1
  81. package/dist/src/utils/abort-signal-polyfill.d.ts +13 -0
  82. package/dist/src/utils/abort-signal-polyfill.d.ts.map +1 -0
  83. package/dist/src/utils/deferrable-map.d.ts +32 -0
  84. package/dist/src/utils/deferrable-map.d.ts.map +1 -0
  85. package/dist/src/utils/subscribeToEvents.d.ts +3 -0
  86. package/dist/src/utils/subscribeToEvents.d.ts.map +1 -1
  87. package/dist/ts4.2/api/SignalClient.d.ts +12 -4
  88. package/dist/ts4.2/e2ee/types.d.ts +6 -0
  89. package/dist/ts4.2/e2ee/utils.d.ts +2 -1
  90. package/dist/ts4.2/index.d.ts +5 -4
  91. package/dist/ts4.2/room/PCTransport.d.ts +5 -0
  92. package/dist/ts4.2/room/PCTransportManager.d.ts +1 -1
  93. package/dist/ts4.2/room/RTCEngine.d.ts +27 -9
  94. package/dist/ts4.2/room/Room.d.ts +13 -3
  95. package/dist/ts4.2/room/data-track/LocalDataTrack.d.ts +48 -0
  96. package/dist/ts4.2/room/data-track/RemoteDataTrack.d.ts +46 -0
  97. package/dist/ts4.2/room/data-track/depacketizer.d.ts +6 -6
  98. package/dist/ts4.2/room/data-track/frame.d.ts +14 -0
  99. package/dist/ts4.2/room/data-track/handle.d.ts +2 -2
  100. package/dist/ts4.2/room/data-track/incoming/IncomingDataTrackManager.d.ts +110 -0
  101. package/dist/ts4.2/room/data-track/incoming/errors.d.ts +24 -0
  102. package/dist/ts4.2/room/data-track/incoming/pipeline.d.ts +38 -0
  103. package/dist/ts4.2/room/data-track/incoming/types.d.ts +20 -0
  104. package/dist/ts4.2/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +63 -29
  105. package/dist/ts4.2/room/data-track/outgoing/errors.d.ts +20 -10
  106. package/dist/ts4.2/room/data-track/outgoing/pipeline.d.ts +9 -8
  107. package/dist/ts4.2/room/data-track/outgoing/types.d.ts +16 -7
  108. package/dist/ts4.2/room/data-track/packet/errors.d.ts +2 -4
  109. package/dist/ts4.2/room/data-track/packet/extensions.d.ts +4 -4
  110. package/dist/ts4.2/room/data-track/packet/index.d.ts +5 -6
  111. package/dist/ts4.2/room/data-track/packet/serializable.d.ts +4 -4
  112. package/dist/ts4.2/room/data-track/packetizer.d.ts +6 -6
  113. package/dist/ts4.2/room/data-track/track-interfaces.d.ts +23 -0
  114. package/dist/ts4.2/room/data-track/types.d.ts +15 -0
  115. package/dist/ts4.2/room/events.d.ts +24 -3
  116. package/dist/ts4.2/room/participant/LocalParticipant.d.ts +11 -1
  117. package/dist/ts4.2/room/participant/RemoteParticipant.d.ts +14 -1
  118. package/dist/ts4.2/room/token-source/TokenSource.d.ts +1 -1
  119. package/dist/ts4.2/room/token-source/types.d.ts +1 -0
  120. package/dist/ts4.2/room/utils.d.ts +2 -1
  121. package/dist/ts4.2/utils/abort-signal-polyfill.d.ts +13 -0
  122. package/dist/ts4.2/utils/deferrable-map.d.ts +32 -0
  123. package/dist/ts4.2/utils/subscribeToEvents.d.ts +3 -0
  124. package/package.json +4 -2
  125. package/src/api/SignalClient.test.ts +9 -4
  126. package/src/api/SignalClient.ts +116 -9
  127. package/src/e2ee/constants.ts +1 -0
  128. package/src/e2ee/types.ts +6 -0
  129. package/src/e2ee/utils.ts +4 -3
  130. package/src/e2ee/worker/DataCryptor.ts +1 -4
  131. package/src/e2ee/worker/FrameCryptor.ts +1 -4
  132. package/src/e2ee/worker/ParticipantKeyHandler.ts +1 -1
  133. package/src/index.ts +6 -4
  134. package/src/room/PCTransport.ts +41 -1
  135. package/src/room/PCTransportManager.ts +1 -1
  136. package/src/room/RTCEngine.ts +274 -112
  137. package/src/room/Room.ts +152 -15
  138. package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +9 -9
  139. package/src/room/data-track/LocalDataTrack.ts +126 -0
  140. package/src/room/data-track/RemoteDataTrack.ts +80 -0
  141. package/src/room/data-track/depacketizer.ts +23 -26
  142. package/src/room/data-track/frame.ts +28 -2
  143. package/src/room/data-track/handle.ts +2 -8
  144. package/src/room/data-track/incoming/IncomingDataTrackManager.test.ts +555 -0
  145. package/src/room/data-track/incoming/IncomingDataTrackManager.ts +589 -0
  146. package/src/room/data-track/incoming/errors.ts +57 -0
  147. package/src/room/data-track/incoming/pipeline.ts +121 -0
  148. package/src/room/data-track/incoming/types.ts +22 -0
  149. package/src/room/data-track/outgoing/OutgoingDataTrackManager.test.ts +240 -27
  150. package/src/room/data-track/outgoing/OutgoingDataTrackManager.ts +165 -84
  151. package/src/room/data-track/outgoing/errors.ts +40 -11
  152. package/src/room/data-track/outgoing/pipeline.ts +25 -23
  153. package/src/room/data-track/outgoing/types.ts +14 -6
  154. package/src/room/data-track/packet/errors.ts +2 -14
  155. package/src/room/data-track/packet/extensions.ts +21 -26
  156. package/src/room/data-track/packet/index.test.ts +22 -33
  157. package/src/room/data-track/packet/index.ts +4 -6
  158. package/src/room/data-track/packet/serializable.ts +4 -4
  159. package/src/room/data-track/packetizer.test.ts +2 -2
  160. package/src/room/data-track/packetizer.ts +7 -10
  161. package/src/room/data-track/track-interfaces.ts +53 -0
  162. package/src/room/data-track/types.ts +31 -0
  163. package/src/room/events.ts +26 -1
  164. package/src/room/participant/LocalParticipant.ts +57 -6
  165. package/src/room/participant/RemoteParticipant.ts +26 -1
  166. package/src/room/token-source/TokenSource.ts +8 -2
  167. package/src/room/token-source/types.ts +4 -0
  168. package/src/room/utils.ts +5 -1
  169. package/src/utils/abort-signal-polyfill.ts +63 -0
  170. package/src/utils/deferrable-map.ts +109 -0
  171. package/src/utils/subscribeToEvents.ts +18 -1
  172. package/dist/src/room/data-track/e2ee.d.ts +0 -12
  173. package/dist/src/room/data-track/e2ee.d.ts.map +0 -1
  174. package/dist/src/room/data-track/track.d.ts +0 -30
  175. package/dist/src/room/data-track/track.d.ts.map +0 -1
  176. package/dist/src/utils/throws.d.ts +0 -36
  177. package/dist/src/utils/throws.d.ts.map +0 -1
  178. package/dist/ts4.2/room/data-track/e2ee.d.ts +0 -12
  179. package/dist/ts4.2/room/data-track/track.d.ts +0 -30
  180. package/dist/ts4.2/utils/throws.d.ts +0 -39
  181. package/src/room/data-track/e2ee.ts +0 -14
  182. package/src/room/data-track/track.ts +0 -50
  183. package/src/utils/throws.ts +0 -42
@@ -27,8 +27,13 @@ import type { InternalRoomOptions } from '../../options';
27
27
  import TypedPromise from '../../utils/TypedPromise';
28
28
  import { PCTransportState } from '../PCTransportManager';
29
29
  import type RTCEngine from '../RTCEngine';
30
+ import { DataChannelKind } from '../RTCEngine';
30
31
  import type OutgoingDataStreamManager from '../data-stream/outgoing/OutgoingDataStreamManager';
31
32
  import type { TextStreamWriter } from '../data-stream/outgoing/StreamWriter';
33
+ import LocalDataTrack from '../data-track/LocalDataTrack';
34
+ import type OutgoingDataTrackManager from '../data-track/outgoing/OutgoingDataTrackManager';
35
+ import { DataTrackPublishError } from '../data-track/outgoing/errors';
36
+ import type { DataTrackOptions } from '../data-track/outgoing/types';
32
37
  import { defaultVideoCodec } from '../defaults';
33
38
  import {
34
39
  DeviceUnsupportedError,
@@ -150,6 +155,8 @@ export default class LocalParticipant extends Participant {
150
155
 
151
156
  private roomOutgoingDataStreamManager: OutgoingDataStreamManager;
152
157
 
158
+ private roomOutgoingDataTrackManager: OutgoingDataTrackManager;
159
+
153
160
  private pendingSignalRequests: Map<
154
161
  number,
155
162
  {
@@ -179,6 +186,7 @@ export default class LocalParticipant extends Participant {
179
186
  options: InternalRoomOptions,
180
187
  roomRpcHandlers: Map<string, (data: RpcInvocationData) => Promise<string>>,
181
188
  roomOutgoingDataStreamManager: OutgoingDataStreamManager,
189
+ roomOutgoingDataTrackManager: OutgoingDataTrackManager,
182
190
  ) {
183
191
  super(sid, identity, undefined, undefined, undefined, {
184
192
  loggerName: options.loggerName,
@@ -198,6 +206,7 @@ export default class LocalParticipant extends Participant {
198
206
  this.pendingSignalRequests = new Map();
199
207
  this.rpcHandlers = roomRpcHandlers;
200
208
  this.roomOutgoingDataStreamManager = roomOutgoingDataStreamManager;
209
+ this.roomOutgoingDataTrackManager = roomOutgoingDataTrackManager;
201
210
  }
202
211
 
203
212
  get lastCameraError(): Error | undefined {
@@ -311,6 +320,35 @@ export default class LocalParticipant extends Participant {
311
320
  }
312
321
  this.pendingSignalRequests.delete(requestId);
313
322
  }
323
+
324
+ switch (response.request.case) {
325
+ case 'publishDataTrack': {
326
+ let error;
327
+ switch (response.reason) {
328
+ case RequestResponse_Reason.NOT_ALLOWED:
329
+ error = DataTrackPublishError.notAllowed(response.message);
330
+ break;
331
+ case RequestResponse_Reason.DUPLICATE_NAME:
332
+ error = DataTrackPublishError.duplicateName(response.message);
333
+ break;
334
+ case RequestResponse_Reason.INVALID_NAME:
335
+ error = DataTrackPublishError.invalidName(response.message);
336
+ break;
337
+ case RequestResponse_Reason.LIMIT_EXCEEDED:
338
+ error = DataTrackPublishError.limitReached(response.message);
339
+ break;
340
+ default:
341
+ error = DataTrackPublishError.unknown(response.reason, response.message);
342
+ return;
343
+ }
344
+
345
+ this.roomOutgoingDataTrackManager.receivedSfuPublishResponse(
346
+ response.request.value.pubHandle,
347
+ { type: 'error', error },
348
+ );
349
+ break;
350
+ }
351
+ }
314
352
  };
315
353
 
316
354
  private handleDataPacket = (packet: DataPacket) => {
@@ -1648,7 +1686,8 @@ export default class LocalParticipant extends Participant {
1648
1686
  * @param options optionally specify a `reliable`, `topic` and `destination`
1649
1687
  */
1650
1688
  async publishData(data: Uint8Array, options: DataPublishOptions = {}): Promise<void> {
1651
- const kind = options.reliable ? DataPacket_Kind.RELIABLE : DataPacket_Kind.LOSSY;
1689
+ const kind = options.reliable ? DataChannelKind.RELIABLE : DataChannelKind.LOSSY;
1690
+ const dataPacketKind = options.reliable ? DataPacket_Kind.RELIABLE : DataPacket_Kind.LOSSY;
1652
1691
  const destinationIdentities = options.destinationIdentities;
1653
1692
  const topic = options.topic;
1654
1693
 
@@ -1660,7 +1699,7 @@ export default class LocalParticipant extends Participant {
1660
1699
  });
1661
1700
 
1662
1701
  const packet = new DataPacket({
1663
- kind: kind,
1702
+ kind: dataPacketKind,
1664
1703
  value: {
1665
1704
  case: 'user',
1666
1705
  value: userPacket,
@@ -1688,7 +1727,7 @@ export default class LocalParticipant extends Participant {
1688
1727
  },
1689
1728
  });
1690
1729
 
1691
- await this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
1730
+ await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
1692
1731
  }
1693
1732
 
1694
1733
  /** @deprecated Consider migrating to {@link sendText} */
@@ -1708,7 +1747,7 @@ export default class LocalParticipant extends Participant {
1708
1747
  }),
1709
1748
  },
1710
1749
  });
1711
- await this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
1750
+ await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
1712
1751
 
1713
1752
  this.emit(ParticipantEvent.ChatMessage, msg);
1714
1753
  return msg;
@@ -1731,7 +1770,7 @@ export default class LocalParticipant extends Participant {
1731
1770
  }),
1732
1771
  },
1733
1772
  });
1734
- await this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
1773
+ await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
1735
1774
  this.emit(ParticipantEvent.ChatMessage, msg);
1736
1775
  return msg;
1737
1776
  }
@@ -1946,7 +1985,7 @@ export default class LocalParticipant extends Participant {
1946
1985
  },
1947
1986
  });
1948
1987
 
1949
- await this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
1988
+ await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
1950
1989
  }
1951
1990
 
1952
1991
  /** @internal */
@@ -2235,4 +2274,16 @@ export default class LocalParticipant extends Participant {
2235
2274
  await sleep(20);
2236
2275
  }
2237
2276
  }
2277
+
2278
+ /** Publishes a data track.
2279
+ *
2280
+ * Returns the published data track if successful. Use {@link LocalDataTrack#tryPush}
2281
+ * to send data frames on the track.
2282
+ */
2283
+ async publishDataTrack(options: DataTrackOptions): Promise<LocalDataTrack> {
2284
+ const track = new LocalDataTrack(options, this.roomOutgoingDataTrackManager);
2285
+ await track.publish();
2286
+
2287
+ return track;
2288
+ }
2238
2289
  }
@@ -5,6 +5,8 @@ import type {
5
5
  UpdateTrackSettings,
6
6
  } from '@livekit/protocol';
7
7
  import type { SignalClient } from '../../api/SignalClient';
8
+ import { DeferrableMap } from '../../utils/deferrable-map';
9
+ import type RemoteDataTrack from '../data-track/RemoteDataTrack';
8
10
  import { ParticipantEvent, TrackEvent } from '../events';
9
11
  import RemoteAudioTrack from '../track/RemoteAudioTrack';
10
12
  import type RemoteTrack from '../track/RemoteTrack';
@@ -27,6 +29,14 @@ export default class RemoteParticipant extends Participant {
27
29
 
28
30
  trackPublications: Map<string, RemoteTrackPublication>;
29
31
 
32
+ /** A map of data track name to the corresponding {@link RemoteDataTrack}.
33
+ * @example
34
+ * // An already existing data track:
35
+ * const track = remoteParticipant.dataTracks.get("data track name");
36
+ * // Wait for a data track which will be published soon:
37
+ * const track = await remoteParticipant.dataTracks.getDeferred("data track name"); */
38
+ dataTracks: DeferrableMap<RemoteDataTrack['info']['name'], RemoteDataTrack>;
39
+
30
40
  signalClient: SignalClient;
31
41
 
32
42
  private volumeMap: Map<Track.Source, number>;
@@ -54,7 +64,7 @@ export default class RemoteParticipant extends Participant {
54
64
  protected get logContext() {
55
65
  return {
56
66
  ...super.logContext,
57
- rpID: this.sid,
67
+ remoteParticipantID: this.sid,
58
68
  remoteParticipant: this.identity,
59
69
  };
60
70
  }
@@ -75,6 +85,7 @@ export default class RemoteParticipant extends Participant {
75
85
  this.trackPublications = new Map();
76
86
  this.audioTrackPublications = new Map();
77
87
  this.videoTrackPublications = new Map();
88
+ this.dataTracks = new DeferrableMap();
78
89
  this.volumeMap = new Map();
79
90
  }
80
91
 
@@ -376,6 +387,20 @@ export default class RemoteParticipant extends Participant {
376
387
  await Promise.all(promises);
377
388
  }
378
389
 
390
+ /** @internal */
391
+ addRemoteDataTrack(remoteDataTrack: RemoteDataTrack) {
392
+ this.dataTracks.set(remoteDataTrack.info.name, remoteDataTrack);
393
+ }
394
+
395
+ /** @internal */
396
+ removeRemoteDataTrack(remoteDataTrackSid: RemoteDataTrack['info']['sid']) {
397
+ for (const [name, dataTrack] of this.dataTracks.entries()) {
398
+ if (remoteDataTrackSid === dataTrack.info.sid) {
399
+ this.dataTracks.delete(name);
400
+ }
401
+ }
402
+ }
403
+
379
404
  /** @internal */
380
405
  emit<E extends keyof ParticipantEventCallbacks>(
381
406
  event: E,
@@ -59,7 +59,7 @@ abstract class TokenSourceCached extends TokenSourceConfigurable {
59
59
  if (!isResponseTokenValid(this.cachedResponse)) {
60
60
  return false;
61
61
  }
62
- if (this.isSameAsCachedFetchOptions(fetchOptions)) {
62
+ if (!this.isSameAsCachedFetchOptions(fetchOptions)) {
63
63
  return false;
64
64
  }
65
65
  return true;
@@ -72,9 +72,15 @@ abstract class TokenSourceCached extends TokenSourceConfigurable {
72
72
  return decodeTokenPayload(this.cachedResponse.participantToken);
73
73
  }
74
74
 
75
- async fetch(options: TokenSourceFetchOptions): Promise<TokenSourceResponseObject> {
75
+ async fetch(
76
+ options: TokenSourceFetchOptions,
77
+ force?: boolean,
78
+ ): Promise<TokenSourceResponseObject> {
76
79
  const unlock = await this.fetchMutex.lock();
77
80
  try {
81
+ if (force) {
82
+ this.cachedResponse = null;
83
+ }
78
84
  if (this.shouldReturnCachedValueFromFetch(options)) {
79
85
  return this.cachedResponse!.toJson() as TokenSourceResponseObject;
80
86
  }
@@ -78,6 +78,10 @@ export type TokenSourceFetchOptions = {
78
78
  */
79
79
  export abstract class TokenSourceConfigurable {
80
80
  abstract fetch(options: TokenSourceFetchOptions): Promise<TokenSourceResponseObject>;
81
+ abstract fetch(
82
+ options: TokenSourceFetchOptions,
83
+ force?: boolean,
84
+ ): Promise<TokenSourceResponseObject>;
81
85
  }
82
86
 
83
87
  /** A TokenSource is a mechanism for fetching credentials required to connect to a LiveKit Room. */
package/src/room/utils.ts CHANGED
@@ -5,10 +5,10 @@ import {
5
5
  DisconnectReason,
6
6
  Transcription as TranscriptionModel,
7
7
  } from '@livekit/protocol';
8
+ import { type Throws } from '@livekit/throws-transformer/throws';
8
9
  import TypedPromise from '../utils/TypedPromise';
9
10
  import { getBrowser } from '../utils/browserParser';
10
11
  import type { BrowserDetails } from '../utils/browserParser';
11
- import { type Throws } from '../utils/throws';
12
12
  import { protocolVersion, version } from '../version';
13
13
  import { type ConnectionError, ConnectionErrorReason } from './errors';
14
14
  import type LocalParticipant from './participant/LocalParticipant';
@@ -775,3 +775,7 @@ export function extractMaxAgeFromRequestHeaders(headers: Headers): number | unde
775
775
  }
776
776
  return undefined;
777
777
  }
778
+
779
+ export function isCompressionStreamSupported() {
780
+ return typeof CompressionStream !== 'undefined';
781
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Implementation of AbortSignal.any
3
+ * Creates a signal that will be aborted when any of the given signals is aborted.
4
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any
5
+ */
6
+ export function abortSignalAny(signals: Array<AbortSignal>): AbortSignal {
7
+ // Handle empty signals array
8
+ if (signals.length === 0) {
9
+ const controller = new AbortController();
10
+ return controller.signal;
11
+ }
12
+
13
+ // Fast path for single signal
14
+ if (signals.length === 1) {
15
+ return signals[0];
16
+ }
17
+
18
+ // Check if any signal is already aborted
19
+ for (const signal of signals) {
20
+ if (signal.aborted) {
21
+ return signal;
22
+ }
23
+ }
24
+
25
+ // Create a new controller for the combined signal
26
+ const controller = new AbortController();
27
+ const unlisteners: Array<() => void> = Array(signals.length);
28
+
29
+ // Function to clean up all event listeners
30
+ const cleanup = () => {
31
+ for (const unsubscribe of unlisteners) {
32
+ unsubscribe();
33
+ }
34
+ };
35
+
36
+ // Add event listeners to each signal
37
+ signals.forEach((signal, index) => {
38
+ const handler = () => {
39
+ controller.abort(signal.reason);
40
+ cleanup();
41
+ };
42
+
43
+ signal.addEventListener('abort', handler);
44
+ unlisteners[index] = () => signal.removeEventListener('abort', handler);
45
+ });
46
+
47
+ return controller.signal;
48
+ }
49
+
50
+ /**
51
+ * Implementation of AbortSignal.timeout
52
+ * Creates a signal that will be aborted after the specified timeout.
53
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout
54
+ */
55
+ export function abortSignalTimeout(ms: number): AbortSignal {
56
+ const controller = new AbortController();
57
+
58
+ setTimeout(() => {
59
+ controller.abort(new DOMException(`signal timed out after ${ms} ms`, 'TimeoutError'));
60
+ }, ms);
61
+
62
+ return controller.signal;
63
+ }
@@ -0,0 +1,109 @@
1
+ import { type Throws } from '@livekit/throws-transformer/throws';
2
+ import { Future } from '../room/utils';
3
+
4
+ /** An error which is thrown if a {@link DeferrableMap#getDeferred} call is aborted midway
5
+ * through. */
6
+ export class DeferrableMapAbortError extends DOMException {
7
+ reason: unknown;
8
+
9
+ constructor(message: string, reason?: unknown) {
10
+ super(message, 'AbortError');
11
+ this.reason = reason;
12
+ }
13
+ }
14
+
15
+ /**
16
+ * A Map-like container keyed by unique strings that supports the ability to wait
17
+ * for future keys to show up in the map.
18
+ *
19
+ * @example
20
+ * // An already existing key:
21
+ * const value = map.get("key");
22
+ * // Wait for a key which will be added soon:
23
+ * const value = await map.getDeferred("key");
24
+ */
25
+ export class DeferrableMap<K, V> extends Map<K, V> {
26
+ private pending: Map<K, Array<Future<V, DeferrableMapAbortError>>> = new Map();
27
+
28
+ set(key: K, value: V): this {
29
+ super.set(key, value);
30
+
31
+ // Resolve any futures waiting on this key.
32
+ const futures = this.pending.get(key);
33
+ if (futures) {
34
+ for (const future of futures) {
35
+ if (!future.isResolved) {
36
+ future.resolve?.(value);
37
+ }
38
+ }
39
+ this.pending.delete(key);
40
+ }
41
+
42
+ return this;
43
+ }
44
+
45
+ get [Symbol.toStringTag](): string {
46
+ return 'WaitableMap';
47
+ }
48
+
49
+ /**
50
+ * Returns the value for `key` immediately if it exists, otherwise returns a
51
+ * promise that resolves once `set(key, value)` is called.
52
+ *
53
+ * If an `AbortSignal` is provided and it is aborted before the key appears,
54
+ * the returned promise rejects with an {@link DeferrableMapAbortError}.
55
+ */
56
+ getDeferred(key: K): Promise<V>;
57
+ getDeferred(key: K, signal: AbortSignal): Promise<Throws<V, DeferrableMapAbortError>>;
58
+ async getDeferred(key: K, signal?: AbortSignal) {
59
+ const existing = this.get(key);
60
+ if (typeof existing !== 'undefined') {
61
+ return existing;
62
+ }
63
+
64
+ // Bail out immediately if the signal is already aborted.
65
+ if (signal?.aborted) {
66
+ throw new DeferrableMapAbortError('The operation was aborted.', signal.reason);
67
+ }
68
+
69
+ const future = new Future<V, DeferrableMapAbortError>(undefined, () => {
70
+ // Clean up the pending list when the future settles.
71
+ const futures = this.pending.get(key);
72
+ if (!futures) {
73
+ return;
74
+ }
75
+
76
+ const idx = futures.indexOf(future);
77
+ if (idx !== -1) {
78
+ futures.splice(idx, 1);
79
+ }
80
+ if (futures.length === 0) {
81
+ this.pending.delete(key);
82
+ }
83
+ });
84
+
85
+ const existingFutures = this.pending.get(key);
86
+ if (existingFutures) {
87
+ existingFutures.push(future);
88
+ } else {
89
+ this.pending.set(key, [future]);
90
+ }
91
+
92
+ // If a signal was provided, listen for abort and reject the future.
93
+ if (signal) {
94
+ const onAbort = () => {
95
+ if (!future.isResolved) {
96
+ future.reject?.(new DeferrableMapAbortError('The operation was aborted.', signal.reason));
97
+ }
98
+ };
99
+ signal.addEventListener('abort', onAbort, { once: true });
100
+
101
+ // Clean up the listener once the future settles (resolved or rejected).
102
+ future.promise.finally(() => {
103
+ signal.removeEventListener('abort', onAbort);
104
+ });
105
+ }
106
+
107
+ return future.promise;
108
+ }
109
+ }
@@ -42,7 +42,11 @@ export function subscribeToEvents<
42
42
  >(eventName: EventName): Promise<EventPayload> {
43
43
  // If an event is already buffered which hasn't been processed yet, pull that off the buffer
44
44
  // and use it.
45
- const earliestBufferedEvent = buffers.get(eventName)!.shift();
45
+ const buffer = buffers.get(eventName);
46
+ if (!buffer) {
47
+ throw new Error(`No events were buffered / received for event "${eventName.toString()}".`);
48
+ }
49
+ const earliestBufferedEvent = buffer.shift();
46
50
  if (earliestBufferedEvent) {
47
51
  return earliestBufferedEvent as EventPayload;
48
52
  }
@@ -53,6 +57,19 @@ export function subscribeToEvents<
53
57
  const nextEvent = await future.promise;
54
58
  return nextEvent as EventPayload;
55
59
  },
60
+ /** Are there events of the given name which are waiting to be processed? Use this to assert
61
+ * that no unexpected events have been emitted. */
62
+ areThereBufferedEvents<
63
+ EventPayload extends Parameters<Callbacks[EventName]>[0],
64
+ EventName extends EventNames = EventNames,
65
+ >(eventName: EventName) {
66
+ const buffer = buffers.get(eventName);
67
+ if (buffer) {
68
+ return buffer.length > 0;
69
+ } else {
70
+ return false;
71
+ }
72
+ },
56
73
  /** Cleanup any lingering subscriptions. */
57
74
  unsubscribe: () => {
58
75
  for (const [eventName, onEvent] of eventHandlers) {
@@ -1,12 +0,0 @@
1
- export type EncryptedPayload = {
2
- payload: Uint8Array;
3
- iv: Uint8Array;
4
- keyIndex: number;
5
- };
6
- export type EncryptionProvider = {
7
- encrypt(payload: Uint8Array): EncryptedPayload;
8
- };
9
- export type DecryptionProvider = {
10
- decrypt(payload: Uint8Array, senderIdentity: string): Uint8Array;
11
- };
12
- //# sourceMappingURL=e2ee.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"e2ee.d.ts","sourceRoot":"","sources":["../../../../src/room/data-track/e2ee.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,UAAU,CAAC;IACpB,EAAE,EAAE,UAAU,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAE/B,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,gBAAgB,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,GAAG,UAAU,CAAC;CAClE,CAAC"}
@@ -1,30 +0,0 @@
1
- import type { DataTrackFrame } from './frame';
2
- import { type DataTrackHandle } from './handle';
3
- import type OutgoingDataTrackManager from './outgoing/OutgoingDataTrackManager';
4
- export type DataTrackSid = string;
5
- /** Information about a published data track. */
6
- export type DataTrackInfo = {
7
- sid: DataTrackSid;
8
- pubHandle: DataTrackHandle;
9
- name: String;
10
- usesE2ee: boolean;
11
- };
12
- export declare class LocalDataTrack {
13
- info: DataTrackInfo;
14
- protected manager: OutgoingDataTrackManager;
15
- constructor(info: DataTrackInfo, manager: OutgoingDataTrackManager);
16
- /** The raw descriptor from the manager containing the internal state for this local track. */
17
- protected get descriptor(): import("./outgoing/OutgoingDataTrackManager").Descriptor | null;
18
- isPublished(): boolean;
19
- /** Try pushing a frame to subscribers of the track.
20
- *
21
- * Pushing a frame can fail for several reasons:
22
- *
23
- * - The track has been unpublished by the local participant or SFU
24
- * - The room is no longer connected
25
- */
26
- tryPush(payload: DataTrackFrame['payload']): void & {
27
- readonly __throws?: import("./outgoing/errors").DataTrackPushFrameError<import("./outgoing/errors").DataTrackPushFrameErrorReason.Dropped> | import("./outgoing/errors").DataTrackPushFrameError<import("./outgoing/errors").DataTrackPushFrameErrorReason.TrackUnpublished> | undefined;
28
- };
29
- }
30
- //# sourceMappingURL=track.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../../../src/room/data-track/track.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,wBAAwB,MAAM,qCAAqC,CAAC;AAEhF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC,gDAAgD;AAChD,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,YAAY,CAAC;IAClB,SAAS,EAAE,eAAe,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,qBAAa,cAAc;IACzB,IAAI,EAAE,aAAa,CAAC;IAEpB,SAAS,CAAC,OAAO,EAAE,wBAAwB,CAAC;gBAEhC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,wBAAwB;IAKlE,8FAA8F;IAC9F,SAAS,KAAK,UAAU,oEAEvB;IAED,WAAW;IAIX;;;;;;OAMG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC;;;CAS3C"}
@@ -1,36 +0,0 @@
1
- type Primitives = null | undefined | string | number | bigint | boolean | symbol;
2
- /**
3
- * Branded type that encodes possible thrown errors in the return type.
4
- *
5
- * Usage:
6
- * function fetchUser(id: string): Throws<User, NetworkError | NotFoundError> { ... }
7
- *
8
- * The actual runtime value is just T - the error types are phantom types
9
- * that exist only for static analysis.
10
- *
11
- * To indicate that a function shouldn't throw any errors, make it return `Throws<T, never>`.
12
- *
13
- * For more info about how this is checked, see ./throws-transformer at the root of this repo.
14
- */
15
- export type Throws<T, E extends Error> = (T & {
16
- readonly __throws?: E;
17
- }) | Extract<T, Primitives>;
18
- /**
19
- * Extract the error types from a Throws type.
20
- */
21
- export type ExtractErrors<T> = T extends Throws<any, infer E> ? E : never;
22
- /**
23
- * Extract the success type from a Throws type.
24
- */
25
- export type ExtractSuccess<T> = T extends Throws<infer S, any> ? S : T;
26
- /**
27
- * Combine error types from multiple Throws types.
28
- */
29
- export type CombineErrors<T extends any[]> = T extends [infer First, ...infer Rest] ? ExtractErrors<First> | CombineErrors<Rest> : never;
30
- /**
31
- * Helper to propagate errors - use this when your function calls other
32
- * throwing functions and wants to propagate their errors.
33
- */
34
- export type PropagatesErrors<T, AdditionalErrors extends Error = never> = Throws<ExtractSuccess<T>, ExtractErrors<T> | AdditionalErrors>;
35
- export {};
36
- //# sourceMappingURL=throws.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"throws.d.ts","sourceRoot":"","sources":["../../../src/utils/throws.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAElG;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,GAC/E,aAAa,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,GAC1C,KAAK,CAAC;AAEV;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,gBAAgB,SAAS,KAAK,GAAG,KAAK,IAAI,MAAM,CAC9E,cAAc,CAAC,CAAC,CAAC,EACjB,aAAa,CAAC,CAAC,CAAC,GAAG,gBAAgB,CACpC,CAAC"}
@@ -1,12 +0,0 @@
1
- export type EncryptedPayload = {
2
- payload: Uint8Array;
3
- iv: Uint8Array;
4
- keyIndex: number;
5
- };
6
- export type EncryptionProvider = {
7
- encrypt(payload: Uint8Array): EncryptedPayload;
8
- };
9
- export type DecryptionProvider = {
10
- decrypt(payload: Uint8Array, senderIdentity: string): Uint8Array;
11
- };
12
- //# sourceMappingURL=e2ee.d.ts.map
@@ -1,30 +0,0 @@
1
- import type { DataTrackFrame } from './frame';
2
- import type { DataTrackHandle } from './handle';
3
- import type OutgoingDataTrackManager from './outgoing/OutgoingDataTrackManager';
4
- export type DataTrackSid = string;
5
- /** Information about a published data track. */
6
- export type DataTrackInfo = {
7
- sid: DataTrackSid;
8
- pubHandle: DataTrackHandle;
9
- name: String;
10
- usesE2ee: boolean;
11
- };
12
- export declare class LocalDataTrack {
13
- info: DataTrackInfo;
14
- protected manager: OutgoingDataTrackManager;
15
- constructor(info: DataTrackInfo, manager: OutgoingDataTrackManager);
16
- /** The raw descriptor from the manager containing the internal state for this local track. */
17
- protected get descriptor(): import("./outgoing/OutgoingDataTrackManager").Descriptor | null;
18
- isPublished(): boolean;
19
- /** Try pushing a frame to subscribers of the track.
20
- *
21
- * Pushing a frame can fail for several reasons:
22
- *
23
- * - The track has been unpublished by the local participant or SFU
24
- * - The room is no longer connected
25
- */
26
- tryPush(payload: DataTrackFrame['payload']): void & {
27
- readonly __throws?: import("./outgoing/errors").DataTrackPushFrameError<import("./outgoing/errors").DataTrackPushFrameErrorReason.Dropped> | import("./outgoing/errors").DataTrackPushFrameError<import("./outgoing/errors").DataTrackPushFrameErrorReason.TrackUnpublished> | undefined;
28
- };
29
- }
30
- //# sourceMappingURL=track.d.ts.map
@@ -1,39 +0,0 @@
1
- type Primitives = null | undefined | string | number | bigint | boolean | symbol;
2
- /**
3
- * Branded type that encodes possible thrown errors in the return type.
4
- *
5
- * Usage:
6
- * function fetchUser(id: string): Throws<User, NetworkError | NotFoundError> { ... }
7
- *
8
- * The actual runtime value is just T - the error types are phantom types
9
- * that exist only for static analysis.
10
- *
11
- * To indicate that a function shouldn't throw any errors, make it return `Throws<T, never>`.
12
- *
13
- * For more info about how this is checked, see ./throws-transformer at the root of this repo.
14
- */
15
- export type Throws<T, E extends Error> = (T & {
16
- readonly __throws?: E;
17
- }) | Extract<T, Primitives>;
18
- /**
19
- * Extract the error types from a Throws type.
20
- */
21
- export type ExtractErrors<T> = T extends Throws<any, infer E> ? E : never;
22
- /**
23
- * Extract the success type from a Throws type.
24
- */
25
- export type ExtractSuccess<T> = T extends Throws<infer S, any> ? S : T;
26
- /**
27
- * Combine error types from multiple Throws types.
28
- */
29
- export type CombineErrors<T extends any[]> = T extends [
30
- infer First,
31
- ...infer Rest
32
- ] ? ExtractErrors<First> | CombineErrors<Rest> : never;
33
- /**
34
- * Helper to propagate errors - use this when your function calls other
35
- * throwing functions and wants to propagate their errors.
36
- */
37
- export type PropagatesErrors<T, AdditionalErrors extends Error = never> = Throws<ExtractSuccess<T>, ExtractErrors<T> | AdditionalErrors>;
38
- export {};
39
- //# sourceMappingURL=throws.d.ts.map
@@ -1,14 +0,0 @@
1
- export type EncryptedPayload = {
2
- payload: Uint8Array;
3
- iv: Uint8Array; // NOTE: should be 12 bytes long
4
- keyIndex: number;
5
- };
6
-
7
- export type EncryptionProvider = {
8
- // FIXME: add in explicit `Throws<..., EncryptionError>`?
9
- encrypt(payload: Uint8Array): EncryptedPayload;
10
- };
11
-
12
- export type DecryptionProvider = {
13
- decrypt(payload: Uint8Array, senderIdentity: string): Uint8Array;
14
- };