@strevokit/meeting-sdk 0.0.0-stage → 0.8.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/CHANGELOG.md +96 -0
- package/LICENSE +215 -0
- package/README.md +173 -2
- package/dist/index.d.ts +249 -0
- package/dist/index.js +3935 -0
- package/dist/index.js.map +7 -0
- package/docs/api-reference.md +361 -0
- package/docs/backend-api.md +370 -0
- package/docs/examples/backend-integration.md +103 -0
- package/docs/examples/react.tsx +144 -0
- package/docs/examples/vanilla.html +101 -0
- package/package.json +62 -4
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/** Why the engine closed. */
|
|
2
|
+
export declare type CloseReason = "left" | "meeting_ended" | "session_replaced" | "connection_lost" | "join_failed" | "error";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Engine lifecycle state. `closed` is terminal: create a new engine to join again.
|
|
6
|
+
*
|
|
7
|
+
* After a recoverable meeting-service interruption while `joined`, the engine moves to `reconnecting`
|
|
8
|
+
* and attempts automatic recovery. Success returns to `joined` (same self identity; `joined` is not
|
|
9
|
+
* re-emitted). Exhaustion or hard failure moves to `closed` with `connection_lost`. Deliberate leave,
|
|
10
|
+
* meeting ended, and session replaced cancel recovery and close accordingly.
|
|
11
|
+
*/
|
|
12
|
+
export declare type ConnectionState = "idle" | "connecting" | "joining" | "joined" | "reconnecting" | "leaving" | "closed";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a meeting engine for one participant. Pass the join token your backend issued and the realtime
|
|
16
|
+
* service URL, then call `join()`.
|
|
17
|
+
*
|
|
18
|
+
* @throws TypeError when `realtimeUrl` or `joinTimeoutMs` is malformed.
|
|
19
|
+
* @throws MeetingError `join_token_invalid` when the token is not a valid join token, or
|
|
20
|
+
* `unsupported_environment` when the browser has no WebSocket support.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createMeetingEngine(options: MeetingEngineOptions): MeetingEngine;
|
|
23
|
+
|
|
24
|
+
/** Local captures available for rendering, such as a self-preview. `null` when that capture is off. */
|
|
25
|
+
export declare interface LocalMedia {
|
|
26
|
+
readonly camera: MediaStream | null;
|
|
27
|
+
readonly microphone: MediaStream | null;
|
|
28
|
+
readonly screen: MediaStream | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Status of the audio and video connection to another participant. */
|
|
32
|
+
export declare type MediaConnectionStatus = "connecting" | "connected" | "interrupted" | "failed";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Which device to use for {@link MeetingEngine.enableCamera} or {@link MeetingEngine.unmute}. Omit `deviceId` to use
|
|
36
|
+
* the browser's default device.
|
|
37
|
+
*/
|
|
38
|
+
export declare interface MediaDeviceOptions {
|
|
39
|
+
/** A `deviceId` from `navigator.mediaDevices.enumerateDevices()`. */
|
|
40
|
+
readonly deviceId?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** A kind of local or remote media. */
|
|
44
|
+
export declare type MediaKind = "camera" | "microphone" | "screen";
|
|
45
|
+
|
|
46
|
+
/** `true` means on: camera on, microphone unmuted, screen being shared. */
|
|
47
|
+
export declare interface MediaState {
|
|
48
|
+
readonly camera: boolean;
|
|
49
|
+
readonly microphone: boolean;
|
|
50
|
+
readonly screen: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** A meeting session for one participant. One engine joins at most once. */
|
|
54
|
+
export declare interface MeetingEngine {
|
|
55
|
+
/** Current lifecycle state. */
|
|
56
|
+
readonly state: ConnectionState;
|
|
57
|
+
/** Set once `joined` fires; `null` before. */
|
|
58
|
+
readonly self: SelfParticipant | null;
|
|
59
|
+
/** Other participants currently present (never includes self). */
|
|
60
|
+
readonly participants: readonly Participant[];
|
|
61
|
+
/** Current local media state. */
|
|
62
|
+
readonly localMediaState: MediaState;
|
|
63
|
+
/** Current local captures, for rendering. */
|
|
64
|
+
readonly localMedia: LocalMedia;
|
|
65
|
+
/** Media currently received from a participant. All fields are `null` when nothing is available. */
|
|
66
|
+
remoteMedia(participantId: string): RemoteMedia;
|
|
67
|
+
/** Status of the audio and video connection to a participant, or `null` when there is none. */
|
|
68
|
+
mediaConnectionStatus(participantId: string): MediaConnectionStatus | null;
|
|
69
|
+
/** Connect and join the meeting. Resolves once admitted and the participant list is known. */
|
|
70
|
+
join(): Promise<void>;
|
|
71
|
+
/** Leave the meeting and release every device. Never rejects. */
|
|
72
|
+
leave(): Promise<void>;
|
|
73
|
+
/** End the meeting for everyone. Only hosts may end a meeting. Resolves once the meeting has ended. */
|
|
74
|
+
endMeeting(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Start the camera. With `options.deviceId`, use that camera; when the camera is already on with another device,
|
|
77
|
+
* switch to it without turning the camera off. Rejects with `device_not_found` when the device is missing, leaving
|
|
78
|
+
* the current camera running.
|
|
79
|
+
*/
|
|
80
|
+
enableCamera(options?: MediaDeviceOptions): Promise<void>;
|
|
81
|
+
/** Stop the camera and release it. */
|
|
82
|
+
disableCamera(): Promise<void>;
|
|
83
|
+
/** Mute the microphone. */
|
|
84
|
+
mute(): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Unmute the microphone, capturing it on first use. With `options.deviceId`, use that microphone; when it is already
|
|
87
|
+
* unmuted with another device, switch to it without muting. Rejects with `device_not_found` when the device is
|
|
88
|
+
* missing, leaving the current microphone running.
|
|
89
|
+
*/
|
|
90
|
+
unmute(options?: MediaDeviceOptions): Promise<void>;
|
|
91
|
+
/** Start sharing the screen. Only hosts may share. */
|
|
92
|
+
startScreenShare(): Promise<void>;
|
|
93
|
+
/** Stop sharing the screen. */
|
|
94
|
+
stopScreenShare(): Promise<void>;
|
|
95
|
+
/** Subscribe to one event type. Returns an unsubscribe function. */
|
|
96
|
+
on<K extends MeetingEventType>(type: K, listener: MeetingEventListener<K>): () => void;
|
|
97
|
+
/** Release everything immediately: devices, connection, listeners. Emits nothing. Idempotent. */
|
|
98
|
+
dispose(): void;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Options for {@link createMeetingEngine}. */
|
|
102
|
+
export declare interface MeetingEngineOptions {
|
|
103
|
+
/** Join token issued by your backend for this participant. Kept in memory only and never logged. */
|
|
104
|
+
token: string;
|
|
105
|
+
/**
|
|
106
|
+
* Realtime service base URL, for example `wss://realtime.example.com`. `ws://` is accepted only for
|
|
107
|
+
* `localhost` and `127.0.0.1`. No path, query, or fragment.
|
|
108
|
+
*/
|
|
109
|
+
realtimeUrl: string;
|
|
110
|
+
/** Milliseconds to wait for admission before `join()` rejects with `join_timeout`. Default 15000, range 1000–60000. */
|
|
111
|
+
joinTimeoutMs?: number;
|
|
112
|
+
/** Optional diagnostics sink. The SDK never passes the join token or raw exception text to it. */
|
|
113
|
+
logger?: MeetingLogger;
|
|
114
|
+
/**
|
|
115
|
+
* Optional. Called when a new meeting-service connection needs a join token and the in-memory token
|
|
116
|
+
* cannot be used. Must resolve to a server-issued join token for the same participant. Reject to fail
|
|
117
|
+
* recovery. The returned token is kept in memory only and never logged.
|
|
118
|
+
*/
|
|
119
|
+
getJoinToken?: () => Promise<string>;
|
|
120
|
+
/**
|
|
121
|
+
* Optional. Continuous unsuccessful recovery budget in milliseconds. Default 120000.
|
|
122
|
+
* Values outside 1000–600000 are clamped to that range.
|
|
123
|
+
*/
|
|
124
|
+
reconnectWindowMs?: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* The single error type raised by the SDK. `message` is a short English sentence that is safe to show to users;
|
|
129
|
+
* branch on `code` rather than on `message`.
|
|
130
|
+
*/
|
|
131
|
+
export declare class MeetingError extends Error {
|
|
132
|
+
readonly name: "MeetingError";
|
|
133
|
+
/** Stable machine-readable code. */
|
|
134
|
+
readonly code: MeetingErrorCode;
|
|
135
|
+
/** True when retrying the same action later (with a fresh token for join errors) may succeed. */
|
|
136
|
+
readonly retryable: boolean;
|
|
137
|
+
constructor(code: MeetingErrorCode);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Every code a {@link MeetingError} can carry. Codes are stable strings; new codes may be added in minor
|
|
142
|
+
* versions, so handle unknown codes generically.
|
|
143
|
+
*/
|
|
144
|
+
export declare type MeetingErrorCode = "join_token_invalid" | "join_token_expired" | "origin_not_allowed" | "connection_failed" | "join_timeout" | "join_cancelled" | "connection_lost" | "session_replaced" | "service_unavailable" | "rate_limited" | "meeting_ended" | "protocol_error" | "already_joined" | "engine_closed" | "not_joined" | "not_permitted" | "permission_denied" | "device_not_found" | "device_unavailable" | "screen_share_cancelled" | "unsupported_environment" | "media_connection_failed" | "media_participant_limit";
|
|
145
|
+
|
|
146
|
+
/** Listener for one event type. */
|
|
147
|
+
export declare type MeetingEventListener<K extends MeetingEventType> = (event: MeetingEventMap[K]) => void;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Payload of every event, keyed by event type. New event types may be added in minor versions, so do not
|
|
151
|
+
* treat this map as closed.
|
|
152
|
+
*/
|
|
153
|
+
export declare interface MeetingEventMap {
|
|
154
|
+
state_changed: {
|
|
155
|
+
readonly state: ConnectionState;
|
|
156
|
+
readonly previous: ConnectionState;
|
|
157
|
+
};
|
|
158
|
+
joined: {
|
|
159
|
+
readonly self: SelfParticipant;
|
|
160
|
+
readonly participants: readonly Participant[];
|
|
161
|
+
};
|
|
162
|
+
participant_joined: {
|
|
163
|
+
readonly participant: Participant;
|
|
164
|
+
};
|
|
165
|
+
participant_left: {
|
|
166
|
+
readonly participantId: string;
|
|
167
|
+
readonly reason: ParticipantLeftReason;
|
|
168
|
+
};
|
|
169
|
+
participant_reconnected: {
|
|
170
|
+
readonly participantId: string;
|
|
171
|
+
};
|
|
172
|
+
participant_media_changed: {
|
|
173
|
+
readonly participantId: string;
|
|
174
|
+
readonly kind: MediaKind;
|
|
175
|
+
readonly enabled: boolean;
|
|
176
|
+
};
|
|
177
|
+
local_media_changed: {
|
|
178
|
+
readonly kind: MediaKind;
|
|
179
|
+
readonly enabled: boolean;
|
|
180
|
+
readonly stream: MediaStream | null;
|
|
181
|
+
};
|
|
182
|
+
/** Media from another participant became available (`stream`) or stopped being available (`null`). */
|
|
183
|
+
remote_media_changed: {
|
|
184
|
+
readonly participantId: string;
|
|
185
|
+
readonly kind: MediaKind;
|
|
186
|
+
readonly stream: MediaStream | null;
|
|
187
|
+
};
|
|
188
|
+
/** The audio and video connection to another participant changed. `null`: there is no connection any more. */
|
|
189
|
+
media_connection_changed: {
|
|
190
|
+
readonly participantId: string;
|
|
191
|
+
readonly status: MediaConnectionStatus | null;
|
|
192
|
+
};
|
|
193
|
+
error: {
|
|
194
|
+
readonly error: MeetingError;
|
|
195
|
+
};
|
|
196
|
+
closed: {
|
|
197
|
+
readonly reason: CloseReason;
|
|
198
|
+
readonly error?: MeetingError;
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Name of an engine event. */
|
|
203
|
+
export declare type MeetingEventType = keyof MeetingEventMap;
|
|
204
|
+
|
|
205
|
+
/** Optional diagnostics sink. Every method is optional. */
|
|
206
|
+
export declare interface MeetingLogger {
|
|
207
|
+
debug?(message: string, fields?: Readonly<Record<string, string | number | boolean>>): void;
|
|
208
|
+
info?(message: string, fields?: Readonly<Record<string, string | number | boolean>>): void;
|
|
209
|
+
warn?(message: string, fields?: Readonly<Record<string, string | number | boolean>>): void;
|
|
210
|
+
error?(message: string, fields?: Readonly<Record<string, string | number | boolean>>): void;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Another participant in the meeting. */
|
|
214
|
+
export declare interface Participant {
|
|
215
|
+
/** Opaque participant ID. */
|
|
216
|
+
readonly id: string;
|
|
217
|
+
readonly role: ParticipantRole;
|
|
218
|
+
readonly displayName?: string;
|
|
219
|
+
readonly media: MediaState;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Why another participant left. Unknown platform reasons are reported as `"other"`. */
|
|
223
|
+
export declare type ParticipantLeftReason = "left" | "disconnected" | "removed" | "meeting_ended" | "other";
|
|
224
|
+
|
|
225
|
+
/** Role assigned by the platform when the join token was issued. */
|
|
226
|
+
export declare type ParticipantRole = "host" | "participant";
|
|
227
|
+
|
|
228
|
+
/** Media received from another participant, for rendering. `null` when that media is not available. */
|
|
229
|
+
export declare interface RemoteMedia {
|
|
230
|
+
readonly camera: MediaStream | null;
|
|
231
|
+
readonly microphone: MediaStream | null;
|
|
232
|
+
/**
|
|
233
|
+
* Live display stream while the remote participant is sharing their screen and peer media has
|
|
234
|
+
* attached it; otherwise `null`. May be non-null in ordinary one-to-one meetings.
|
|
235
|
+
*/
|
|
236
|
+
readonly screen: MediaStream | null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** The participant using this engine. */
|
|
240
|
+
export declare interface SelfParticipant {
|
|
241
|
+
/** Opaque participant ID. */
|
|
242
|
+
readonly id: string;
|
|
243
|
+
readonly role: ParticipantRole;
|
|
244
|
+
readonly displayName?: string;
|
|
245
|
+
/** ISO-8601 UTC timestamp from the platform. */
|
|
246
|
+
readonly joinedAt: string;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export { }
|