@xloon/xms-client 0.1.0

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/room.d.ts ADDED
@@ -0,0 +1,201 @@
1
+ import type { WebSocketFactory } from './signaling.js';
2
+ import type { ParticipantInfo, ProtocolError, TrackInfo } from './protocol.js';
3
+ export interface JoinOptions {
4
+ /** Signaling WebSocket URL, e.g. wss://media.example.com/ws/signaling */
5
+ url: string;
6
+ roomId: string;
7
+ /** Join token minted by the app backend (POST /api/v1/rooms/{roomId}/tokens). */
8
+ token: string;
9
+ /** Used only when the token carries no name. */
10
+ displayName?: string;
11
+ /** Subscribe to every publisher (all tracks) automatically and keep those subscriptions in step
12
+ * with publisher changes. Default true. Turn off to choose publishers/tracks yourself. */
13
+ autoSubscribe?: boolean;
14
+ /** Returns a fresh join token from your backend. Used only when rejoining after a dropped
15
+ * connection and the server rejects the current token (e.g. it expired); without it, an expired
16
+ * token ends reconnection with `disconnected`. */
17
+ getToken?: () => Promise<string>;
18
+ /** For tests: delay before the first reconnect attempt (default 1000; doubles each attempt). */
19
+ reconnectDelayMs?: number;
20
+ /** For tests. */
21
+ webSocketFactory?: WebSocketFactory;
22
+ /** For tests. */
23
+ createPeerConnection?: (config: RTCConfiguration) => RTCPeerConnection;
24
+ }
25
+ export interface PublishOptions {
26
+ /** Send video as 3 simulcast layers (rids "l", "m", "h", lowest first) so each subscriber can be
27
+ * given the quality it needs. Default true. */
28
+ simulcast?: boolean;
29
+ }
30
+ export interface SubscribeOptions {
31
+ /** Which of the publisher's tracks to receive (TrackInfo.trackId); all when omitted. */
32
+ trackIds?: string[];
33
+ /** trackId -> simulcast rid to start on; the server defaults to the highest layer. */
34
+ layers?: Record<string, string>;
35
+ }
36
+ export interface RemoteParticipant extends ParticipantInfo {
37
+ /** Tracks this participant currently publishes (empty when not publishing). */
38
+ tracks: TrackInfo[];
39
+ }
40
+ export interface RemoteTrack {
41
+ participantId: string;
42
+ trackId: string;
43
+ kind: 'audio' | 'video';
44
+ track: MediaStreamTrack;
45
+ }
46
+ export interface RoomEvents {
47
+ participantJoined: RemoteParticipant;
48
+ participantLeft: {
49
+ participantId: string;
50
+ reason: string;
51
+ };
52
+ publisherAdded: RemoteParticipant;
53
+ publisherUpdated: RemoteParticipant;
54
+ publisherRemoved: {
55
+ participantId: string;
56
+ };
57
+ trackMuted: {
58
+ participantId: string;
59
+ trackId: string;
60
+ muted: boolean;
61
+ };
62
+ /** Media for a subscribed track started arriving. */
63
+ track: RemoteTrack;
64
+ /** A subscribed track stopped (unsubscribed, unpublished, or the participant left). */
65
+ trackEnded: {
66
+ participantId: string;
67
+ trackId: string;
68
+ };
69
+ chat: {
70
+ participantId: string;
71
+ text: string;
72
+ timestampMillis: number;
73
+ };
74
+ /** App data another participant sent with {@link XmsRoom.sendData}. */
75
+ data: {
76
+ participantId: string;
77
+ type: string;
78
+ payload: unknown;
79
+ timestampMillis: number;
80
+ };
81
+ recordingStarted: {
82
+ recordingId: string;
83
+ };
84
+ recordingStopped: {
85
+ recordingId: string;
86
+ };
87
+ error: ProtocolError & {
88
+ transportId?: string | null;
89
+ };
90
+ /** The connection dropped (or a media connection failed) and the room is being rejoined; emitted
91
+ * per attempt. Remote tracks have ended (trackEnded); they come back as new `track` events. */
92
+ reconnecting: {
93
+ attempt: number;
94
+ };
95
+ /** Rejoined under a new localParticipantId: your tracks are published again (mute kept) and
96
+ * subscriptions are being restored. */
97
+ reconnected: {
98
+ participantId: string;
99
+ };
100
+ /** Final: after {@link XmsRoom.leave}, or when rejoining gave up. */
101
+ disconnected: {
102
+ code: number;
103
+ reason: string;
104
+ };
105
+ }
106
+ type Handler<E extends keyof RoomEvents> = (data: RoomEvents[E]) => void;
107
+ export declare class XmsRoom {
108
+ readonly roomId: string;
109
+ private readonly options;
110
+ private signaling;
111
+ private participantId;
112
+ private token;
113
+ private iceServers;
114
+ private readonly autoSubscribe;
115
+ private readonly newPeerConnection;
116
+ private readonly remote;
117
+ private readonly subscriptions;
118
+ /** What each subscription asked for, so it can be restored after a rejoin. */
119
+ private readonly subscribeOptions;
120
+ private readonly published;
121
+ /** Our participantIds from before rejoins: the server may list them until it notices they're gone. */
122
+ private readonly previousIds;
123
+ /** PeerConnections that have connected at least once. */
124
+ private readonly connectedPcs;
125
+ private readonly listeners;
126
+ /** Serializes negotiations per transport: key "pub" or a publisherId. */
127
+ private readonly queues;
128
+ private publisherPc;
129
+ private left;
130
+ private reconnecting;
131
+ /** Connects, authenticates and joins. Existing publishers are subscribed to automatically unless
132
+ * {@link JoinOptions.autoSubscribe} is false. If the connection later drops, the room is rejoined
133
+ * automatically (see the reconnecting/reconnected events). */
134
+ static join(options: JoinOptions): Promise<XmsRoom>;
135
+ private constructor();
136
+ /** This client's participantId; a new one after each rejoin. */
137
+ get localParticipantId(): string;
138
+ /** Other participants currently in the room. */
139
+ get participants(): RemoteParticipant[];
140
+ on<E extends keyof RoomEvents>(event: E, handler: Handler<E>): () => void;
141
+ /**
142
+ * Publishes the stream's tracks. Call again to add a track later (e.g. turn the camera on after
143
+ * joining audio-only): a track whose kind is already published replaces that one in place, a
144
+ * new kind is added and the publish transport is renegotiated.
145
+ */
146
+ publish(stream: MediaStream, options?: PublishOptions): Promise<void>;
147
+ private publishTracks;
148
+ /** Stops sending one kind of track (e.g. turn the camera off for good, freeing its bandwidth);
149
+ * other participants see a publisherUpdated without it. Use {@link setMuted} for a quick toggle. */
150
+ unpublishTrack(kind: 'audio' | 'video'): Promise<void>;
151
+ /** Mutes/unmutes a published track: stops its media locally and tells the room (trackMuted). */
152
+ setMuted(kind: 'audio' | 'video', muted: boolean): Promise<void>;
153
+ /** Replaces the outgoing track of that kind without renegotiating (e.g. camera <-> screen). */
154
+ replaceTrack(kind: 'audio' | 'video', track: MediaStreamTrack): Promise<void>;
155
+ /** Stops publishing entirely (stays in the room). */
156
+ unpublish(): Promise<void>;
157
+ private ensurePublisherPc;
158
+ private negotiatePublisher;
159
+ /**
160
+ * Subscribes to a publisher (all its tracks unless {@link SubscribeOptions.trackIds} narrows it).
161
+ * Calling again for the same publisher renegotiates that subscription to the new track set.
162
+ */
163
+ subscribe(participantId: string, options?: SubscribeOptions): Promise<void>;
164
+ /** Switches which simulcast layer (a TrackInfo.rids entry) of a subscribed track is received. */
165
+ setLayer(participantId: string, trackId: string, rid: string): Promise<void>;
166
+ unsubscribe(participantId: string): Promise<void>;
167
+ private createSubscription;
168
+ /** After a renegotiation that dropped tracks, their receivers have ended: report them. */
169
+ private sweepEndedTracks;
170
+ private closeSubscription;
171
+ sendChat(text: string): Promise<void>;
172
+ /** Sends app data (reactions, raise-hand, cursors, ...) to everyone else in the room, or only to
173
+ * `options.to`. `type` is your own label (1-64 chars); `payload` any JSON, at most 16 KB. Not
174
+ * echoed back to you; at most 50 per second. */
175
+ sendData(type: string, payload: unknown, options?: {
176
+ to?: string[];
177
+ }): Promise<void>;
178
+ /** Leaves the room and releases every transport. Local media tracks are left to the caller. */
179
+ leave(): Promise<void>;
180
+ /** The underlying PeerConnections, for diagnostics (getStats) and tests. */
181
+ peerConnections(): {
182
+ publisher: RTCPeerConnection | null;
183
+ subscribers: Record<string, RTCPeerConnection>;
184
+ };
185
+ /** Takes in a room.join result: the room's participants and publishers, and the subscriptions to
186
+ * set up. On a rejoin, reports how the room changed while we were away instead of a fresh list. */
187
+ private applyJoin;
188
+ private reconnectIfFailed;
189
+ /** Drops every transport and the signaling connection, then rejoins with backoff. */
190
+ private reconnect;
191
+ private rejoin;
192
+ private connectAndJoinRefreshingToken;
193
+ /** Publishes the tracks we had published before the rejoin (still live ones), mute state included. */
194
+ private republish;
195
+ private bindSignalingEvents;
196
+ private upsertParticipant;
197
+ private enqueue;
198
+ private closePeerConnection;
199
+ private emit;
200
+ }
201
+ export {};