livekit-client 2.5.10 → 2.6.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +54 -0
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +431 -45
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +2 -0
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/RegionUrlProvider.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/errors.d.ts +2 -2
- package/dist/src/room/errors.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +56 -0
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/rpc.d.ts +96 -0
- package/dist/src/room/rpc.d.ts.map +1 -0
- package/dist/src/room/track/RemoteAudioTrack.d.ts +1 -1
- package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts +2 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/utils.d.ts +2 -2
- package/dist/src/room/track/utils.d.ts.map +1 -1
- package/dist/ts4.2/src/index.d.ts +2 -0
- package/dist/ts4.2/src/room/PCTransport.d.ts +2 -0
- package/dist/ts4.2/src/room/errors.d.ts +2 -2
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +56 -0
- package/dist/ts4.2/src/room/rpc.d.ts +96 -0
- package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +1 -1
- package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/utils.d.ts +2 -2
- package/package.json +2 -2
- package/src/api/SignalClient.ts +19 -3
- package/src/index.ts +2 -0
- package/src/room/PCTransport.ts +42 -29
- package/src/room/PCTransportManager.ts +6 -1
- package/src/room/RTCEngine.ts +13 -3
- package/src/room/RegionUrlProvider.ts +3 -1
- package/src/room/Room.ts +9 -3
- package/src/room/errors.ts +2 -2
- package/src/room/participant/LocalParticipant.test.ts +304 -0
- package/src/room/participant/LocalParticipant.ts +340 -1
- package/src/room/rpc.ts +172 -0
- package/src/room/track/RemoteAudioTrack.ts +1 -1
- package/src/room/track/RemoteVideoTrack.ts +1 -1
- package/src/room/track/utils.ts +1 -6
@@ -0,0 +1,96 @@
|
|
1
|
+
import { RpcError as RpcError_Proto } from '@livekit/protocol';
|
2
|
+
/** Parameters for initiating an RPC call */
|
3
|
+
export interface PerformRpcParams {
|
4
|
+
/** The `identity` of the destination participant */
|
5
|
+
destinationIdentity: string;
|
6
|
+
/** The method name to call */
|
7
|
+
method: string;
|
8
|
+
/** The method payload */
|
9
|
+
payload: string;
|
10
|
+
/** Timeout for receiving a response after initial connection (milliseconds). Default: 10000 */
|
11
|
+
responseTimeout?: number;
|
12
|
+
}
|
13
|
+
/**
|
14
|
+
* Data passed to method handler for incoming RPC invocations
|
15
|
+
*/
|
16
|
+
export interface RpcInvocationData {
|
17
|
+
/**
|
18
|
+
* The unique request ID. Will match at both sides of the call, useful for debugging or logging.
|
19
|
+
*/
|
20
|
+
requestId: string;
|
21
|
+
/**
|
22
|
+
* The unique participant identity of the caller.
|
23
|
+
*/
|
24
|
+
callerIdentity: string;
|
25
|
+
/**
|
26
|
+
* The payload of the request. User-definable format, typically JSON.
|
27
|
+
*/
|
28
|
+
payload: string;
|
29
|
+
/**
|
30
|
+
* The maximum time the caller will wait for a response.
|
31
|
+
*/
|
32
|
+
responseTimeout: number;
|
33
|
+
}
|
34
|
+
/**
|
35
|
+
* Specialized error handling for RPC methods.
|
36
|
+
*
|
37
|
+
* Instances of this type, when thrown in a method handler, will have their `message`
|
38
|
+
* serialized and sent across the wire. The sender will receive an equivalent error on the other side.
|
39
|
+
*
|
40
|
+
* Built-in types are included but developers may use any string, with a max length of 256 bytes.
|
41
|
+
*/
|
42
|
+
export declare class RpcError extends Error {
|
43
|
+
static MAX_MESSAGE_BYTES: number;
|
44
|
+
static MAX_DATA_BYTES: number;
|
45
|
+
code: number;
|
46
|
+
data?: string;
|
47
|
+
/**
|
48
|
+
* Creates an error object with the given code and message, plus an optional data payload.
|
49
|
+
*
|
50
|
+
* If thrown in an RPC method handler, the error will be sent back to the caller.
|
51
|
+
*
|
52
|
+
* Error codes 1001-1999 are reserved for built-in errors (see RpcError.ErrorCode for their meanings).
|
53
|
+
*/
|
54
|
+
constructor(code: number, message: string, data?: string);
|
55
|
+
/**
|
56
|
+
* @internal
|
57
|
+
*/
|
58
|
+
static fromProto(proto: RpcError_Proto): RpcError;
|
59
|
+
/**
|
60
|
+
* @internal
|
61
|
+
*/
|
62
|
+
toProto(): RpcError_Proto;
|
63
|
+
static ErrorCode: {
|
64
|
+
readonly APPLICATION_ERROR: 1500;
|
65
|
+
readonly CONNECTION_TIMEOUT: 1501;
|
66
|
+
readonly RESPONSE_TIMEOUT: 1502;
|
67
|
+
readonly RECIPIENT_DISCONNECTED: 1503;
|
68
|
+
readonly RESPONSE_PAYLOAD_TOO_LARGE: 1504;
|
69
|
+
readonly SEND_FAILED: 1505;
|
70
|
+
readonly UNSUPPORTED_METHOD: 1400;
|
71
|
+
readonly RECIPIENT_NOT_FOUND: 1401;
|
72
|
+
readonly REQUEST_PAYLOAD_TOO_LARGE: 1402;
|
73
|
+
readonly UNSUPPORTED_SERVER: 1403;
|
74
|
+
readonly UNSUPPORTED_VERSION: 1404;
|
75
|
+
};
|
76
|
+
/**
|
77
|
+
* @internal
|
78
|
+
*/
|
79
|
+
static ErrorMessage: Record<keyof typeof RpcError.ErrorCode, string>;
|
80
|
+
/**
|
81
|
+
* Creates an error object from the code, with an auto-populated message.
|
82
|
+
*
|
83
|
+
* @internal
|
84
|
+
*/
|
85
|
+
static builtIn(key: keyof typeof RpcError.ErrorCode, data?: string): RpcError;
|
86
|
+
}
|
87
|
+
export declare const MAX_PAYLOAD_BYTES = 15360;
|
88
|
+
/**
|
89
|
+
* @internal
|
90
|
+
*/
|
91
|
+
export declare function byteLength(str: string): number;
|
92
|
+
/**
|
93
|
+
* @internal
|
94
|
+
*/
|
95
|
+
export declare function truncateBytes(str: string, maxBytes: number): string;
|
96
|
+
//# sourceMappingURL=rpc.d.ts.map
|
@@ -50,6 +50,6 @@ export default class RemoteAudioTrack extends RemoteTrack<Track.Kind.Audio> {
|
|
50
50
|
private connectWebAudio;
|
51
51
|
private disconnectWebAudio;
|
52
52
|
protected monitorReceiver: () => Promise<void>;
|
53
|
-
|
53
|
+
getReceiverStats(): Promise<AudioReceiverStats | undefined>;
|
54
54
|
}
|
55
55
|
//# sourceMappingURL=RemoteAudioTrack.d.ts.map
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import type { VideoReceiverStats } from '../stats';
|
1
2
|
import type { LoggerOptions } from '../types';
|
2
3
|
import RemoteTrack from './RemoteTrack';
|
3
4
|
import { Track } from './Track';
|
@@ -35,7 +36,7 @@ export default class RemoteVideoTrack extends RemoteTrack<Track.Kind.Video> {
|
|
35
36
|
/** @internal */
|
36
37
|
getDecoderImplementation(): string | undefined;
|
37
38
|
protected monitorReceiver: () => Promise<void>;
|
38
|
-
|
39
|
+
getReceiverStats(): Promise<VideoReceiverStats | undefined>;
|
39
40
|
private stopObservingElement;
|
40
41
|
protected handleAppVisibilityChanged(): Promise<void>;
|
41
42
|
private readonly debouncedHandleResize;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { TrackPublishedResponse } from '@livekit/protocol';
|
2
2
|
import { Track } from './Track';
|
3
3
|
import type { TrackPublication } from './TrackPublication';
|
4
|
-
import type { AudioCaptureOptions, CreateLocalTracksOptions, ScreenShareCaptureOptions, VideoCaptureOptions } from './options';
|
4
|
+
import type { AudioCaptureOptions, CreateLocalTracksOptions, ScreenShareCaptureOptions, VideoCaptureOptions, VideoCodec } from './options';
|
5
5
|
import type { AudioTrack } from './types';
|
6
6
|
export declare function mergeDefaultOptions(options?: CreateLocalTracksOptions, audioDefaults?: AudioCaptureOptions, videoDefaults?: VideoCaptureOptions): CreateLocalTracksOptions;
|
7
7
|
export declare function constraintsForOptions(options: CreateLocalTracksOptions): MediaStreamConstraints;
|
@@ -26,7 +26,7 @@ export declare function sourceToKind(source: Track.Source): MediaDeviceKind | un
|
|
26
26
|
* @internal
|
27
27
|
*/
|
28
28
|
export declare function screenCaptureToDisplayMediaStreamOptions(options: ScreenShareCaptureOptions): DisplayMediaStreamOptions;
|
29
|
-
export declare function mimeTypeToVideoCodecString(mimeType: string):
|
29
|
+
export declare function mimeTypeToVideoCodecString(mimeType: string): VideoCodec;
|
30
30
|
export declare function getTrackPublicationInfo<T extends TrackPublication>(tracks: T[]): TrackPublishedResponse[];
|
31
31
|
export declare function getLogContextFromTrack(track: Track | TrackPublication): Record<string, unknown>;
|
32
32
|
export declare function supportsSynchronizationSources(): boolean;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "livekit-client",
|
3
|
-
"version": "2.
|
3
|
+
"version": "2.6.1",
|
4
4
|
"description": "JavaScript/TypeScript client SDK for LiveKit",
|
5
5
|
"main": "./dist/livekit-client.umd.js",
|
6
6
|
"unpkg": "./dist/livekit-client.umd.js",
|
@@ -88,7 +88,7 @@
|
|
88
88
|
"build": "rollup --config --bundleConfigAsCjs && rollup --config rollup.config.worker.js --bundleConfigAsCjs && pnpm downlevel-dts",
|
89
89
|
"build:watch": "rollup --watch --config --bundleConfigAsCjs",
|
90
90
|
"build:worker:watch": "rollup --watch --config rollup.config.worker.js --bundleConfigAsCjs",
|
91
|
-
"build-docs": "typedoc",
|
91
|
+
"build-docs": "typedoc && mkdir -p docs/assets/github && cp .github/*.png docs/assets/github/ && find docs -name '*.html' -type f -exec sed -i.bak 's|=\"/.github/|=\"assets/github/|g' {} + && find docs -name '*.bak' -delete",
|
92
92
|
"proto": "protoc --es_out src/proto --es_opt target=ts -I./protocol ./protocol/livekit_rtc.proto ./protocol/livekit_models.proto",
|
93
93
|
"examples:demo": "vite examples/demo -c vite.config.mjs",
|
94
94
|
"lint": "eslint src",
|
package/src/api/SignalClient.ts
CHANGED
@@ -272,12 +272,22 @@ export class SignalClient {
|
|
272
272
|
const abortHandler = async () => {
|
273
273
|
this.close();
|
274
274
|
clearTimeout(wsTimeout);
|
275
|
-
reject(
|
275
|
+
reject(
|
276
|
+
new ConnectionError(
|
277
|
+
'room connection has been cancelled (signal)',
|
278
|
+
ConnectionErrorReason.Cancelled,
|
279
|
+
),
|
280
|
+
);
|
276
281
|
};
|
277
282
|
|
278
283
|
const wsTimeout = setTimeout(() => {
|
279
284
|
this.close();
|
280
|
-
reject(
|
285
|
+
reject(
|
286
|
+
new ConnectionError(
|
287
|
+
'room connection has timed out (signal)',
|
288
|
+
ConnectionErrorReason.ServerUnreachable,
|
289
|
+
),
|
290
|
+
);
|
281
291
|
}, opts.websocketTimeout);
|
282
292
|
|
283
293
|
if (abortSignal?.aborted) {
|
@@ -391,6 +401,7 @@ export class SignalClient {
|
|
391
401
|
reject(
|
392
402
|
new ConnectionError(
|
393
403
|
`did not receive join response, got ${resp.message?.case} instead`,
|
404
|
+
ConnectionErrorReason.InternalError,
|
394
405
|
),
|
395
406
|
);
|
396
407
|
}
|
@@ -407,7 +418,12 @@ export class SignalClient {
|
|
407
418
|
|
408
419
|
this.ws.onclose = (ev: CloseEvent) => {
|
409
420
|
if (this.isEstablishingConnection) {
|
410
|
-
reject(
|
421
|
+
reject(
|
422
|
+
new ConnectionError(
|
423
|
+
'Websocket got closed during a (re)connection attempt',
|
424
|
+
ConnectionErrorReason.InternalError,
|
425
|
+
),
|
426
|
+
);
|
411
427
|
}
|
412
428
|
|
413
429
|
this.log.warn(`websocket closed`, {
|
package/src/index.ts
CHANGED
@@ -39,6 +39,8 @@ import {
|
|
39
39
|
} from './room/utils';
|
40
40
|
import { getBrowser } from './utils/browserParser';
|
41
41
|
|
42
|
+
export { RpcError, type RpcInvocationData, type PerformRpcParams } from './room/rpc';
|
43
|
+
|
42
44
|
export * from './connectionHelper/ConnectionCheck';
|
43
45
|
export * from './connectionHelper/checks/Checker';
|
44
46
|
export * from './e2ee';
|
package/src/room/PCTransport.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { EventEmitter } from 'events';
|
2
|
-
import type { MediaDescription } from 'sdp-transform';
|
2
|
+
import type { MediaDescription, SessionDescription } from 'sdp-transform';
|
3
3
|
import { parse, write } from 'sdp-transform';
|
4
4
|
import { debounce } from 'ts-debounce';
|
5
5
|
import log, { LoggerNames, getLogger } from '../logger';
|
@@ -48,6 +48,8 @@ export default class PCTransport extends EventEmitter {
|
|
48
48
|
|
49
49
|
private loggerOptions: LoggerOptions;
|
50
50
|
|
51
|
+
private ddExtID = 0;
|
52
|
+
|
51
53
|
pendingCandidates: RTCIceCandidateInit[] = [];
|
52
54
|
|
53
55
|
restartingIce: boolean = false;
|
@@ -288,7 +290,7 @@ export default class PCTransport extends EventEmitter {
|
|
288
290
|
}
|
289
291
|
|
290
292
|
if (isSVCCodec(trackbr.codec)) {
|
291
|
-
ensureVideoDDExtensionForSVC(media);
|
293
|
+
this.ensureVideoDDExtensionForSVC(media, sdpParsed);
|
292
294
|
}
|
293
295
|
|
294
296
|
// TODO: av1 slow starting issue already fixed in chrome 124, clean this after some versions
|
@@ -503,6 +505,44 @@ export default class PCTransport extends EventEmitter {
|
|
503
505
|
throw new NegotiationError(msg);
|
504
506
|
}
|
505
507
|
}
|
508
|
+
|
509
|
+
private ensureVideoDDExtensionForSVC(
|
510
|
+
media: {
|
511
|
+
type: string;
|
512
|
+
port: number;
|
513
|
+
protocol: string;
|
514
|
+
payloads?: string | undefined;
|
515
|
+
} & MediaDescription,
|
516
|
+
sdp: SessionDescription,
|
517
|
+
) {
|
518
|
+
const ddFound = media.ext?.some((ext): boolean => {
|
519
|
+
if (ext.uri === ddExtensionURI) {
|
520
|
+
return true;
|
521
|
+
}
|
522
|
+
return false;
|
523
|
+
});
|
524
|
+
|
525
|
+
if (!ddFound) {
|
526
|
+
if (this.ddExtID === 0) {
|
527
|
+
let maxID = 0;
|
528
|
+
sdp.media.forEach((m) => {
|
529
|
+
if (m.type !== 'video') {
|
530
|
+
return;
|
531
|
+
}
|
532
|
+
m.ext?.forEach((ext) => {
|
533
|
+
if (ext.value > maxID) {
|
534
|
+
maxID = ext.value;
|
535
|
+
}
|
536
|
+
});
|
537
|
+
});
|
538
|
+
this.ddExtID = maxID + 1;
|
539
|
+
}
|
540
|
+
media.ext?.push({
|
541
|
+
value: this.ddExtID,
|
542
|
+
uri: ddExtensionURI,
|
543
|
+
});
|
544
|
+
}
|
545
|
+
}
|
506
546
|
}
|
507
547
|
|
508
548
|
function ensureAudioNackAndStereo(
|
@@ -555,33 +595,6 @@ function ensureAudioNackAndStereo(
|
|
555
595
|
}
|
556
596
|
}
|
557
597
|
|
558
|
-
function ensureVideoDDExtensionForSVC(
|
559
|
-
media: {
|
560
|
-
type: string;
|
561
|
-
port: number;
|
562
|
-
protocol: string;
|
563
|
-
payloads?: string | undefined;
|
564
|
-
} & MediaDescription,
|
565
|
-
) {
|
566
|
-
let maxID = 0;
|
567
|
-
const ddFound = media.ext?.some((ext): boolean => {
|
568
|
-
if (ext.uri === ddExtensionURI) {
|
569
|
-
return true;
|
570
|
-
}
|
571
|
-
if (ext.value > maxID) {
|
572
|
-
maxID = ext.value;
|
573
|
-
}
|
574
|
-
return false;
|
575
|
-
});
|
576
|
-
|
577
|
-
if (!ddFound) {
|
578
|
-
media.ext?.push({
|
579
|
-
value: maxID + 1,
|
580
|
-
uri: ddExtensionURI,
|
581
|
-
});
|
582
|
-
}
|
583
|
-
}
|
584
|
-
|
585
598
|
function extractStereoAndNackAudioFromOffer(offer: RTCSessionDescriptionInit): {
|
586
599
|
stereoMids: string[];
|
587
600
|
nackMids: string[];
|
@@ -342,7 +342,12 @@ export class PCTransportManager {
|
|
342
342
|
|
343
343
|
const connectTimeout = CriticalTimers.setTimeout(() => {
|
344
344
|
abortController?.signal.removeEventListener('abort', abortHandler);
|
345
|
-
reject(
|
345
|
+
reject(
|
346
|
+
new ConnectionError(
|
347
|
+
'could not establish pc connection',
|
348
|
+
ConnectionErrorReason.InternalError,
|
349
|
+
),
|
350
|
+
);
|
346
351
|
}, timeout);
|
347
352
|
|
348
353
|
while (this.state !== PCTransportState.CONNECTED) {
|
package/src/room/RTCEngine.ts
CHANGED
@@ -313,7 +313,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
313
313
|
const publicationTimeout = setTimeout(() => {
|
314
314
|
delete this.pendingTrackResolvers[req.cid];
|
315
315
|
reject(
|
316
|
-
new ConnectionError(
|
316
|
+
new ConnectionError(
|
317
|
+
'publication of local track timed out, no response from server',
|
318
|
+
ConnectionErrorReason.InternalError,
|
319
|
+
),
|
317
320
|
);
|
318
321
|
}, 10_000);
|
319
322
|
this.pendingTrackResolvers[req.cid] = {
|
@@ -1061,7 +1064,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1061
1064
|
} catch (e: any) {
|
1062
1065
|
// TODO do we need a `failed` state here for the PC?
|
1063
1066
|
this.pcState = PCState.Disconnected;
|
1064
|
-
throw new ConnectionError(
|
1067
|
+
throw new ConnectionError(
|
1068
|
+
`could not establish PC connection, ${e.message}`,
|
1069
|
+
ConnectionErrorReason.InternalError,
|
1070
|
+
);
|
1065
1071
|
}
|
1066
1072
|
}
|
1067
1073
|
|
@@ -1126,7 +1132,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1126
1132
|
const transport = subscriber ? this.pcManager.subscriber : this.pcManager.publisher;
|
1127
1133
|
const transportName = subscriber ? 'Subscriber' : 'Publisher';
|
1128
1134
|
if (!transport) {
|
1129
|
-
throw new ConnectionError(
|
1135
|
+
throw new ConnectionError(
|
1136
|
+
`${transportName} connection not set`,
|
1137
|
+
ConnectionErrorReason.InternalError,
|
1138
|
+
);
|
1130
1139
|
}
|
1131
1140
|
|
1132
1141
|
let needNegotiation = false;
|
@@ -1167,6 +1176,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1167
1176
|
|
1168
1177
|
throw new ConnectionError(
|
1169
1178
|
`could not establish ${transportName} connection, state: ${transport.getICEConnectionState()}`,
|
1179
|
+
ConnectionErrorReason.InternalError,
|
1170
1180
|
);
|
1171
1181
|
}
|
1172
1182
|
|
@@ -70,7 +70,9 @@ export class RegionUrlProvider {
|
|
70
70
|
} else {
|
71
71
|
throw new ConnectionError(
|
72
72
|
`Could not fetch region settings: ${regionSettingsResponse.statusText}`,
|
73
|
-
regionSettingsResponse.status === 401
|
73
|
+
regionSettingsResponse.status === 401
|
74
|
+
? ConnectionErrorReason.NotAllowed
|
75
|
+
: ConnectionErrorReason.InternalError,
|
74
76
|
regionSettingsResponse.status,
|
75
77
|
);
|
76
78
|
}
|
package/src/room/Room.ts
CHANGED
@@ -714,7 +714,10 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
714
714
|
} catch (err) {
|
715
715
|
await this.engine.close();
|
716
716
|
this.recreateEngine();
|
717
|
-
const resultingError = new ConnectionError(
|
717
|
+
const resultingError = new ConnectionError(
|
718
|
+
`could not establish signal connection`,
|
719
|
+
ConnectionErrorReason.ServerUnreachable,
|
720
|
+
);
|
718
721
|
if (err instanceof Error) {
|
719
722
|
resultingError.message = `${resultingError.message}: ${err.message}`;
|
720
723
|
}
|
@@ -732,7 +735,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
732
735
|
if (abortController.signal.aborted) {
|
733
736
|
await this.engine.close();
|
734
737
|
this.recreateEngine();
|
735
|
-
throw new ConnectionError(`Connection attempt aborted
|
738
|
+
throw new ConnectionError(`Connection attempt aborted`, ConnectionErrorReason.Cancelled);
|
736
739
|
}
|
737
740
|
|
738
741
|
try {
|
@@ -783,7 +786,9 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
783
786
|
this.log.warn('abort connection attempt', this.logContext);
|
784
787
|
this.abortController?.abort();
|
785
788
|
// in case the abort controller didn't manage to cancel the connection attempt, reject the connect promise explicitly
|
786
|
-
this.connectFuture?.reject?.(
|
789
|
+
this.connectFuture?.reject?.(
|
790
|
+
new ConnectionError('Client initiated disconnect', ConnectionErrorReason.Cancelled),
|
791
|
+
);
|
787
792
|
this.connectFuture = undefined;
|
788
793
|
}
|
789
794
|
// send leave
|
@@ -1414,6 +1419,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
1414
1419
|
participant.unpublishTrack(publication.trackSid, true);
|
1415
1420
|
});
|
1416
1421
|
this.emit(RoomEvent.ParticipantDisconnected, participant);
|
1422
|
+
this.localParticipant?.handleParticipantDisconnected(participant.identity);
|
1417
1423
|
}
|
1418
1424
|
|
1419
1425
|
// updates are sent only when there's a change to speaker ordering
|
package/src/room/errors.ts
CHANGED
@@ -20,9 +20,9 @@ export const enum ConnectionErrorReason {
|
|
20
20
|
export class ConnectionError extends LivekitError {
|
21
21
|
status?: number;
|
22
22
|
|
23
|
-
reason
|
23
|
+
reason: ConnectionErrorReason;
|
24
24
|
|
25
|
-
constructor(message
|
25
|
+
constructor(message: string, reason: ConnectionErrorReason, status?: number) {
|
26
26
|
super(1, message);
|
27
27
|
this.status = status;
|
28
28
|
this.reason = reason;
|