livekit-client 2.15.4 → 2.15.6
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.
- package/dist/livekit-client.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +373 -164
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +982 -643
- 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/e2ee/E2eeManager.d.ts.map +1 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts +0 -47
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/e2ee/worker/naluUtils.d.ts +27 -0
- package/dist/src/e2ee/worker/naluUtils.d.ts.map +1 -0
- package/dist/src/e2ee/worker/sifPayload.d.ts +22 -0
- package/dist/src/e2ee/worker/sifPayload.d.ts.map +1 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +6 -10
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/data-stream/incoming/IncomingDataStreamManager.d.ts +20 -0
- package/dist/src/room/data-stream/incoming/IncomingDataStreamManager.d.ts.map +1 -0
- package/dist/{ts4.2/src/room → src/room/data-stream/incoming}/StreamReader.d.ts +82 -56
- package/dist/src/room/data-stream/incoming/StreamReader.d.ts.map +1 -0
- package/dist/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts +27 -0
- package/dist/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts.map +1 -0
- package/dist/src/room/{StreamWriter.d.ts → data-stream/outgoing/StreamWriter.d.ts} +1 -1
- package/dist/src/room/data-stream/outgoing/StreamWriter.d.ts.map +1 -0
- package/dist/src/room/errors.d.ts +13 -0
- package/dist/src/room/errors.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +32 -19
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +7 -2
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts +1 -0
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +4 -1
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/types.d.ts +17 -1
- package/dist/src/room/types.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +8 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/ts4.2/src/e2ee/worker/FrameCryptor.d.ts +0 -47
- package/dist/ts4.2/src/e2ee/worker/naluUtils.d.ts +27 -0
- package/dist/ts4.2/src/e2ee/worker/sifPayload.d.ts +22 -0
- package/dist/ts4.2/src/index.d.ts +2 -2
- package/dist/ts4.2/src/room/Room.d.ts +6 -10
- package/dist/ts4.2/src/room/data-stream/incoming/IncomingDataStreamManager.d.ts +20 -0
- package/dist/{src/room → ts4.2/src/room/data-stream/incoming}/StreamReader.d.ts +82 -56
- package/dist/ts4.2/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts +27 -0
- package/dist/ts4.2/src/room/{StreamWriter.d.ts → data-stream/outgoing/StreamWriter.d.ts} +1 -1
- package/dist/ts4.2/src/room/errors.d.ts +13 -0
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +32 -19
- package/dist/ts4.2/src/room/track/LocalTrack.d.ts +7 -2
- package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +1 -0
- package/dist/ts4.2/src/room/track/Track.d.ts +4 -1
- package/dist/ts4.2/src/room/types.d.ts +17 -1
- package/dist/ts4.2/src/room/utils.d.ts +8 -0
- package/package.json +7 -7
- package/src/e2ee/E2eeManager.ts +18 -1
- package/src/e2ee/worker/FrameCryptor.ts +56 -157
- package/src/e2ee/worker/e2ee.worker.ts +6 -1
- package/src/e2ee/worker/naluUtils.ts +328 -0
- package/src/e2ee/worker/sifPayload.ts +75 -0
- package/src/index.ts +2 -2
- package/src/room/Room.ts +104 -208
- package/src/room/data-stream/incoming/IncomingDataStreamManager.ts +247 -0
- package/src/room/data-stream/incoming/StreamReader.ts +317 -0
- package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +316 -0
- package/src/room/{StreamWriter.ts → data-stream/outgoing/StreamWriter.ts} +1 -1
- package/src/room/errors.ts +34 -0
- package/src/room/participant/LocalParticipant.ts +39 -295
- package/src/room/track/LocalAudioTrack.ts +2 -2
- package/src/room/track/LocalTrack.ts +70 -50
- package/src/room/track/RemoteVideoTrack.ts +12 -2
- package/src/room/track/Track.ts +10 -1
- package/src/room/types.ts +22 -1
- package/src/room/utils.ts +14 -5
- package/dist/src/e2ee/worker/SifGuard.d.ts +0 -11
- package/dist/src/e2ee/worker/SifGuard.d.ts.map +0 -1
- package/dist/src/room/StreamReader.d.ts.map +0 -1
- package/dist/src/room/StreamWriter.d.ts.map +0 -1
- package/dist/ts4.2/src/e2ee/worker/SifGuard.d.ts +0 -11
- package/src/e2ee/worker/SifGuard.ts +0 -47
- package/src/room/StreamReader.ts +0 -170
package/src/room/track/Track.ts
CHANGED
@@ -37,6 +37,8 @@ export abstract class Track<
|
|
37
37
|
|
38
38
|
source: Track.Source;
|
39
39
|
|
40
|
+
private _streamState: Track.StreamState = Track.StreamState.Active;
|
41
|
+
|
40
42
|
/**
|
41
43
|
* sid is set after track is published to server, or if it's a remote track
|
42
44
|
*/
|
@@ -51,7 +53,14 @@ export abstract class Track<
|
|
51
53
|
* indicates current state of stream, it'll indicate `paused` if the track
|
52
54
|
* has been paused by congestion controller
|
53
55
|
*/
|
54
|
-
streamState: Track.StreamState
|
56
|
+
get streamState(): Track.StreamState {
|
57
|
+
return this._streamState;
|
58
|
+
}
|
59
|
+
|
60
|
+
/** @internal */
|
61
|
+
setStreamState(value: Track.StreamState) {
|
62
|
+
this._streamState = value;
|
63
|
+
}
|
55
64
|
|
56
65
|
/** @internal */
|
57
66
|
rtpTimestamp: number | undefined;
|
package/src/room/types.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
import type { DataStream_Chunk } from '@livekit/protocol';
|
1
|
+
import type { DataStream_Chunk, Encryption_Type } from '@livekit/protocol';
|
2
|
+
import type { Future } from './utils';
|
2
3
|
|
3
4
|
export type SimulationOptions = {
|
4
5
|
publish?: {
|
@@ -35,6 +36,24 @@ export interface StreamTextOptions {
|
|
35
36
|
attributes?: Record<string, string>;
|
36
37
|
}
|
37
38
|
|
39
|
+
export type StreamBytesOptions = {
|
40
|
+
name?: string;
|
41
|
+
topic?: string;
|
42
|
+
attributes?: Record<string, string>;
|
43
|
+
destinationIdentities?: Array<string>;
|
44
|
+
streamId?: string;
|
45
|
+
mimeType?: string;
|
46
|
+
totalSize?: number;
|
47
|
+
};
|
48
|
+
|
49
|
+
export type SendFileOptions = Pick<
|
50
|
+
StreamBytesOptions,
|
51
|
+
'topic' | 'mimeType' | 'destinationIdentities'
|
52
|
+
> & {
|
53
|
+
onProgress?: (progress: number) => void;
|
54
|
+
encryptionType?: Encryption_Type.NONE;
|
55
|
+
};
|
56
|
+
|
38
57
|
export type DataPublishOptions = {
|
39
58
|
/**
|
40
59
|
* whether to send this as reliable or lossy.
|
@@ -105,6 +124,8 @@ export interface StreamController<T extends DataStream_Chunk> {
|
|
105
124
|
controller: ReadableStreamDefaultController<T>;
|
106
125
|
startTime: number;
|
107
126
|
endTime?: number;
|
127
|
+
sendingParticipantIdentity: string;
|
128
|
+
outOfBandFailureRejectingFuture: Future<never>;
|
108
129
|
}
|
109
130
|
|
110
131
|
export interface BaseStreamInfo {
|
package/src/room/utils.ts
CHANGED
@@ -64,8 +64,9 @@ export function supportsAV1(): boolean {
|
|
64
64
|
if (!('getCapabilities' in RTCRtpSender)) {
|
65
65
|
return false;
|
66
66
|
}
|
67
|
-
if (isSafari()) {
|
67
|
+
if (isSafari() || isFireFox()) {
|
68
68
|
// Safari 17 on iPhone14 reports AV1 capability, but does not actually support it
|
69
|
+
// Firefox does support AV1, but SVC publishing is not supported
|
69
70
|
return false;
|
70
71
|
}
|
71
72
|
const capabilities = RTCRtpSender.getCapabilities('video');
|
@@ -214,12 +215,12 @@ export function isE2EESimulcastSupported() {
|
|
214
215
|
} else if (
|
215
216
|
browser.os === 'iOS' &&
|
216
217
|
browser.osVersion &&
|
217
|
-
compareVersions(
|
218
|
+
compareVersions(browser.osVersion, supportedSafariVersion) >= 0
|
218
219
|
) {
|
219
220
|
return true;
|
220
221
|
} else if (
|
221
222
|
browser.name === 'Safari' &&
|
222
|
-
compareVersions(
|
223
|
+
compareVersions(browser.version, supportedSafariVersion) >= 0
|
223
224
|
) {
|
224
225
|
return true;
|
225
226
|
} else {
|
@@ -282,6 +283,14 @@ export function getDevicePixelRatio(): number {
|
|
282
283
|
return 1;
|
283
284
|
}
|
284
285
|
|
286
|
+
/**
|
287
|
+
* @param v1 - The first version string to compare.
|
288
|
+
* @param v2 - The second version string to compare.
|
289
|
+
* @returns A number indicating the order of the versions:
|
290
|
+
* - 1 if v1 is greater than v2
|
291
|
+
* - -1 if v1 is less than v2
|
292
|
+
* - 0 if v1 and v2 are equal
|
293
|
+
*/
|
285
294
|
export function compareVersions(v1: string, v2: string): number {
|
286
295
|
const parts1 = v1.split('.');
|
287
296
|
const parts2 = v2.split('.');
|
@@ -538,13 +547,13 @@ export function unwrapConstraint(constraint: ConstrainDOMString | ConstrainULong
|
|
538
547
|
if (Array.isArray(constraint)) {
|
539
548
|
return constraint[0];
|
540
549
|
}
|
541
|
-
if (constraint.exact) {
|
550
|
+
if (constraint.exact !== undefined) {
|
542
551
|
if (Array.isArray(constraint.exact)) {
|
543
552
|
return constraint.exact[0];
|
544
553
|
}
|
545
554
|
return constraint.exact;
|
546
555
|
}
|
547
|
-
if (constraint.ideal) {
|
556
|
+
if (constraint.ideal !== undefined) {
|
548
557
|
if (Array.isArray(constraint.ideal)) {
|
549
558
|
return constraint.ideal[0];
|
550
559
|
}
|
@@ -1,11 +0,0 @@
|
|
1
|
-
export declare class SifGuard {
|
2
|
-
private consecutiveSifCount;
|
3
|
-
private sifSequenceStartedAt;
|
4
|
-
private lastSifReceivedAt;
|
5
|
-
private userFramesSinceSif;
|
6
|
-
recordSif(): void;
|
7
|
-
recordUserFrame(): void;
|
8
|
-
isSifAllowed(): boolean;
|
9
|
-
reset(): void;
|
10
|
-
}
|
11
|
-
//# sourceMappingURL=SifGuard.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"SifGuard.d.ts","sourceRoot":"","sources":["../../../../src/e2ee/worker/SifGuard.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAQ;IACnB,OAAO,CAAC,mBAAmB,CAAK;IAEhC,OAAO,CAAC,oBAAoB,CAAqB;IAEjD,OAAO,CAAC,iBAAiB,CAAa;IAEtC,OAAO,CAAC,kBAAkB,CAAa;IAEvC,SAAS;IAMT,eAAe;IAgBf,YAAY;IAQZ,KAAK;CAKN"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"StreamReader.d.ts","sourceRoot":"","sources":["../../../src/room/StreamReader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9E,uBAAe,gBAAgB,CAAC,CAAC,SAAS,cAAc;IACtD,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAEnD,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEjC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;IAEnB,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC;IAEhC,IAAI,IAAI,MAEP;gBAEW,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,gBAAgB,CAAC,EAAE,aAAa,CAAC,EAAE,MAAM;IAOrF,SAAS,CAAC,QAAQ,CAAC,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAErE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAEpD,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;CACxD;AAED,qBAAa,gBAAiB,SAAQ,gBAAgB,CAAC,cAAc,CAAC;IACpE,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,gBAAgB;IAQrD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAEpD,CAAC,MAAM,CAAC,aAAa,CAAC;oBAIF,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;kBAenC,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;;IAOjD,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;CAO5C;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,gBAAgB,CAAC,cAAc,CAAC;IACpE,OAAO,CAAC,cAAc,CAAgC;IAEtD;;;OAGG;gBAED,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,cAAc,CAAC,gBAAgB,CAAC,EACxC,eAAe,CAAC,EAAE,MAAM;IAM1B,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,gBAAgB;IAerD;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAEpD;;;;OAIG;IACH,CAAC,MAAM,CAAC,aAAa,CAAC;oBAKF,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;kBAmB/B,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;;IAO7C,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CAOjC;AAED,MAAM,MAAM,iBAAiB,GAAG,CAC9B,MAAM,EAAE,gBAAgB,EACxB,eAAe,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,KAClC,IAAI,CAAC;AAEV,MAAM,MAAM,iBAAiB,GAAG,CAC9B,MAAM,EAAE,gBAAgB,EACxB,eAAe,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,KAClC,IAAI,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"StreamWriter.d.ts","sourceRoot":"","sources":["../../../src/room/StreamWriter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9E,cAAM,gBAAgB,CAAC,CAAC,EAAE,QAAQ,SAAS,cAAc;IACvD,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAE5C,SAAS,CAAC,aAAa,EAAE,2BAA2B,CAAC,CAAC,CAAC,CAAC;IAExD,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAE/B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;gBAEZ,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI;IAOnF,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxB,KAAK;CAKZ;AAED,qBAAa,gBAAiB,SAAQ,gBAAgB,CAAC,MAAM,EAAE,cAAc,CAAC;CAAG;AAEjF,qBAAa,gBAAiB,SAAQ,gBAAgB,CAAC,UAAU,EAAE,cAAc,CAAC;CAAG"}
|
@@ -1,11 +0,0 @@
|
|
1
|
-
export declare class SifGuard {
|
2
|
-
private consecutiveSifCount;
|
3
|
-
private sifSequenceStartedAt;
|
4
|
-
private lastSifReceivedAt;
|
5
|
-
private userFramesSinceSif;
|
6
|
-
recordSif(): void;
|
7
|
-
recordUserFrame(): void;
|
8
|
-
isSifAllowed(): boolean;
|
9
|
-
reset(): void;
|
10
|
-
}
|
11
|
-
//# sourceMappingURL=SifGuard.d.ts.map
|
@@ -1,47 +0,0 @@
|
|
1
|
-
import { MAX_SIF_COUNT, MAX_SIF_DURATION } from '../constants';
|
2
|
-
|
3
|
-
export class SifGuard {
|
4
|
-
private consecutiveSifCount = 0;
|
5
|
-
|
6
|
-
private sifSequenceStartedAt: number | undefined;
|
7
|
-
|
8
|
-
private lastSifReceivedAt: number = 0;
|
9
|
-
|
10
|
-
private userFramesSinceSif: number = 0;
|
11
|
-
|
12
|
-
recordSif() {
|
13
|
-
this.consecutiveSifCount += 1;
|
14
|
-
this.sifSequenceStartedAt ??= Date.now();
|
15
|
-
this.lastSifReceivedAt = Date.now();
|
16
|
-
}
|
17
|
-
|
18
|
-
recordUserFrame() {
|
19
|
-
if (this.sifSequenceStartedAt === undefined) {
|
20
|
-
return;
|
21
|
-
} else {
|
22
|
-
this.userFramesSinceSif += 1;
|
23
|
-
}
|
24
|
-
if (
|
25
|
-
// reset if we received more user frames than SIFs
|
26
|
-
this.userFramesSinceSif > this.consecutiveSifCount ||
|
27
|
-
// also reset if we got a new user frame and the latest SIF frame hasn't been updated in a while
|
28
|
-
Date.now() - this.lastSifReceivedAt > MAX_SIF_DURATION
|
29
|
-
) {
|
30
|
-
this.reset();
|
31
|
-
}
|
32
|
-
}
|
33
|
-
|
34
|
-
isSifAllowed() {
|
35
|
-
return (
|
36
|
-
this.consecutiveSifCount < MAX_SIF_COUNT &&
|
37
|
-
(this.sifSequenceStartedAt === undefined ||
|
38
|
-
Date.now() - this.sifSequenceStartedAt < MAX_SIF_DURATION)
|
39
|
-
);
|
40
|
-
}
|
41
|
-
|
42
|
-
reset() {
|
43
|
-
this.userFramesSinceSif = 0;
|
44
|
-
this.consecutiveSifCount = 0;
|
45
|
-
this.sifSequenceStartedAt = undefined;
|
46
|
-
}
|
47
|
-
}
|
package/src/room/StreamReader.ts
DELETED
@@ -1,170 +0,0 @@
|
|
1
|
-
import type { DataStream_Chunk } from '@livekit/protocol';
|
2
|
-
import type { BaseStreamInfo, ByteStreamInfo, TextStreamInfo } from './types';
|
3
|
-
import { bigIntToNumber } from './utils';
|
4
|
-
|
5
|
-
abstract class BaseStreamReader<T extends BaseStreamInfo> {
|
6
|
-
protected reader: ReadableStream<DataStream_Chunk>;
|
7
|
-
|
8
|
-
protected totalByteSize?: number;
|
9
|
-
|
10
|
-
protected _info: T;
|
11
|
-
|
12
|
-
protected bytesReceived: number;
|
13
|
-
|
14
|
-
get info() {
|
15
|
-
return this._info;
|
16
|
-
}
|
17
|
-
|
18
|
-
constructor(info: T, stream: ReadableStream<DataStream_Chunk>, totalByteSize?: number) {
|
19
|
-
this.reader = stream;
|
20
|
-
this.totalByteSize = totalByteSize;
|
21
|
-
this._info = info;
|
22
|
-
this.bytesReceived = 0;
|
23
|
-
}
|
24
|
-
|
25
|
-
protected abstract handleChunkReceived(chunk: DataStream_Chunk): void;
|
26
|
-
|
27
|
-
onProgress?: (progress: number | undefined) => void;
|
28
|
-
|
29
|
-
abstract readAll(): Promise<string | Array<Uint8Array>>;
|
30
|
-
}
|
31
|
-
|
32
|
-
export class ByteStreamReader extends BaseStreamReader<ByteStreamInfo> {
|
33
|
-
protected handleChunkReceived(chunk: DataStream_Chunk) {
|
34
|
-
this.bytesReceived += chunk.content.byteLength;
|
35
|
-
const currentProgress = this.totalByteSize
|
36
|
-
? this.bytesReceived / this.totalByteSize
|
37
|
-
: undefined;
|
38
|
-
this.onProgress?.(currentProgress);
|
39
|
-
}
|
40
|
-
|
41
|
-
onProgress?: (progress: number | undefined) => void;
|
42
|
-
|
43
|
-
[Symbol.asyncIterator]() {
|
44
|
-
const reader = this.reader.getReader();
|
45
|
-
|
46
|
-
return {
|
47
|
-
next: async (): Promise<IteratorResult<Uint8Array>> => {
|
48
|
-
try {
|
49
|
-
const { done, value } = await reader.read();
|
50
|
-
if (done) {
|
51
|
-
return { done: true, value: undefined as any };
|
52
|
-
} else {
|
53
|
-
this.handleChunkReceived(value);
|
54
|
-
return { done: false, value: value.content };
|
55
|
-
}
|
56
|
-
} catch (error) {
|
57
|
-
// TODO handle errors
|
58
|
-
return { done: true, value: undefined };
|
59
|
-
}
|
60
|
-
},
|
61
|
-
|
62
|
-
async return(): Promise<IteratorResult<Uint8Array>> {
|
63
|
-
reader.releaseLock();
|
64
|
-
return { done: true, value: undefined };
|
65
|
-
},
|
66
|
-
};
|
67
|
-
}
|
68
|
-
|
69
|
-
async readAll(): Promise<Array<Uint8Array>> {
|
70
|
-
let chunks: Set<Uint8Array> = new Set();
|
71
|
-
for await (const chunk of this) {
|
72
|
-
chunks.add(chunk);
|
73
|
-
}
|
74
|
-
return Array.from(chunks);
|
75
|
-
}
|
76
|
-
}
|
77
|
-
|
78
|
-
/**
|
79
|
-
* A class to read chunks from a ReadableStream and provide them in a structured format.
|
80
|
-
*/
|
81
|
-
export class TextStreamReader extends BaseStreamReader<TextStreamInfo> {
|
82
|
-
private receivedChunks: Map<number, DataStream_Chunk>;
|
83
|
-
|
84
|
-
/**
|
85
|
-
* A TextStreamReader instance can be used as an AsyncIterator that returns the entire string
|
86
|
-
* that has been received up to the current point in time.
|
87
|
-
*/
|
88
|
-
constructor(
|
89
|
-
info: TextStreamInfo,
|
90
|
-
stream: ReadableStream<DataStream_Chunk>,
|
91
|
-
totalChunkCount?: number,
|
92
|
-
) {
|
93
|
-
super(info, stream, totalChunkCount);
|
94
|
-
this.receivedChunks = new Map();
|
95
|
-
}
|
96
|
-
|
97
|
-
protected handleChunkReceived(chunk: DataStream_Chunk) {
|
98
|
-
const index = bigIntToNumber(chunk.chunkIndex);
|
99
|
-
const previousChunkAtIndex = this.receivedChunks.get(index);
|
100
|
-
if (previousChunkAtIndex && previousChunkAtIndex.version > chunk.version) {
|
101
|
-
// we have a newer version already, dropping the old one
|
102
|
-
return;
|
103
|
-
}
|
104
|
-
this.receivedChunks.set(index, chunk);
|
105
|
-
this.bytesReceived += chunk.content.byteLength;
|
106
|
-
const currentProgress = this.totalByteSize
|
107
|
-
? this.bytesReceived / this.totalByteSize
|
108
|
-
: undefined;
|
109
|
-
this.onProgress?.(currentProgress);
|
110
|
-
}
|
111
|
-
|
112
|
-
/**
|
113
|
-
* @param progress - progress of the stream between 0 and 1. Undefined for streams of unknown size
|
114
|
-
*/
|
115
|
-
onProgress?: (progress: number | undefined) => void;
|
116
|
-
|
117
|
-
/**
|
118
|
-
* Async iterator implementation to allow usage of `for await...of` syntax.
|
119
|
-
* Yields structured chunks from the stream.
|
120
|
-
*
|
121
|
-
*/
|
122
|
-
[Symbol.asyncIterator]() {
|
123
|
-
const reader = this.reader.getReader();
|
124
|
-
const decoder = new TextDecoder();
|
125
|
-
|
126
|
-
return {
|
127
|
-
next: async (): Promise<IteratorResult<string>> => {
|
128
|
-
try {
|
129
|
-
const { done, value } = await reader.read();
|
130
|
-
if (done) {
|
131
|
-
return { done: true, value: undefined };
|
132
|
-
} else {
|
133
|
-
this.handleChunkReceived(value);
|
134
|
-
|
135
|
-
return {
|
136
|
-
done: false,
|
137
|
-
value: decoder.decode(value.content),
|
138
|
-
};
|
139
|
-
}
|
140
|
-
} catch (error) {
|
141
|
-
// TODO handle errors
|
142
|
-
return { done: true, value: undefined };
|
143
|
-
}
|
144
|
-
},
|
145
|
-
|
146
|
-
async return(): Promise<IteratorResult<string>> {
|
147
|
-
reader.releaseLock();
|
148
|
-
return { done: true, value: undefined };
|
149
|
-
},
|
150
|
-
};
|
151
|
-
}
|
152
|
-
|
153
|
-
async readAll(): Promise<string> {
|
154
|
-
let finalString: string = '';
|
155
|
-
for await (const chunk of this) {
|
156
|
-
finalString += chunk;
|
157
|
-
}
|
158
|
-
return finalString;
|
159
|
-
}
|
160
|
-
}
|
161
|
-
|
162
|
-
export type ByteStreamHandler = (
|
163
|
-
reader: ByteStreamReader,
|
164
|
-
participantInfo: { identity: string },
|
165
|
-
) => void;
|
166
|
-
|
167
|
-
export type TextStreamHandler = (
|
168
|
-
reader: TextStreamReader,
|
169
|
-
participantInfo: { identity: string },
|
170
|
-
) => void;
|